SVN: zdaemon/trunk/ - If the run directory does not exist it will be created. This allow to use

Christian Zagrodnick <[email protected]>
Newsgroups gmane.comp.web.zope.zope3.cvs
Message-ID <20090128153632.B419B9418B__11121.5436635122$1233157085$gmane$org@cvs.zope.org>
Log message for revision 95330:
  - If the run directory does not exist it will be created. This allow to use
    `/var/run/mydaemon` as run directory when /var/run is a tmpfs (LP #318118).
  
  
  

Changed:
  U   zdaemon/trunk/CHANGES.txt
  U   zdaemon/trunk/src/zdaemon/tests/testzdoptions.py
  U   zdaemon/trunk/src/zdaemon/tests/testzdrun.py
  U   zdaemon/trunk/src/zdaemon/zdctl.py
  U   zdaemon/trunk/src/zdaemon/zdoptions.py

-=-
Modified: zdaemon/trunk/CHANGES.txt
===================================================================
--- zdaemon/trunk/CHANGES.txt	2009-01-28 15:33:11 UTC (rev 95329)
+++ zdaemon/trunk/CHANGES.txt	2009-01-28 15:36:32 UTC (rev 95330)
@@ -6,6 +6,9 @@
 
 - Added support to bootstrap on Jython.
 
+- If the run directory does not exist it will be created. This allow to use
+  `/var/run/mydaemon` as run directory when /var/run is a tmpfs (LP #318118).
+
 Bugs Fixed
 ----------
 

Modified: zdaemon/trunk/src/zdaemon/tests/testzdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/testzdoptions.py	2009-01-28 15:33:11 UTC (rev 95329)
+++ zdaemon/trunk/src/zdaemon/tests/testzdoptions.py	2009-01-28 15:36:32 UTC (rev 95330)
@@ -17,12 +17,14 @@
 import os
 import sys
 import tempfile
+import shutil
 import unittest
 from StringIO import StringIO
 
 import ZConfig
 import zdaemon
-from zdaemon.zdoptions import ZDOptions
+from zdaemon.zdoptions import (
+    ZDOptions, RunnerOptions, existing_parent_directory)
 
 class ZDOptionsTestBase(unittest.TestCase):
 
@@ -320,11 +322,53 @@
                              ["-Xunknown=foo"])
 
 
+
+class TestRunnerDirectory(ZDOptionsTestBase):
+
+    OptionsClass = RunnerOptions
+
+    def setUp(self):
+        super(TestRunnerDirectory, self).setUp()
+        # Create temporary directory to work in
+        self.root = tempfile.mkdtemp()
+
+    def tearDown(self):
+        shutil.rmtree(self.root)
+        super(TestRunnerDirectory, self).tearDown()
+
+    def test_not_existing_directory(self):
+        options = self.OptionsClass()
+        path = os.path.join(self.root, 'does-not-exist', 'really-not')
+        self.check_exit_code(options, ["-z", path])
+
+    def test_existing_director(self):
+        options = self.OptionsClass()
+        options.realize(["-z", self.root])
+
+    def test_parent_is_created(self):
+        options = self.OptionsClass()
+        path = os.path.join(self.root, 'will-be-created')
+        options.realize(["-z", path])
+        self.assertEquals(path, options.directory)
+        # Directory will be created when zdaemon runs, not when the
+        # configuration is read
+        self.assertFalse(os.path.exists(path))
+
+    def test_existing_parent_directory(self):
+        self.assertTrue(existing_parent_directory(self.root))
+        self.assertTrue(existing_parent_directory(
+            os.path.join(self.root, 'not-there')))
+        self.assertRaises(
+            ValueError, existing_parent_directory,
+            os.path.join(self.root, 'not-there', 'this-also-not'))
+
+
 def test_suite():
     suite = unittest.TestSuite()
     for cls in [TestBasicFunctionality,
                 TestZDOptionsEnvironment,
-                TestCommandLineOverrides]:
+                TestCommandLineOverrides,
+                TestRunnerDirectory]:
         suite.addTest(unittest.makeSuite(cls))
     return suite
 

