[Zope-Checkins] CVS: Zope/inst - zctl.in:1.1.2.6

Jens Vagelpohl jens@zope.com
Sat, 7 Sep 2002 13:17:34 -0400


Update of /cvs-repository/Zope/inst
In directory cvs.zope.org:/tmp/cvs-serv27149/inst

Modified Files:
      Tag: chrism-install-branch
	zctl.in 
Log Message:
- add new directives to zctl, "start_zeo" and "stop_zeo", that can be used to
  stop and start the ZEO server in a ZEO setup

- start will now check to see if this is a ZEO setup and then start the ZEO
  server if it is not running

- _checkService has been expanded to be able to check for a service on a 
  unix domain socket if people have their ZEOs listen on those.

there is some big nastiness in trying to determine the location of the "start"
script for ZEO and then in invoking it. however, i found this preferable to
all previous zctls i have seen which had paths hardcoded in the zctl script 
itself. adding specific directives for the zeo software location in zope.conf 
might improve this.

none of this has been tested on windoze.



=== Zope/inst/zctl.in 1.1.2.5 => 1.1.2.6 ===
--- Zope/inst/zctl.in:1.1.2.5	Tue Sep  3 03:12:24 2002
+++ Zope/inst/zctl.in	Sat Sep  7 13:17:34 2002
@@ -58,6 +58,8 @@
     help [<command>]
     start
     stop
+    start_zeo
+    stop_zeo
     restart
     logopenclose
     status
@@ -90,13 +92,21 @@
 
             All options are passed to the zope.py command line.
         """
-        lock_status = self.lockFile()
-        if lock_status:
-            self._report('Cannot start Zope.  Another Zope instance has locked'
-                         ' the "%s" file.  Use "stop" to stop it.' % 
-                         self._getPidfileName())
-            self._report()
-            return
+        if self._getDirective('use_zeo_server'):
+            # Is the ZEO server up? start it if not
+            zeo_host, zeo_port, zeo_socket = self._getZEOConfig()
+            if not self._checkService(zeo_host, zeo_port, zeo_socket):
+                self.start_zeo(arg)
+
+        else:
+            lock_status = self.lockFile()
+            if lock_status:
+                self._report('Cannot start Zope.  Another Zope instance has locked'
+                             ' the "%s" file.  Use "stop" to stop it.' % 
+                             self._getPidfileName())
+                self._report()
+                return
+
         zope_py = os.path.join(self._getZopeHome(), 'zope.py')
         cmdline = '"%s" "%s" %s %s' % (
             sys.executable,
@@ -106,6 +116,110 @@
             )
         self._doSystem('Starting Zope', cmdline)
 
+    def start_zeo(self, arg):
+        """
+            Start the ZEO server.
+
+            Syntax: start_zeo [options]
+
+            All options are passed to the ZEO start.py script.
+        """
+        zeo_host, zeo_port, zeo_socket = self._getZEOConfig()
+        my_args = []
+
+        pp = self._getDirective('python_path')
+        if pp:
+            paths = pp.split(':')
+
+            for path in paths:
+                sys.path.append(path)
+
+        try:
+            import ZEO
+
+            if self._checkService(zeo_host, zeo_port, zeo_socket):
+                self._report('ZEO server already running.')
+                self._report()
+                return
+
+            # ZEO not running. gotta start.
+            initpy_path = os.path.abspath(ZEO.__file__)
+            zeo_path = os.path.split(initpy_path)[0]
+            start_py = os.path.join(zeo_path, 'start.py')
+
+            if zeo_port and not zeo_socket:
+                my_args.append('-h %s' % zeo_host)
+                my_args.append('-p %s' % str(zeo_port))
+                msg = 'Starting ZEO on %s port %s' % (zeo_host, str(zeo_port))
+            elif zeo_socket and not zeo_port:
+                my_args.append('-U %s' % zeo_socket)
+                msg = 'Starting ZEO on socket %s' % zeo_socket
+            else:
+                self._report('ZEO misconfiguration. Please check your'
+                             ' zope.conf configuration file.')
+                self._report()
+                return
+
+            cmdline = 'PYTHONPATH="%s"; "%s" "%s" %s %s &' % (
+                                           ':'.join(sys.path)
+                                          , sys.executable
+                                          , start_py
+                                          , ' '.join(my_args)
+                                          , arg
+                                          )
+
+            self._doSystem(msg, cmdline)
+
+            count = 0
+            while not self._checkService(zeo_host, zeo_port, zeo_socket):
+                count = count + 1
+                if count > 180:
+                    self._report('ZEO connection failure')
+                    self._report()
+                    return
+
+                self._report('Waiting for ZEO server to start... %d' % count)
+                time.sleep(1)
+
+            self._report('ZEO server ready')
+
+        except ImportError:
+            self._report('Cannot find the ZEO installation. Please make sure'
+                         ' that ZEO is installed and in your PYTHONPATH.')
+            return
+
+    def stop_zeo(self, arg):
+        """
+            Stop the ZEO server
+
+            Syntax: zeo_stop
+        """
+        client_home = self._getClientHome()
+        zeo_pidfile = os.path.join(client_home, 'ZEO_SERVER.pid')
+        try:
+            pids = get_pids(zeo_pidfile)
+            pid = pids[-1]
+            status = kill(pid, signal.SIGTERM)
+
+            if status:
+                self._report('Could not stop ZEO (maybe already stopped or '
+                             'pending start?)')
+            else:
+                self._report('ZEO stopped successfully')
+
+            zeo_host, zeo_port, zeo_socket = self._getZEOConfig()
+            if zeo_socket:
+                try:
+                    os.remove(zeo_socket)
+                except OSError:
+                    pass
+
+            return status
+
+        except IOError:
+            self._report('Pid file %s could not be found' % zeo_pidfile)
+
+
     def restart( self, arg ):
         """
             Restart the Zope appserver.
@@ -385,13 +499,19 @@
         status = os.system( cmdline )
         return status
 
-    def _checkService( self, host, port ):
+    def _checkService( self, host, port, socket_path=None ):
         """
             Return 1 if server is found at (host, port), 0 otherwise.
         """
-        address = ( host, int(port) )
         import socket
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+        if socket_path is None:
+            address = ( host, int(port) )
+            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        else:
+            address = socket_path
+            s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+
         try:
             s.connect( address )
         except socket.error:
@@ -464,6 +584,21 @@
             return 1
         return 0
 
+    def _getZEOConfig(self):
+        gd = self._getDirective
+        zeo_host = gd('zeo_storage_server_hostname')
+        zeo_path_or_port = gd('zeo_storage_server_path_or_port')
+
+        try:
+            zeo_port = int(zeo_path_or_port)
+            zeo_socket = None
+        except:
+            zeo_port = None
+            zeo_socket = zeo_path_or_port
+
+        return zeo_host, zeo_port, zeo_socket
+
+
 def normalizeDocstring( bound_method ):
 
     doc = bound_method.__doc__
@@ -603,6 +738,8 @@
     
     do_start         = _MAKEDO( 'start' )
     do_start         = _MAKEDO( 'start' )
+    do_zeo_start     = _MAKEDO( 'zeo_start' )
+    do_zeo_stop      = _MAKEDO( 'zeo_stop' )
     do_restart       = _MAKEDO( 'restart' )
     do_logopenclose  = _MAKEDO( 'logopenclose' )
     do_stop          = _MAKEDO( 'stop' )