[Zope-Checkins] CVS: ZODB3/zdaemon - sample.conf:1.3 schema.xml:1.4 zdctl.py:1.20 zdoptions.py:1.8 zdrun.py:1.5

Guido van Rossum guido@python.org
Tue, 21 Jan 2003 13:20:11 -0500


Update of /cvs-repository/ZODB3/zdaemon
In directory cvs.zope.org:/tmp/cvs-serv8707

Modified Files:
	sample.conf schema.xml zdctl.py zdoptions.py zdrun.py 
Log Message:
Make zdrun and zdctl share more configuration.

zrdun no longer has a "client" mode; you have to do that using zdctl.

This isn't completely cooked yet; I have disabled some tests that were
using zdrun's client mode until I find time to figure out how to
rewrite those tests.


=== ZODB3/zdaemon/sample.conf 1.2 => 1.3 ===
--- ZODB3/zdaemon/sample.conf:1.2	Mon Jan 20 11:21:02 2003
+++ ZODB3/zdaemon/sample.conf	Tue Jan 21 13:19:38 2003
@@ -1,11 +1,9 @@
 # Sample config file for zdctl.py and zdrun.py (which share a schema).
 
-<zdctl>
-  # This is a pure example
-  program sleep 100
-</zdctl>
-
-<zdrun>
+<runner>
+  # Harmless example
+  program       sleep 100
+  # Repeat the defaults
   backoff-limit 10
   daemon	True
   forever	True
@@ -13,4 +11,4 @@
   exit-codes	0,2
   # user has no default
   directory	/
-</zdrun>
+</runner>


=== ZODB3/zdaemon/schema.xml 1.3 => 1.4 ===
--- ZODB3/zdaemon/schema.xml:1.3	Mon Jan 20 11:21:02 2003
+++ ZODB3/zdaemon/schema.xml	Tue Jan 21 13:19:38 2003
@@ -4,11 +4,10 @@
     Schema for zdctl.py and zdrun.py.
   </description>
 
-  <sectiontype name="zdctl">
+  <sectiontype name="runner">
+    <key name="python" datatype="existing-path" />
+    <key name="zdrun" datatype="existing-path" />
     <key name="program" datatype="string-list" required="yes" />
-  </sectiontype>
-
-  <sectiontype name="zdrun">
     <key name="backoff-limit" datatype="integer" default="10" />
     <key name="daemon" datatype="boolean" default="False" />
     <key name="forever" datatype="boolean" default="False" />
@@ -19,7 +18,6 @@
     <key name="directory" datatype="existing-directory" default="/" />
   </sectiontype>
 
-  <section name="*" type="zdctl" attribute="zdctl" required="yes" />
-  <section name="*" type="zdrun" attribute="zdrun" required="yes" />
+  <section name="*" type="runner" attribute="runner" required="yes" />
 
 </schema>


