[Zope-Checkins] CVS: Zope/utilities - zctl_lib.py:1.1.4.1
Chris McDonough
chrism@zope.com
Thu, 22 Aug 2002 00:30:17 -0400
Update of /cvs-repository/Zope/utilities
In directory cvs.zope.org:/tmp/cvs-serv26817/utilities
Added Files:
Tag: chrism-install-branch
zctl_lib.py
Log Message:
A branch which allows for a ./configure; make; make install Zope installation.
Here is a sample session to get a flavor for things:
[chrism@james InstallerBranch]$ ./configure --prefix=/home/chrism/opt/zoptest
Configuring Zope installation
Testing for an acceptable Python interpreter...
The optimimum Python version (2.1.3) was found at /home/chrism/bin/python.
Configuring...
SOFTWARE_HOME (Zope binary directory) will be /home/chrism/opt/zoptest.
Makefile written.
'makeinstance' script written.
[chrism@james InstallerBranch]$ make
/home/chrism/bin/python /home/chrism/software/InstallerBranch/inst/compile_all.py
------------------------------------------------------------------------------
Compiling python modules
Building extension modules
/home/chrism/bin/python setup.py build_ext -i
running build_ext
building 'AccessControl.cAccessControl' extension
gcc -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -g -O2 -Wall -Wstrict-prototypes -fPIC -I/home/chrism/software/InstallerBranch/lib/Components/ExtensionClass/src -I/home/chrism/opt/Python2.1.3/include/python2.1 -c AccessControl/cAccessControl.c -o build/temp.linux-i686-2.1/cAccessControl.o
... and so on ...
chmod 0711 /home/chrism/software/InstallerBranch/var
------------------------------------------------------------------------------
/bin/touch /home/chrism/software/InstallerBranch/build
Zope built. Next, do make install.
[chrism@james InstallerBranch]$ make install
/bin/mkdir -p /home/chrism/opt/zoptest
/bin/cp -r -u /home/chrism/software/InstallerBranch/* /home/chrism/opt/zoptest
... and so on ...
Zope binaries installed successfully.
Now run /home/chrism/opt/zoptest/makeinstance.
[chrism@james InstallerBranch]$ /home/chrism/opt/zoptest/makeinstance
The instance home is the directory from which you will run Zope.
Several instance homes, each with their own data and
configuration, can share one copy of Zope.
Instance home [/home/chrism/opt/zoptest]: /home/chrism/opt/instance
'/home/chrism/opt/instance' does not exist.
Shall I create it [y]?
Created.
Created 'Extensions' directory.
Created 'import' directory.
Created 'Products' directory.
Created 'var' directory.
Created default database
Created zctl.py
------------------------------------------------------------------------------
Now to create a starting user. Leave the username blank if you want to skip this step.
------------------------------------------------------------------------------
Please choose a username and password.
This will create the initial user with which you manage Zope.
Username: admin
Password:
Verify password:
chmod 0644 /home/chrism/opt/instance/inituser
Done! Use "/home/chrism/opt/instance/zctl.py start" to start Zope.
[chrism@james InstallerBranch]$ cd ~
[chrism@james chrism]$ cd opt/instance/
[chrism@james instance]$ ./zctl.py start
Starting Zope, using:
"/home/chrism/bin/python" "/home/chrism/opt/zoptest/z2.py"
[chrism@james instance]$
=== Added File Zope/utilities/zctl_lib.py ===
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
def zctl_usage(args):
print """Control Zope, and ZEO server if it's configured
Usage:
zctl.py start [--zeo -arg ... [--zope]] -arg ...
Start Zope, checking that ZEO is up and starting it, if necessary.
zctl.py stop
Stop Zope. Does not stop ZEO.
zctl.py debug
Open an interactive Python session with Zope loaded.
zctl.py test filename
zctl.py script filename
Load Zope environment, then execute file as a Python program.
zctl.py do [-i] [-f filename]* commands
Execute Python commands and zero or more files.
zctl.py stop_all
Stop Zope, and run ZEO stop script if possible.
zctl.py start_zeo
Run ZEO start script if possible.
zctl.py stop_zeo
Run ZEO stop script if possible.
zctl.py status
Show the status of Zope, and possibly ZEO.
zctl.py make_cgi [filename]
Write a Zope.cgi file for use with PCGI.
zctl.py usage | --help
Print this information.
'zctl.py' contains configuration information for Zope, and optionally
for connecting to ZEO, for a single Zope instance. The directory
containing the file 'zctl.py' is the INSTANCE_HOME. More than one
INSTANCE_HOME can be set up to use the same copy of the Zope software,
and each one can have its own Zope database(s), Products, and
Extensions.
If an instance uses a ZEO server, then you can run a 'zctl.py debug'
session without stopping the Zope instance.
"""
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 = os.curdir()
else: HERE = psplit(sys.argv[0])[0]
HERE = abspath(HERE)
ZOPE_HOME = abspath(ZOPE_HOME)
CLIENT_HOME = pjoin(HERE, 'var')
PYTHON = '"%s"' % sys.executable
ZOPE = {}
ZOPE_ENV = {}
ZEO = {} # ZEO is off by default
# Define 'constants'
OPTS, PORT, LOG, WAIT, SOCKET, CONTROL = (
'OPTS', 'PORT', 'LOG', 'WAIT', 'SOCKET', 'CONTROL')
# Commands
def zctl_start(args):
"""Start Zope when ZEO is reachable, starting ZEO first if necessary."""
pidf = pjoin(CLIENT_HOME, 'Z2.pid')
running = _check_pids(pidf)
if running:
for pid, up in running.items():
if up:
print 'There appears to be a Zope instance already running.'
print 'Either stop it, or delete "%s".' % pidf
return
zeo_args = []
zope_args = []
app = zope_args.append
while args:
arg = args.pop(0)
if arg[:2] == '--':
argmap = {'zeo': zeo_args, 'zope': zope_args}.get(arg[2:])
if argmap is None:
app(arg)
else:
app = argmap.append
else:
app(arg)
cmd = '%s "%s/z2.py" %%s' % (PYTHON, ZOPE_HOME)
args = list(zope_args)
if ZOPE.get(OPTS):
args.insert(0, ZOPE[OPTS])
if ZOPE.get(PORT):
args.insert(0, '-P %s' % ZOPE[PORT])
if ZOPE.get(LOG):
args.append('"STUPID_LOG_FILE=%s"' % ZOPE[LOG])
for k,v in ZOPE_ENV.items():
env[k] = str(v)
env['INSTANCE_HOME'] = HERE
if ZEO:
zctl_start_zeo(zeo_args)
env['ZEO_SOCKET'] = ZEO[SOCKET]
cmd = cmd % string.join(args)
print 'Starting Zope, using:'
print cmd
run(cmd)
def zctl_start_zeo(args):
"""Try to start ZEO."""
zeosocket = ZEO.get(SOCKET)
if zeosocket is None:
print 'Error: ZEO[SOCKET] is not defined.'
return
elif ':' in zeosocket:
zeosocket = tuple(string.split(zeosocket, ':'))
host, port = zeosocket
if ZEO.get(CONTROL) and not _check_for_service(zeosocket):
run(ZEO[CONTROL] + ' start ' + ZEO.get(OPTS, ''))
count = 0
ZEO_WAIT_BAILOUT = ZEO.get(WAIT, 60)
while not _check_for_service(zeosocket):
count = count + 1
if count > ZEO_WAIT_BAILOUT:
print ("ZEO connect failure, on %s after %d seconds"
% (zeosocket, ZEO_WAIT_BAILOUT))
sys.exit(1)
print "waiting for ZEO server to start %d/%d" % (count,
ZEO_WAIT_BAILOUT)
time.sleep(1)
if host == 'localhost' and not _check_for_service(host, port):
print "Starting ZEO server on", port
cmd = '%s %s/lib/python/ZEO/start.py -p %s %s &' % (
PYTHON, ZOPE_HOME, port, string.join(args)
)
run(cmd)
def zctl_stop_zeo(args):
"""Stop the ZEO server."""
if not ZEO.get(CONTROL):
print 'Error: ZEO[CONTROL] is not defined.'
return
run(ZEO[CONTROL] + ' stop')
def zctl_stop(args):
"""Stop client."""
pidf = pjoin(CLIENT_HOME, 'Z2.pid')
if not isfile(pidf):
print '"%s" was not found' % pidf
return
for pid in string.split(open(pidf).read()):
print 'Stopping Zope process %s' % pid
os.kill(int(pid), 15)
def zctl_stop_all(args):
"Stop client and ZEO server"
zctl_stop(args)
zctl_stop_zeo(args)
def zctl_status(args):
"""Print status."""
pidf = pjoin(CLIENT_HOME, 'Z2.pid')
running = _check_pids(pidf)
if running is None:
print 'No Zope process found.'
return
for pid, up in running.items():
if up is None:
print '%s is in pid file.' % pid
elif up:
print '%s is running.' % pid
else:
print '%s is in pid file, but not running.' % pid
def zctl_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=%(CLIENT_HOME)s/pcgi.soc
PCGI_PID_FILE=%(CLIENT_HOME)s/pcgi.pid
PCGI_ERROR_LOG=%(CLIENT_HOME)s/pcgi.log
PCGI_DISPLAY_ERRORS=1
BOBO_REALM=Zope
BOBO_DEBUG_MODE=1
INSTANCE_HOME=%(HERE)s
''' % globals())
def zctl_do(args):
"""Execute python commands"""
if ZEO:
start_zeo([])
for k,v in ZOPE_ENV.items():
env[k] = str(v)
env['INSTANCE_HOME'] = HERE
cwd = os.getcwd()
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]
imports = 'import Zope'
if not (os.path.samefile(cwd, os.getcwd()) or
os.path.samefile(cwd, HERE)):
imports = '%s; import sys; sys.path.append("%s")' % (
imports, cwd)
cmd = ("%s %s '%s; app=Zope.app(); %s'"
% (PYTHON, options, imports, string.join(args, " ")))
run(cmd)
def zctl_debug(args):
"""Start an interactive debugging session"""
args.insert(0, '-i')
zctl_do(args)
def zctl_script(args):
"""Execute a Python script"""
args[0] = os.path.abspath(args[0])
args.insert(0, '-f')
zctl_do(args)
def zctl_test(args):
"""Run a test"""
zctl_script(args)
# Internal helper functions
def _check_pids(pidfile):
"""Return dictionary of pids, or None if pidfile not found.
The value for each pid indicates whether the process is running.
"""
if isfile(pidfile):
pids = string.split(open(pidfile, 'r').read())
else:
return
running = {}
if isdir('/proc'):
for pid in pids:
running[pid] = isdir('/proc/%s' % pid)
else:
for pid in pids:
running[pid] = None
return running
def _check_for_service(ssock):
"""Return 1 if server is found, 0 otherwise."""
try:
if type(ssock) is type(()):
stype = socket.AF_INET
else:
stype = socket.AF_UNIX
s = socket.socket(stype, socket.SOCK_STREAM)
s.connect(ssock)
return 1
except socket.error:
return 0
def main():
"""Dispatch command line invocation."""
if len(sys.argv) == 1:
print """\
start [--zeo -arg ... [--zope]] -arg ...
stop
stop_all
start_zeo
stop_zeo
status
make_cgi [filename]
debug
test filename
do [-i] [-f filename]* commands
script filename
usage
"""
args = string.split(raw_input('command: '))
else:
args = sys.argv[1:]
action = string.lower(args.pop(0))
if action == '--help':
action = 'usage'
if not globals().has_key('zctl_'+action):
print 'Unknown command "%s"' % action
sys.exit(1)
for k, v in ZEO.items():
env['ZEO_'+k] = str(v)
globals()['zctl_'+action](args)