You are not logged in Log in Join
You are here: Home » Members » klm » ZopeDebugging » Zope/ZEO instance control script » View File

Log in
Name

Password

 

Zope/ZEO instance control script

File details
Size
8 K
File type
text/plain

File contents

#!/home/klm/work/zope/Zope/bin/python
# XXX ^^ Above, put the path to the bin/python of your Zope software home ^^
# -*- python -*-

"""Control Zope and ZEO server if it's configured

Usage:

    %(zctl)s start [confname ...] [--zeo -arg ... [--zope]] -arg ...

    %(zctl)s stop [confname ...]

    %(zctl)s start_zeo

    %(zctl)s stop_zeo

    %(zctl)s status [confname ...]

    %(zctl)s make_cgi [filename]

    %(zctl)s debug

    %(zctl)s test filename

    %(zctl)s do [-i] [-f filename]* commands

The file 'zope.conf' must exist in the INSTANCE_HOME where '%(zctl)s' lives.
It contains configuration information for Zope, and optionally for ZEO.
Additional Zope configurations may be defined by creating subdirectories
of the INSTANCE_HOME containing 'conf.py'.  If you specify the name of
one or more of these subdirectories in a '%(zctl)s start' or '%(zctl)s stop',
that configuration will be started or stopped instead of the default.

'%(zctl)s make_cgi' will write PCGI settings to the file you specify, or to
'Zope.cgi' if the name is omitted.

'%(zctl)s debug' will launch an interactive Python session with the Zope
application object loaded as 'app'.
""" % {'zctl': 'i1zctl.py'}

import sys, os, socket, time, string
from os.path import isfile, isdir, abspath
pjoin = os.path.join
psplit = os.path.split
env = os.environ
run = os.system

# Find out where we are, and where Python is.
if not sys.argv[0]: HERE = '.'
else: HERE = psplit(sys.argv[0])[0]
HERE = abspath(HERE)
PYTHON = '"%s"' % sys.executable
ZOPE_ENV = {}
ZEO = {} # ZEO is off by default

# Load configuration data into global variables
ZOPE_CONFIG = pjoin(HERE, 'zope.conf')
if not isfile(ZOPE_CONFIG):
    print 'Zope configuration file "zope.conf" not found.'
    sys.exit(1)
execfile(ZOPE_CONFIG, globals())

# Poke environment variables needed by Zope and ZEO
env['INSTANCE_HOME'] = HERE
ZOPE_HOME = abspath(ZOPE_HOME)
for k, v in ZEO.items():
    env[k] = str(v)
PYTHONPATH = env.get('PYTHONPATH', '')
PYTHONPATH = "%s:%s/lib/python%s%s" % (ZOPE_HOME, ZOPE_HOME,
                                       PYTHONPATH and '', PYTHONPATH)

# Commands

def test(args):
    print PYTHON
    print HERE
    print ZOPE_HOME
    print ZEO

def start(args):
    """Start Zope when ZEO is reachable, starting ZEO first if necessary."""
    clients = []
    zeo_args = []
    zope_args = []
    while args and args[0][:1] != '-':
        clients.append(args.pop(0))
    while args:
        if args[0] == '--zeo':
            args.pop(0)
            while args and args[0][:2] != '--':
                zeo_args.append(args.pop(0))
        else:
            if args[0] == '--zope':
                args.pop(0)
            while args and args[0][:2] != '--':
                zope_args.append(args.pop(0))
    if not clients:
        clients.append('default')

    cmd = '%s "%s/z2.py" %%s' % (PYTHON, ZOPE_HOME)
    global ZOPE_PORT, ZOPE_LOG, ZOPE_OPTS, ZOPE_ENV, CLIENT_HOME
    for client in clients:
        args = list(zope_args)
        if client != 'default':
            ZOPE_PORT = ZOPE_LOG = ZOPE_OPTS = None
            CLIENT_HOME = pjoin(HERE, client)
            conf = pjoin(CLIENT_HOME, 'conf.py')
            if not (isdir(CLIENT_HOME) and isfile(conf)):
                print 'Client configuration file "%s" was not found.' % conf
                continue
            execfile(conf, globals())
            args.append('"CLIENT_HOME=%s"' % CLIENT_HOME)
        if ZOPE_OPTS is not None:
            args.insert(0, ZOPE_OPTS)
        if ZOPE_PORT is not None:
            args.insert(0, '-P %s' % ZOPE_PORT)
        if ZOPE_LOG is not None:
            args.append('"STUPID_LOG_FILE=%s"' % ZOPE_LOG)
        for k,v in ZOPE_ENV.items():
            env[k] = str(v)
        if ZEO:
            start_zeo(zeo_args)
        print 'Starting %s (%s) Zope...' % (client, ZOPE_PORT or 80)
        run(cmd % string.join(args))
        