=== ZODB3/zdaemon/zdctl.py 1.19 => 1.20 ===
--- ZODB3/zdaemon/zdctl.py:1.19	Mon Jan 20 11:32:41 2003
+++ ZODB3/zdaemon/zdctl.py	Tue Jan 21 13:19:38 2003
@@ -14,12 +14,21 @@
 ##############################################################################
 """zdctl -- control an application run by zdaemon.
 
-Usage: python zdctl.py [-C URL] [-h] [-p PROGRAM] [action [arguments]]
+Usage: python zdctl.py [-C URL] [-h] [-p PROGRAM]
+       [zdrun-options] [action [arguments]]
 
 Options:
 -C/--configuration URL -- configuration file or URL
 -h/--help -- print usage message and exit
+-b/--backoff-limit SECONDS -- set backoff limit to SECONDS (default 10)
+-d/--daemon-- run as a proper daemon; fork a subprocess, close files etc.
+-f/--forever -- run forever (by default, exit when backoff limit is exceeded)
+-h/--help -- print this usage message and exit
 -p/--program PROGRAM -- the program to run
+-s/--socket-name SOCKET -- Unix socket name for client (default "zdsock")
+-u/--user USER -- run as this user (or numeric uid)
+-x/--exit-codes LIST -- list of fatal exit codes (default "0,2")
+-z/--directory DIRECTORY -- directory to chdir to when using -d (default "/")
 action [arguments] -- see below
 
 Actions are commands like "start", "stop" and "status".  If no action
@@ -45,46 +54,48 @@
 
 if __name__ == "__main__":
     # Add the parent of the script directory to the module search path
-    from os.path import dirname, abspath, normpath
-    sys.path.append(dirname(dirname(normpath(abspath(sys.argv[0])))))
+    # (but only when the script is run from inside the zdaemon package)
+    from os.path import dirname, basename, abspath, normpath
+    scriptdir = dirname(normpath(abspath(sys.argv[0])))
+    if basename(scriptdir).lower() == "zdaemon":
+        sys.path.append(dirname(scriptdir))
 
 import ZConfig
-from zdaemon.zdoptions import ZDOptions
+from zdaemon.zdoptions import RunnerOptions
 
 
 def string_list(arg):
     return arg.split()
 
 
-class ZDCtlOptions(ZDOptions):
+class ZDCtlOptions(RunnerOptions):
 
     positional_args_allowed = 1
 
-    # Where's python?
-    python = sys.executable
-
-    # Where's zdaemon?
-    if __name__ == "__main__":
-        _file = sys.argv[0]
-    else:
-        _file = __file__
-    _file = os.path.normpath(os.path.abspath(_file))
-    _dir = os.path.dirname(_file)
-    zdaemon = os.path.join(_dir, "zdrun.py")
-
-    # Options for zdaemon
-    backofflimit = 10                   # -b SECONDS
-    forever = 0                         # -f
-    sockname = os.path.abspath("zdsock") # -s SOCKET
-    exitcodes = [0, 2]                  # -x LIST
-    user = None                         # -u USER
-    zdirectory = "/"                    # -z DIRECTORY
-
     def __init__(self):
-        ZDOptions.__init__(self)
-        self.add("program", "zdctl.program", "p:", "program=",
+        RunnerOptions.__init__(self)
+        self.add("program", "runner.program", "p:", "program=",
                  handler=string_list,
                  required="no program specified; use -p or -C")
+        self.add("python", "runner.python")
+        self.add("zdrun", "runner.zdrun")
+
+    def realize(self, *args, **kwds):
+        RunnerOptions.realize(self, *args, **kwds)
+
+        # Where's python?
+        if not self.python:
+            self.python = sys.executable
+
+        # Where's zdrun?
+        if not self.zdrun:
+            if __name__ == "__main__":
+                file = sys.argv[0]
+            else:
+                file = __file__
+            file = os.path.normpath(os.path.abspath(file))
+            dir = os.path.dirname(file)
+            self.zdrun = os.path.join(dir, "zdrun.py")
 
 
 class ZDCmd(cmd.Cmd):
@@ -101,7 +112,7 @@
                 s = m.group(1)
                 args = eval(s, {"__builtins__": {}})
                 if args != self.options.program:
-                    print "WARNING! zdaemon is managing a different program!"
+                    print "WARNING! zdrun is managing a different program!"
                     print "our program   =", self.options.program
                     print "daemon's args =", args
 
@@ -109,7 +120,7 @@
         pass # We don't want a blank line to repeat the last command
 
     def send_action(self, action):
-        """Send an action to the zdaemon server and return the response.
+        """Send an action to the zdrun server and return the response.
 
         Return None if the server is not up or any other error happened.
         """