Modified: zdaemon/trunk/src/zdaemon/tests/testzdrun.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/testzdrun.py	2009-01-28 15:33:11 UTC (rev 95329)
+++ zdaemon/trunk/src/zdaemon/tests/testzdrun.py	2009-01-28 15:36:32 UTC (rev 95330)
@@ -308,6 +308,46 @@
             if os.path.exists(path):
                 os.remove(path)
 
+
+class TestRunnerDirectory(unittest.TestCase):
+
+    def setUp(self):
+        super(TestRunnerDirectory, self).setUp()
+        self.root = tempfile.mkdtemp()
+        self.save_stdout = sys.stdout
+        self.save_stderr = sys.stderr
+        sys.stdout = StringIO()
+        sys.stderr = StringIO()
+
+    def tearDown(self):
+        shutil.rmtree(self.root)
+        sys.stdout = self.save_stdout
+        sys.stderr = self.save_stderr
+        super(TestRunnerDirectory, self).tearDown()
+
+    def run_ctl(self, path):
+        true_cmd = "/bin/true"
+        if not os.path.exists(true_cmd):
+            true_cmd = "/usr/bin/true"  # Mac OS X
+        options = zdctl.ZDCtlOptions()
+        options.realize(['-z', path, '-p', 'sleep 1', 'fg'])
+        self.expect = 'sleep 1\n'
+        proc = zdctl.ZDCmd(options)
+        proc.onecmd(" ".join(options.args))
+
+    def testCtlRunDirectoryCreation(self):
+        path = os.path.join(self.root, 'rundir')
+        self.run_ctl(path)
+        self.assert_(os.path.exists(path))
+
+    def testCtlRunDirectoryCreationOnlyOne(self):
+        path = os.path.join(self.root, 'rundir', 'not-created')
+        self.run_ctl(path)
+        self.assertFalse(os.path.exists(path))
+        self.assertTrue(sys.stdout.getvalue().startswith(
+            'Error: invalid value for -z'))
+
+
 def send_action(action, sockname):
     """Send an action to the zdrun server and return the response.
 
@@ -338,6 +378,7 @@
     suite = unittest.TestSuite()
     if os.name == "posix":
         suite.addTest(unittest.makeSuite(ZDaemonTests))
+        suite.addTest(unittest.makeSuite(TestRunnerDirectory))
     return suite
 
 if __name__ == '__main__':

Modified: zdaemon/trunk/src/zdaemon/zdctl.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdctl.py	2009-01-28 15:33:11 UTC (rev 95329)
+++ zdaemon/trunk/src/zdaemon/zdctl.py	2009-01-28 15:36:32 UTC (rev 95330)
@@ -144,8 +144,20 @@
                     for k, v in env.items():
                         os.environ[k] = v
 
+        self.create_rundir()
         self.set_uid()
 
+    def create_rundir(self):
+        if self.options.directory is None:
+            return
+        if os.path.isdir(self.options.directory):
+            return
+        os.mkdir(self.options.directory)
+        uid = os.geteuid()
+        if uid == 0 and uid != self.options.uid:
+            # Change owner of directory to target
+            os.chown(self.options.uid, self.options.gid)
+
     def set_uid(self):
         if self.options.uid is None:
             return

Modified: zdaemon/trunk/src/zdaemon/zdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdoptions.py	2009-01-28 15:33:11 UTC (rev 95329)
+++ zdaemon/trunk/src/zdaemon/zdoptions.py	2009-01-28 15:36:32 UTC (rev 95330)
@@ -362,7 +362,7 @@
         self.add("umask", "runner.umask", "m:", "umask=", octal_type,
                  default=022)
         self.add("directory", "runner.directory", "z:", "directory=",
-                 ZConfig.datatypes.existing_directory)
+                 existing_parent_directory)
         self.add("hang_around", "runner.hang_around", default=0)
 
     def realize(self, *args, **kwds):
@@ -401,6 +401,14 @@
     return int(arg, 8)
 
 
+def existing_parent_directory(arg):
+    path = os.path.expanduser(arg)
+    parent, tail = os.path.split(path)
+    if os.path.isdir(parent):
+        return path
+    raise ValueError('%s is not an existing directory' % arg)
+
+
 def _test():
     # Stupid test program
     z = ZDOptions()
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.