def start_zeo(args):
    """Try to start ZEO."""
    host = ZEO.get('ZEO_SERVER_NAME', 'localhost')
    port = ZEO['ZEO_SERVER_PORT']
    if host == 'localhost' and not _check_for_service(host, port):
        stop_zeo(None)
        print "Starting ZEO server on", port
        cmd = 'PYTHONPATH=%s %s %s/lib/python/ZEO/start.py -p %s %s &' % (
            PYTHONPATH, PYTHON, ZOPE_HOME, port, string.join(args)
            )
        run(cmd)
    count = 0
    while not _check_for_service(host, port):
        count = count + 1
        if count > ZEO_WAIT_BAILOUT:
            print ("ZEO connect failure, on port %s after %d seconds"
                   % (port, ZEO_WAIT_BAILOUT))
            sys.exit(1)
        print "waiting for ZEO server to start %d/%d" % (count,
                                                         ZEO_WAIT_BAILOUT)
        time.sleep(1)
    print "ZEO server ready."

def stop_zeo(args):
    """Stop the ZEO server."""
    try:
        pids = open('%s/var/ZEO_SERVER.pid' % HERE, 'r').read()
    except:
        return
    print "Stopping ZEO pid: %s" % pids
    run('kill %s' % pids)

def stop(args):
    """Stop client(s)."""
    if not args:
        args = ['var']
    for client in args:
        pidf = pjoin(HERE, client, 'Z2.pid')
        if not isfile(pidf):
            print '"%s" was not found' % pidf
            continue
        run('kill %s' % open(pidf, 'r').read())

def status(args):
    """Print status."""
    print "NAME\tPORT\tPIDS"
    if ZEO:
        host = ZEO.get('ZEO_SERVER_NAME', 'localhost')
        port = ZEO['ZEO_SERVER_PORT']
        pids = ''
        if _check_for_service(host, port):
            if host == 'localhost':
                pids = open('%s/var/ZEO_SERVER.pid' % HERE, 'r').read()
            else:
                pids = 'unknown'
        print "ZEO\t%s\t%s" % (port, pids)
    if not args:
        import glob
        for client in glob.glob('%s/*/conf.py' % HERE):
            args.append(psplit(psplit(client)[0])[1])
    for client in args:
        pidf = pjoin(HERE, client, 'Z2.pid')
        if isfile(pidf):
            pids = open(pidf, 'r').read()
        else:
            pids = 'not found'
        print '%s\t%s\t%s' % (client, '', pids)

def make_cgi(args):
    """Create a PCGI parameter file."""
    if args:
        fname = args.pop(0)
    else:
        fname = 'Zope.cgi'
    write = open(fname, 'w').write
    write('''\
#!%(ZOPE_HOME)s/pcgi/pcgi-wrapper
PCGI_NAME=Zope
PCGI_MODULE_PATH=%(ZOPE_HOME)s/lib/python/Zope
PCGI_PUBLISHER=%(ZOPE_HOME)s/pcgi/pcgi_publisher.py
PCGI_EXE=%(PYTHON)s
PCGI_SOCKET_FILE=%(HERE)s/var/pcgi.soc
PCGI_PID_FILE=%(HERE)s/var/pcgi.pid
PCGI_ERROR_LOG=%(HERE)s/var/pcgi.log
PCGI_DISPLAY_ERRORS=1
BOBO_REALM=Zope
BOBO_DEBUG_MODE=1
INSTANCE_HOME=%(HERE)s
''' % globals())

def do(args):
    """Execute python commands"""
    if ZEO:
        start_zeo([])
    for k,v in ZOPE_ENV.items():
        env[k] = str(v)
    os.chdir(pjoin(ZOPE_HOME, 'lib', 'python'))
    msg = """
          Zope debugging session for %s
          The root application object is bound to name 'app'.
          To let other people see your changes, you must:
            get_transaction().commit()
          To see other people's changes, you must:
            app._p_jar.sync()""" % HERE
    options = "-c"
    if not args or '-i' in args:
        options = '-i ' + options
        if args:
            args.remove('-i')
        print msg
    while '-f' in args:
        fpos = args.index('-f')
        args.pop(fpos)
        args[fpos] = 'execfile("%s");' % args[fpos]
    cmd = ("%s %s 'import Zope, sys; app=Zope.app(); %s'"
           % (PYTHON, options, string.join(args, " ")))
    run(cmd)

def debug(args):
    """Start an interactive debugging session"""
    args.insert(0, '-i')
    do(args)

def test(args):
    """Run tests"""
    args[0] = os.path.abspath(args[0])
    args.insert(0, '-f')
    do(args)

# Internal helper functions

def _check_for_service(host, port):
    """Return 1 if server is found at (host, port), 0 otherwise."""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect((host, int(port)))
        return 1
    except socket.error:
        return 0

def _dispatch():
    """Dispatch command line invocation."""
    if len(sys.argv) == 1:
        print """\
    start [confname ...] [--zeo -arg ... [--zope]] -arg ...
    stop [confname ...]
    start_zeo
    stop_zeo
    status [confname ...]
    make_cgi [filename]
    debug
    test filename
    do [-i] [-f filename]* commands
"""
        args = string.split(raw_input('command: '))
    else:
        args = sys.argv[1:]
    action = string.lower(args.pop(0))
    if action[:1] == '_':
        print 'Invalid action "%s"' % action
        sys.exit(1)
    globals()[action](args)

if __name__ == "__main__":
    _dispatch()