@@ -169,7 +180,7 @@
         if not self.zd_up:
             args = [
                 self.options.python,
-                self.options.zdaemon,
+                self.options.zdrun,
                 "-b", str(self.options.backofflimit),
                 "-d",
                 "-s", self.options.sockname,
@@ -287,7 +298,7 @@
     def show_options(self):
         print "schemafile:  ", repr(self.options.schemafile)
         print "configfile:  ", repr(self.options.configfile)
-        print "zdaemon:     ", repr(self.options.zdaemon)
+        print "zdrun:       ", repr(self.options.zdrun)
         print "program:     ", repr(self.options.program)
         print "backofflimit:", repr(self.options.backofflimit)
         print "forever:     ", repr(self.options.forever)


=== ZODB3/zdaemon/zdoptions.py 1.7 => 1.8 ===
--- ZODB3/zdaemon/zdoptions.py:1.7	Mon Jan 20 11:21:02 2003
+++ ZODB3/zdaemon/zdoptions.py	Tue Jan 21 13:19:38 2003
@@ -273,6 +273,24 @@
         EventLogger.event_logger.logger = logger
 
 
+class RunnerOptions(ZDOptions):
+
+    def __init__(self):
+        ZDOptions.__init__(self)
+        self.add("backofflimit", "runner.backoff_limit",
+                 "b:", "backoff-limit=", int, default=10)
+        self.add("daemon", "runner.daemon", "d", "daemon", flag=1, default=0)
+        self.add("forever", "runner.forever", "f", "forever",
+                 flag=1, default=0)
+        self.add("sockname", "runner.socket_name", "s:", "socket-name=",
+                 ZConfig.datatypes.existing_dirpath, default="zdsock")
+        self.add("exitcodes", "runner.exit_codes", "x:", "exit-codes=",
+                 list_of_ints, default=[0, 2])
+        self.add("user", "runner.user", "u:", "user=")
+        self.add("zdirectory", "runner.directory", "z:", "directory=",
+                 ZConfig.datatypes.existing_directory, default="/")
+
+
 # ZConfig datatype
 
 def list_of_ints(arg):


=== ZODB3/zdaemon/zdrun.py 1.4 => 1.5 ===
--- ZODB3/zdaemon/zdrun.py:1.4	Mon Jan 20 11:32:41 2003
+++ ZODB3/zdaemon/zdrun.py	Tue Jan 21 13:19:38 2003
@@ -15,12 +15,10 @@
 """zrdun -- run an application as a daemon.
 
 Usage: python zrdun.py [zrdun-options] program [program-arguments]
-Or:    python zrdun.py -c [command]
 
 Options:
 -C/--configuration URL -- configuration file or URL
 -b/--backoff-limit SECONDS -- set backoff limit to SECONDS (default 10)
--c/--client -- client mode, to sends a command to the daemon manager
 -d/--daemon-- run as a proper daemon; fork a subprocess, close files etc.
 -f/--forever -- run forever (by default, exit when backoff limit is exceeded)
 -h/--help -- print this usage message and exit
@@ -30,20 +28,6 @@
 -z/--directory DIRECTORY -- directory to chdir to when using -d (default "/")
 program [program-arguments] -- an arbitrary application to run
 
-Client mode options:
-  -s SOCKET -- socket name (a Unix pathname) for client communication
-  [command] -- the command to send to the daemon manager (default "status")
-
-Client commands are:
-  help -- return command help
-  status -- report application status (this is the default command)
-  kill [signal] -- send a signal to the application
-                   (default signal is SIGTERM)
-  start -- start the application if not already running
-  stop -- stop the application if running; daemon manager keeps running
-  restart -- stop followed by start
-  exit -- stop the application and exit
-
 This daemon manager has two purposes: it restarts the application when
 it dies, and (when requested to do so with the -d option) it runs the
 application in the background, detached from the foreground tty
@@ -91,32 +75,28 @@
 
 if __name__ == "__main__":
     # Add the parent of the script directory to the module search path
-    from os.path import dirname, abspath, normpath
-    sys.path.append(dirname(dirname(normpath(abspath(sys.argv[0])))))
+    # (but only when the script is run from inside the zdaemon package)
+    from os.path import dirname, basename, abspath, normpath
+    scriptdir = dirname(normpath(abspath(sys.argv[0])))
+    if basename(scriptdir).lower() == "zdaemon":
+        sys.path.append(dirname(scriptdir))
 
 import ZConfig.datatypes
 import zLOG
-from zdaemon.zdoptions import ZDOptions, list_of_ints
+from zdaemon.zdoptions import RunnerOptions
+
 
-class ZDRunOptions(ZDOptions):
+class ZDRunOptions(RunnerOptions):
 
     positional_args_allowed = 1
+    program = None
 
-    def __init__(self):
-        ZDOptions.__init__(self)
-        self.add("backofflimit", "zdrun.backoff_limit",
-                 "b:", "backoff-limit=", int, default=10)
-        self.add("isclient", None, "c", "client", flag=1, default=0)
-        self.add("daemon", "zdrun.daemon", "d", "daemon", flag=1, default=0)
-        self.add("forever", "zdrun.forever", "f", "forever",
-                 flag=1, default=0)
-        self.add("sockname", "zdrun.socket_name", "s:", "socket-name=",
-                 ZConfig.datatypes.existing_dirpath, default="zdsock")
-        self.add("exitcodes", "zdrun.exit_codes", "x:", "exit-codes=",
-                 list_of_ints, default=[0, 2])
-        self.add("user", "zdrun.user", "u:", "user=")
-        self.add("zdirectory", "zdrun.directory", "z:", "directory=",
-                 ZConfig.datatypes.existing_directory, default="/")
+    def realize(self, *args, **kwds):
+        RunnerOptions.realize(self, *args, **kwds)
+        if self.args:
+            self.program = self.args
+        if not self.program:
+            self.usage("no program specified (use -C or positional args)")
 
 
 class Subprocess:
@@ -224,47 +204,6 @@
         """
         self.pid = 0
 
-class Client:
-
-    """A class representing the control client."""
-
-    def __init__(self, options, args=None):
-        """Constructor.
-
-        Arguments are an ZDRunOptions instance and a list of program
-        arguments representing the command to send to the server.
-        """
-        self.options = options
-        if args is None:
-            args = options.args
-        if not args:
-            self.command = "status"
-        else:
-            self.command = " ".join(args)
-
-    def doit(self):
-        """Send the command to the server and write the results to stdout."""
-        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        try:
-            sock.connect(self.options.sockname)
-        except socket.error, msg:
-            sys.stderr.write("Can't connect to %r: %s\n" %
-                             (self.options.sockname, msg))
-            sys.exit(1)
-        sock.send(self.command + "\n")
-        sock.shutdown(1) # We're not writing any more
-        lastdata = ""
-        while 1:
-            data = sock.recv(1000)
-            if not data:
-                break
-            sys.stdout.write(data)
-            lastdata = data
-        if not lastdata:
-            sys.stderr.write("No response received\n")
-            sys.exit(1)
-        if not lastdata.endswith("\n"):
-            sys.stdout.write("\n")
 
 class Daemonizer:
 
@@ -272,11 +211,7 @@
         self.options = ZDRunOptions()
         self.options.realize(args)
         self.set_uid()
-        if self.options.isclient:
-            clt = Client(self.options)
-            clt.doit()
-        else:
-            self.run()
+        self.run()
 
     def set_uid(self):
         if self.options.user is None: