[Zope-Checkins] CVS: Zope/lib/python/Zope/Startup - ZctlLib.py:1.2 __init__.py:1.2 cmdline.py:1.2 datatypes.py:1.2 handlers.py:1.2 zopeschema.xml:1.2
Fred L. Drake, Jr.
fred@zope.com
Wed, 29 Jan 2003 15:25:49 -0500
Update of /cvs-repository/Zope/lib/python/Zope/Startup
In directory cvs.zope.org:/tmp/cvs-serv21529
Added Files:
ZctlLib.py __init__.py cmdline.py datatypes.py handlers.py
zopeschema.xml
Log Message:
Update from chrism-install-branch.
=== Zope/lib/python/Zope/Startup/ZctlLib.py 1.1 => 1.2 === (648/748 lines abridged)
--- /dev/null Wed Jan 29 15:25:49 2003
+++ Zope/lib/python/Zope/Startup/ZctlLib.py Wed Jan 29 15:25:15 2003
@@ -0,0 +1,745 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+ Zope appserver controller. This is akin to apache's apachectl,
+ except with an interactive interpreter if no commands are specified
+ on the command-line.
+"""
+
+__version__ = '$Revision$'[11:-2]
+
+import cmd
+import getopt
+import os
+import signal
+import sys
+import time
+
+try:
+ import readline
+except:
+ readline = None
+
+from Zope.Startup import getOptions, getOptionDescriptions, configure
+from Zope.Startup.misc import TextBlockFormatter
+from Zope.Startup.misc.lock_file import lock_file
+
+USAGE = """\
+
+zopectl: Zope appserver controller
+
+Usage:
+ zopectl [-h | --help] [--config=filepath or url] [additional options]
+
+Options:
+ -h or --help Print this message. Not compatible with the 'start'
+ or 'restart' command.
+
[-=- -=- -=- 648 lines omitted -=- -=- -=-]
+ self.cmdqueue.append(' '.join(args))
+ self.cmdqueue.append('EOF')
+
+ self.cmdloop()
+
+def get_pids(filename):
+ for line in open(filename).readlines():
+ pids = line.split()
+ if pids:
+ return [ int(x.strip()) for x in pids ]
+
+def win32kill(pid, sig):
+ # we ignore the signal on win32
+ try:
+ import win32api
+ import pywintypes
+ except:
+ print ("Could not open win32api module, have you installed the "
+ "'win32all' package?")
+ return 1
+ try:
+ handle = win32api.OpenProcess(1, 0, pid)
+ except pywintypes.error, why:
+ # process named by pid not running
+ return 1
+ try:
+ status = win32api.TerminateProcess(handle, 0)
+ except:
+ return 1
+ if status is None:
+ return 0
+ return 1
+
+def kill(pid, sig):
+ try:
+ os.kill(pid, sig)
+ except OSError, why:
+ return 1
+ else:
+ return 0
+
+def cmdquote(cmd):
+ if sys.platform == 'win32':
+ # ugh. win32 requires the command to be quoted. unix requires
+ # that the command *not* be quoted.
+ cmd = '"%s"' % cmd
+ return cmd
+
+if sys.platform == 'win32':
+ kill = win32kill
=== Zope/lib/python/Zope/Startup/__init__.py 1.1 => 1.2 ===
--- /dev/null Wed Jan 29 15:25:49 2003
+++ Zope/lib/python/Zope/Startup/__init__.py Wed Jan 29 15:25:15 2003
@@ -0,0 +1,314 @@
+""" Startup package. Responsible for startup configuration of Zope """
+
+import os
+import sys
+import socket
+import re
+
+import ZConfig
+
+from misc.lock_file import lock_file
+from cmdline import getOptions, getOptionDescriptions # exported
+
+# global to hold config structures
+_schema = None
+_configuration = None
+
+def getConfiguration():
+ return _configuration
+
+def getSchema():
+ global _schema
+ if _schema is None:
+ here = os.path.dirname(__file__)
+ path = os.path.join(here, 'zopeschema.xml')
+ _schema = ZConfig.loadSchema(path)
+ return _schema
+
+def getSchemaKeys():
+ schema = getSchema()
+ return schema.getchildnames()
+
+def configure(config_location, options):
+ global _configuration
+ import handlers
+ schema = getSchema()
+ _configuration, handler = ZConfig.loadConfig(schema, config_location)
+ handlers.handleConfig(_configuration, handler, options)
+ return _configuration
+
+def start_zope(config_location, options):
+ check_python_version()
+ cfg = configure(config_location, options)
+
+ if cfg.zope_home not in sys.path:
+ sys.path.insert(0, cfg.zope_home)
+
+ if cfg.software_home not in sys.path:
+ sys.path.insert(0, cfg.software_home)
+
+ sys.path = filter(None, sys.path) # strip empties out of sys.path
+
+ # set up our initial logging environment (log everything to stderr
+ # if we're not in debug mode).
+ import zLOG
+
+ # don't initialize the event logger from the environment
+ zLOG._call_initialize = 0
+ import logging
+
+ from zLOG.LogHandlers import StartupHandler
+
+ # we log events to the root logger, which is backed by a
+ # "StartupHandler" log handler. The "StartupHandler" outputs to
+ # stderr but also buffers log messages. When the "real" loggers
+ # are set up, we flush accumulated messages in StartupHandler's
+ # buffers to the real logger.
+ startup_handler = StartupHandler(sys.stderr)
+ formatter = zLOG.EventLogger.formatters['file']
+ startup_handler.setFormatter(formatter)
+ if not cfg.debug_mode:
+ # prevent startup messages from going to stderr if we're not
+ # in debug mode
+ if os.path.exists('/dev/null'): # unix
+ devnull = '/dev/null'
+ else: # win32
+ devnull = 'nul:'
+ startup_handler = StartupHandler(open(devnull, 'w'))
+
+ # set up our event logger temporarily with a startup handler
+ event_logger = logging.getLogger('event')
+ event_logger.addHandler(startup_handler)
+
+ # set a locale if one has been specified in the config
+ cfg.locale and do_locale(cfg.locale)
+
+ # goofy source_port clients business
+ dav_clients = cfg.webdav_source_user_agents
+ if dav_clients:
+ sys.WEBDAV_SOURCE_PORT_CLIENTS = re.compile(dav_clients).search
+
+ # make sure to import zdaemon before zserver or weird things
+ # begin to happen
+ import zdaemon
+
+ # Import ZServer before we open the database or get at interesting
+ # application code so that ZServer's asyncore gets to be the
+ # official one. Also gets SOFTWARE_HOME, INSTANCE_HOME, and CLIENT_HOME
+ import ZServer
+
+ # Increase the number of threads
+ from ZServer import setNumberOfThreads
+ setNumberOfThreads(cfg.zserver_threads)
+
+ # if we're not using ZDaemon or if we're the child of a Zdaemon process,
+ # start ZServer servers before we setuid so we can bind to low ports
+ if not cfg.use_daemon_process or (
+ cfg.use_daemon_process and os.environ.get('ZDAEMON_MANAGED')
+ ):
+ socket_err = (
+ 'There was a problem starting a server of type "%s". '
+ 'This may mean that your user does not have permission to '
+ 'bind to the port which the server is trying to use or the '
+ 'port may already be in use by another application.'
+ )
+ for server_type, server in cfg.servers:
+ # create the server from the server factory
+ # set up in the config
+ try:
+ server()
+ except socket.error:
+ raise ZConfig.ConfigurationError(socket_err % server_type)
+
+ # do stuff that only applies to posix platforms (setuid, daemonizing)
+ if os.name == 'posix':
+ do_posix_stuff(cfg)
+
+ # Import Zope
+ import Zope
+ Zope.startup()
+
+ if not cfg.zserver_read_only_mode:
+ # lock_file is used for the benefit of zctl, so it can tell whether
+ # Zope is already running before attempting to fire it off again.
+ # We aren't concerned about locking the file to protect against
+ # other Zope instances running from our CLIENT_HOME, we just
+ # try to lock the file to signal that zctl should not try to
+ # start Zope if *it* can't lock the file; we don't panic
+ # if we can't lock it.
+ # we need a separate lock file because on win32, locks are not
+ # advisory, otherwise we would just use the pid file
+ lock_filename = (cfg.lock_filename or
+ os.path.join(cfg.instance_home, 'var', 'Z2.lock'))
+
+ try:
+ if os.path.exists(lock_filename):
+ os.unlink(lock_filename)
+ LOCK_FILE = open(lock_filename, 'w')
+ lock_file(LOCK_FILE)
+ except IOError:
+ pass
+
+ # write pid file if zdaemon didn't do it already
+ if not cfg.use_daemon_process:
+ pf = open(cfg.pid_filename, 'w')
+ pid='%s\n' % os.getpid()
+ pf.write(pid)
+ pf.close()
+
+ # now that we've successfully setuid'd, we can log to
+ # somewhere other than stderr. We rely on config
+ # to set up our logging properly.
+ for logger_name in ('access', 'trace'):
+ factory = getattr(cfg, logger_name)
+ if factory:
+ logger = factory() # activate the logger
+
+ # flush buffered startup messages to event logger
+ if cfg.eventlog:
+ logger = cfg.eventlog()
+ startup_handler.flushBufferTo(logger)
+
+ event_logger.removeHandler(startup_handler)
+
+ zLOG.LOG('Zope', zLOG.INFO, 'Ready to handle requests')
+
+ # Start Medusa, Ye Hass!
+ sys.ZServerExitCode=0
+ try:
+ import Lifetime
+ Lifetime.loop()
+ sys.exit(sys.ZServerExitCode)
+ finally:
+ if not cfg.zserver_read_only_mode:
+ try:
+ os.unlink(cfg.pid_filename)
+ except OSError:
+ pass
+ try:
+ LOCK_FILE.close()
+ os.unlink(lock_filename)
+ except OSError:
+ pass
+
+def _warn_nobody():
+ import zLOG
+ zLOG.LOG("Zope", zLOG.INFO, ("Running Zope as 'nobody' can compromise "
+ "your Zope files; consider using a "
+ "dedicated user account for Zope"))
+
+def check_python_version():
+ # check for Python version
+ python_version = sys.version.split()[0]
+ optimum_version = '2.2.2'
+ if python_version < '2.2':
+ raise ZConfig.ConfigurationError(
+ 'Invalid python version ' + python_version)
+ if python_version[:3] == '2.2':
+ if python_version[4:5] < '2':
+ err = ('You are running Python version %s. This Python version '
+ 'has known bugs that may cause Zope to run improperly. '
+ 'Consider upgrading to Python %s\n' %
+ (python_version, optimum_version))
+ sys.stderr.write(err)
+
+def do_posix_stuff(cfg):
+ import zLOG
+ import zdaemon
+ import pwd
+ from Signals import Signals
+ Signals.registerZopeSignals()
+
+ # Warn if we were started as nobody.
+ if os.getuid():
+ if pwd.getpwuid(os.getuid())[0] == 'nobody':
+ _warn_nobody()
+
+ # Drop root privileges if we have them, and do some sanity checking
+ # to make sure we're not starting with an obviously insecure setup.
+ if os.getuid() == 0:
+ UID = cfg.effective_user
+ if UID == None:
+ msg = ('A user was not specified to setuid to; fix this to '
+ 'start as root (change the effective_user directive '
+ 'in zope.conf)')
+ zLOG.LOG('Zope', zLOG.PANIC, msg)
+ raise ZConfig.ConfigurationError(msg)
+ # stuff about client home faults removed (real effective user
+ # support now)
+ try:
+ UID = int(UID)
+ except (TypeError, ValueError):
+ pass
+ gid = None
+ if isinstance(UID, str):
+ uid = pwd.getpwnam(UID)[2]
+ gid = pwd.getpwnam(UID)[3]
+ elif isinstance(UID, int):
+ uid = pwd.getpwuid(UID)[2]
+ gid = pwd.getpwuid(UID)[3]
+ UID = pwd.getpwuid(UID)[0]
+ else:
+ zLOG.LOG("Zope", zLOG.ERROR, ("Can't find UID %s" % UID))
+ raise ZConfig.ConfigurationError('Cant find UID %s' % UID)
+ if UID == 'nobody':
+ _warn_nobody()
+ if gid is not None:
+ try:
+ import initgroups
+ initgroups.initgroups(UID, gid)
+ os.setgid(gid)
+ except OSError:
+ zLOG.LOG("Zope", zLOG.INFO,
+ 'Could not set group id of effective user',
+ error=sys.exc_info())
+ os.setuid(uid)
+ zLOG.LOG("Zope", zLOG.INFO,
+ 'Set effective user to "%s"' % UID)
+
+ if not cfg.debug_mode:
+ # umask is silly, blame POSIX. We have to set it to get its value.
+ current_umask = os.umask(0)
+ os.umask(current_umask)
+ if current_umask != 077:
+ current_umask = '%03o' % current_umask
+ zLOG.LOG("Zope", zLOG.INFO, (
+ 'Your umask of %s may be too permissive; for the security of '
+ 'your Zope data, it is recommended you use 077' % current_umask
+ ))
+
+ # try to use a management daemon process. We do this after we setuid so
+ # we don't write our pidfile out as root.
+ if cfg.use_daemon_process and not cfg.zserver_read_only_mode:
+ import App.FindHomes
+ sys.ZMANAGED=1
+ # zdaemon.run creates a process which "manages" the actual Zope
+ # process (restarts it if it dies). The management process passes
+ # along signals that it receives to its child.
+ zdaemon.run(sys.argv, cfg.pid_filename)
+
+def do_locale(locale_id):
+ # workaround to allow unicode encoding conversions in DTML
+ import codecs
+ dummy = codecs.lookup('iso-8859-1')
+
+ if locale_id is not None:
+ try:
+ import locale
+ except:
+ raise ZConfig.ConfigurationError(
+ 'The locale module could not be imported.\n'
+ 'To use localization options, you must ensure\n'
+ 'that the locale module is compiled into your\n'
+ 'Python installation.'
+ )
+ try:
+ locale.setlocale(locale.LC_ALL, locale_id)
+ except:
+ raise ZConfig.ConfigurationError(
+ 'The specified locale "%s" is not supported by your system.\n'
+ 'See your operating system documentation for more\n'
+ 'information on locale support.' % locale_id
+ )
+
+
=== Zope/lib/python/Zope/Startup/cmdline.py 1.1 => 1.2 ===
--- /dev/null Wed Jan 29 15:25:49 2003
+++ Zope/lib/python/Zope/Startup/cmdline.py Wed Jan 29 15:25:15 2003
@@ -0,0 +1,179 @@
+import getopt
+
+def getOptionDescriptions():
+ """ Temporary implementation """
+
+ short, long = getOptions()
+ n = 0
+ short_d = {}
+ long_d = {}
+
+ last = 0
+ n = 0
+
+ print short
+
+ if short:
+ while 1:
+ try:
+ opt = short[n]
+ except IndexError:
+ next = None
+ try:
+ next = short[n+1]
+ except IndexError:
+ next = None
+ if next == ':':
+ short_d[opt] = 1
+ n = n + 2
+ else:
+ if next is None and short.endswith(':'):
+ short_d[opt] = 1
+ else:
+ short_d[opt] = 0
+ n = n + 1
+ if next is None:
+ break
+
+ for opt in long:
+ if opt.endswith('='):
+ long_d[opt[:-1]] = 1
+ else:
+ long_d[opt] = 0
+
+ opts = []
+
+ short_l = short_d.items()
+ short_l.sort()
+ for k, v in short_l:
+ opts.append(' -%s%s' % (k, (v and ' <value>' or '')))
+
+ long_l = long_d.items()
+ long_l.sort()
+ for k, v in long_l:
+ opts.append(' --%s%s' % (k, (v and ' <value>' or '')))
+ return '\n'.join(opts)
+
+def getOptions():
+ short = 'Z:t:i:D:a:d:u:L:l:M:E:Xw:W:f:p:F:m:'
+ long = [
+ 'use-daemon-process=',
+ 'zserver-threads=',
+ 'python-check-interval=',
+ 'debug-mode=',
+ 'ip-address=',
+ 'dns-ip-address=',
+ 'effective-user=',
+ 'locale=',
+ 'access-log=',
+ 'trace-log=',
+ 'event-log=',
+ 'disable-servers',
+ 'http-server=',
+ 'webdav-source-server=',
+# XXX need to finish these
+# 'ftp-server=',
+# 'pcgi-server=',
+# 'fcgi-server=',
+# 'monitor-server=',
+# 'icp-server=',
+ ]
+ return short, long
+
+class CommandLineOptions:
+
+ def __call__(self, cfg, options):
+ import Zope.Startup.datatypes
+ import Zope.Startup.handlers
+ import ZConfig.datatypes
+
+ short, long = getOptions()
+ opts, args = getopt.getopt(options, short, long)
+
+ for k, v in opts:
+ # set up data that servers may rely on
+ if k in ('-Z', '--use-daemon-process'):
+ datatype = Zope.Startup.datatypes.use_daemon_process
+ handler = Zope.Startup.handlers.use_daemon_process
+ v = datatype(v)
+ handler(v)
+ cfg.use_daemon_process = v
+ elif k in ('-t', '--zserver-threads'):
+ cfg.zserver_threads = int(v)
+ elif k in ('-i', '--python-check-interval'):
+ cfg.python_check_interval = int(v)
+ elif k in ('-D', '--debug-mode'):
+ datatype = ZConfig.datatypes.asBoolean
+ handler = Zope.Startup.handlers.debug_mode
+ v = datatype(v)
+ handler(v)
+ cfg.debug_mode = v
+ elif k in ('-i', '--ip-address'):
+ datatype = ZConfig.datatypes.IpaddrOrHostname()
+ cfg.ip_address = datatype(v)
+ elif k in ('-d', '--dns-ip-address'):
+ datatype = ZConfig.datatypes.IpaddrOrHostname()
+ cfg.dns_ip_address = datatype(v)
+ elif k in ('-u', '--effective-user'):
+ cfg.effective_user = v
+ elif k in ('-L', '--locale'):
+ datatype = ZConfig.datatypes.check_locale
+ cfg.locale = datatype(v)
+ elif k in ('-l', '--access-log'):
+ cfg.access = default_logger('access', v,
+ '%(message)s',
+ '%Y-%m-%dT%H:%M:%S')
+ elif k in ('-M', '--trace-log'):
+ cfg.trace = default_logger('trace', v,
+ '%(message)s',
+ '%Y-%m-%dT%H:%M:%S')
+ elif k in ('-E', '--event-log'):
+ cfg.trace = default_logger('event', v,
+ '------\n%(asctime)s %(message)s',
+ '%Y-%m-%dT%H:%M:%S')
+ elif k in ('-X', '--disable-servers'):
+ cfg.servers = []
+ else:
+ # continue if we've not matched, otherwise
+ # fall through to the pop statement below
+ continue
+
+ opts.pop(0) # pop non-server data from opts
+
+ factory = Zope.Startup.handlers.ServerFactoryFactory(cfg)
+
+ for k, v in opts:
+ # set up server data from what's left in opts,
+ # using repopulated cfg
+ if k in ('-w', '--http-server'):
+ datatype = ZConfig.datatypes.inet_address
+ host, port = datatype(v)
+ section = dummy()
+ section.ports = [(host, port)]
+ section.force_connection_close = 0
+ cfg.servers.append(['http_server',
+ factory.http_server(section)[0]])
+ if k in ('-W', '--webdav-source-server'):
+ datatype = ZConfig.datatypes.inet_address
+ host, port = datatype(v)
+ section = dummy()
+ section.ports = [(host, port)]
+ section.force_connection_close = 0
+ cfg.servers.append(['webdav_source_server',
+ factory.webdav_source_server(section)[0]])
+
+class dummy:
+ # used as a namespace generator
+ pass
+
+def default_logger(name, file, format, dateformat):
+ import Zope.Startup.datatypes
+ logger = dummy()
+ logger.level = 20
+ handler = dummy()
+ handler.file = file
+ handler.format = format
+ handler.dateformat = dateformat
+ handler.level = 20
+ handlers = [Zope.Startup.datatypes.file_handler(handler)]
+ return Zope.Startup.datatypes.LoggerWrapper(name, 20, handlers)
=== Zope/lib/python/Zope/Startup/datatypes.py 1.1 => 1.2 ===
--- /dev/null Wed Jan 29 15:25:49 2003
+++ Zope/lib/python/Zope/Startup/datatypes.py Wed Jan 29 15:25:15 2003
@@ -0,0 +1,137 @@
+import os
+
+from misc.factory import Factory
+
+# generic datatypes
+
+def security_policy_implementation(value):
+ value = value.upper()
+ ok = ('PYTHON', 'C')
+ if value not in ok:
+ raise ValueError, (
+ "security_policy_implementation must be one of %s" % ok
+ )
+ return value
+
+def use_daemon_process(value):
+ from ZConfig.datatypes import asBoolean
+ daemonize = asBoolean(value)
+ # cannot use daemon process on non-POSIX platforms
+ if os.name != 'posix':
+ return False
+ return daemonize
+
+# log-related datatypes
+# (the loghandler datatypes come from the zLOG package)
+
+def logger(section):
+ return LoggerWrapper(section.getSectionName(),
+ section.level,
+ section.handlers)
+
+# database-related datatypes
+
+def mount_point(value):
+ if value.startswith('/'):
+ return value
+ raise ValueError, (
+ 'Invalid mount_point "%s" (must start with a slash)' % value
+ )
+
+def database(section):
+ if len(section.storages) > 1:
+ raise ValueError, ('Current database support limits database '
+ 'instances to a single storage')
+ if len(section.storages) < 1:
+ raise ValueError, 'Must name one storage in a database section'
+ klass = section.db_class
+ mounts = section.mount_points
+ dbfactory = Factory(
+ klass, None,
+ pool_size=section.pool_size,
+ cache_size=section.cache_size,
+ cache_deactivate_after=section.cache_deactivate_after,
+ version_pool_size=section.version_pool_size,
+ version_cache_size=section.version_cache_size,
+ version_cache_deactivate_after=section.version_cache_deactivate_after)
+ storagefactory = section.storages[0]
+ return mounts, DBWrapper(dbfactory, storagefactory)
+
+def filestorage(section):
+ return Factory('ZODB.FileStorage.FileStorage', None, section.path,
+ create=section.create,
+ read_only=section.read_only,
+ stop=section.stop,
+ quota=section.quota)
+
+def mappingstorage(section):
+ name = section.name
+ return Factory('ZODB.MappingStorage.MappingStorage', None, name)
+
+def clientstorage(section):
+ return Factory('ZEO.ClientStorage.ClientStorage', None, section.addr,
+ storage=section.storage,
+ cache_size=section.cache_size,
+ name=section.name,
+ client=section.client,
+ debug=section.debug,
+ var=section.var,
+ min_disconnect_poll=section.min_disconnect_poll,
+ max_disconnect_poll=section.max_disconnect_poll,
+ wait=section.wait,
+ read_only=section.read_only,
+ read_only_fallback=section.read_only_fallback)
+
+_marker = object()
+
+class LoggerWrapper:
+ """
+ A wrapper used to create loggers while delaying actual logger
+ instance construction. We need to do this because we may
+ want to reference a logger before actually instantiating it (for example,
+ to allow the app time to set an effective user).
+ An instance of this wrapper is a callable which, when called, returns a
+ logger object.
+ """
+ def __init__(self, name, level, handler_factories):
+ self.name = name
+ self.level = level
+ self.handler_factories = handler_factories
+ self.resolved = _marker
+
+ def __call__(self):
+ if self.resolved is _marker:
+ # set the logger up
+ import logging
+ logger = logging.getLogger(self.name)
+ logger.handlers = []
+ logger.propagate = 0
+ logger.setLevel(self.level)
+ for handler_factory in self.handler_factories:
+ handler = handler_factory()
+ logger.addHandler(handler)
+ self.resolved = logger
+ return self.resolved
+
+class DBWrapper:
+ """
+ A wrapper used to create ZODB databases while delaying the underlying
+ storage instance construction. We need to do this because we may
+ want to reference a database before actually instantiating it (for
+ example, in order to delay database construction until after an
+ effective user is set or until all configuration parsing is done).
+ An instance of this wrapper is a callable which, when called, returns a
+ database object.
+ """
+ def __init__(self, dbfactory, storagefactory):
+ self.dbfactory = dbfactory
+ self.storagefactory = storagefactory
+ self.resolved = _marker
+
+ def __call__(self):
+ if self.resolved is _marker:
+ args, kw = self.dbfactory.getArgs()
+ args = [self.storagefactory()] + list(args)
+ self.dbfactory.setArgs(args, kw)
+ self.resolved = self.dbfactory()
+ return self.resolved
=== Zope/lib/python/Zope/Startup/handlers.py 1.1 => 1.2 ===
--- /dev/null Wed Jan 29 15:25:49 2003
+++ Zope/lib/python/Zope/Startup/handlers.py Wed Jan 29 15:25:15 2003
@@ -0,0 +1,334 @@
+import os
+import types
+
+from misc.factory import Factory
+
+# top-level key handlers
+
+def _setenv(name, value):
+ if isinstance(value, types.StringTypes):
+ os.environ[name] = value
+ else:
+ os.environ[name] = `value`
+
+def _append_slash(value):
+ if value is None:
+ return None
+ if not value.endswith(os.sep):
+ return value + os.sep
+ return value
+
+def software_home(value):
+ value = _append_slash(value)
+ value and _setenv('SOFTWARE_HOME', value)
+ return value
+
+def zope_home(value):
+ value = _append_slash(value)
+ value and _setenv('ZOPE_HOME', value)
+ return value
+
+def instance_home(value):
+ value = _append_slash(value)
+ value and _setenv('INSTANCE_HOME', value)
+ return value
+
+def client_home(value):
+ value = _append_slash(value)
+ value and _setenv('CLIENT_HOME', value)
+ return value
+
+def debug_mode(value):
+ value and _setenv('Z_DEBUG_MODE', '1')
+ return value
+
+def enable_product_installation(value):
+ value and _setenv('FORCE_PRODUCT_LOAD', '1')
+ return value
+
+def locale(value):
+ import locale
+ locale.setlocale(locale.LC_ALL, value)
+ return value
+
+def use_daemon_process(value):
+ value and _setenv('Z_DEBUG_MODE', '1')
+ return value
+
+def zserver_read_only_mode(value):
+ value and _setenv('ZOPE_READ_ONLY', '1')
+ return value
+
+def automatically_quote_dtml_request_data(value):
+ not value and _setenv('ZOPE_DTML_REQUEST_AUTOQUOTE', '0')
+ return value
+
+def skip_authentication_checking(value):
+ value and _setenv('ZSP_AUTHENTICATED_SKIP', '1')
+ return value
+
+def skip_ownership_checking(value):
+ value and _setenv('ZSP_OWNEROUS_SKIP', '1')
+ return value
+
+def maximum_number_of_session_objects(value):
+ default = 1000
+ value not in (None, default) and _setenv('ZSESSION_OBJECT_LIMIT', value)
+ return value
+
+def session_add_notify_script_path(value):
+ value is not None and _setenv('ZSESSION_ADD_NOTIFY', value)
+ return value
+
+def session_delete_notify_script_path(value):
+ value is not None and _setenv('ZSESSION_DEL_NOTIFY', value)
+ return value
+
+def session_timeout_minutes(value):
+ default = 20
+ value not in (None, default) and _setenv('ZSESSION_TIMEOUT_MINS', value)
+ return value
+
+def suppress_all_access_rules(value):
+ value and _setenv('SUPPRESS_ACCESSRULE', value)
+ return value
+
+def suppress_all_site_roots(value):
+ value and _setenv('SUPPRESS_SITEROOT', value)
+ return value
+
+def database_quota_size(value):
+ value and _setenv('ZOPE_DATABASE_QUOTA', value)
+ return value
+
+def read_only_database(value):
+ value and _setenv('ZOPE_READ_ONLY', '1')
+ return value
+
+def zeo_client_name(value):
+ value and _setenv('ZEO_CLIENT', value)
+ return value
+
+def structured_text_header_level(value):
+ value is not None and _setenv('STX_DEFAULT_LEVEL', value)
+ return value
+
+def maximum_security_manager_stack_size(value):
+ value is not None and _setenv('Z_MAX_STACK_SIZE', value)
+ return value
+
+def publisher_profile_file(value):
+ value is not None and _setenv('PROFILE_PUBLISHER', value)
+ return value
+
+def http_realm(value):
+ value is not None and _setenv('Z_REALM', value)
+ return value
+
+def security_policy_implementation(value):
+ value not in ('C', None) and _setenv('ZOPE_SECURITY_POLICY', value)
+
+# server handlers
+
+class _RootHandler:
+ def __init__(self, options):
+ self.options = options
+
+ def __call__(self, config):
+ """ Mutate the configuration with defaults and perform
+ fixups of values that require knowledge about configuration
+ values outside of their context. """
+
+ # set up cgi overrides
+ env = {}
+ for pair in config.cgi_environment_variables:
+ key, value = pair
+ self._env[key] = value
+ config.cgi_environment_variables = env
+
+ # set up server factories
+ factory = ServerFactoryFactory(config)
+ l = []
+
+ for section in config.servers:
+ # XXX ugly; need to clean this up soon
+ server_type = section.getSectionType().replace("-", "_")
+ for server_factory in getattr(factory, server_type)(section):
+ l.append((server_type, server_factory))
+
+ # if no servers are defined, create default http server and ftp server
+ if not l:
+ class dummy:
+ pass
+ http, ftp = dummy(), dummy()
+
+ http.ports = [('', 8080)]
+ http.force_connection_close = 0
+ ftp.ports = [('', 8021)]
+
+ http = factory.http_server(http)[0]
+ ftp = factory.ftp_server(ftp)[0]
+ l.extend([('http_server', http), ('ftp_server', ftp)])
+
+ config.servers = l
+
+ # set up defaults for zope_home and client_home if they're
+ # not in the config
+ if config.zope_home is None:
+ config.zope_home = zope_home(
+ os.path.dirname(os.path.dirname(config.software_home))
+ )
+ if config.client_home is None:
+ config.client_home = client_home(
+ os.path.join(config.instance_home, 'var')
+ )
+
+ # set up defaults for pid_filename and lock_filename if they're
+ # not in the config
+ if config.pid_filename is None:
+ config.pid_filename = os.path.join(config.client_home, 'Z2.pid')
+ if config.lock_filename is None:
+ config.lock_filename = os.path.join(config.client_home, 'Z2.lock')
+
+ # set up a default root filestorage if there are no root storages
+ # mentioned in the config
+ databases = config.databases
+ root_mounts = [ ('/' in db.mount_points) for db in databases ]
+ if not True in root_mounts:
+ from datatypes import DBWrapper, Factory
+ storagefactory = Factory(
+ 'ZODB.FileStorage.FileStorage', None,
+ os.path.join(config.client_home, 'Data.fs'))
+ dbfactory = Factory('ZODB.DB', None)
+ databases.append((['/'], DBWrapper(dbfactory, storagefactory)))
+
+ # do command-line overrides
+ import cmdline
+ opt_processor = cmdline.CommandLineOptions()
+ opt_processor(config, self.options)
+
+class ServerFactoryFactory:
+ def __init__(self, config):
+ self._config = config
+ # alias some things for use in server handlers
+ from zLOG.AccessLogger import access_logger
+ self._logger = access_logger
+ import ZODB # :-( required to import user
+ from AccessControl.User import emergency_user
+ if hasattr(emergency_user, '__null_user__'):
+ self._pw = None
+ else:
+ self._pw = emergency_user._getPassword()
+ self._resolver = self.get_dns_resolver()
+ self._read_only = config.zserver_read_only_mode
+ self._default_ip = config.ip_address
+ self._env = config.cgi_environment_variables
+ self._module = 'Zope' # no longer settable
+
+ def get_dns_resolver(self):
+ if self._config.dns_ip_address:
+ from ZServer import resolver
+ return resolver.caching_resolver(self._config.dns_ip_address)
+
+ def http_server(self, section):
+ l = []
+ from ZServer import zhttp_server, zhttp_handler
+ for addr, port in section.ports:
+ def callback(inst, self=self):
+ handler = zhttp_handler(self._module, '', self._env)
+ inst.install_handler(handler)
+ if section.force_connection_close:
+ handler._force_connection_close = 1
+ serverfactory = Factory('ZServer.zhttp_server', callback,
+ ip=addr, port=port,
+ resolver=self._resolver,
+ logger_object=self._logger)
+ l.append(serverfactory)
+ return l
+
+ def webdav_source_server(self, section):
+ l = []
+ for addr, port in section.ports:
+ def callback(inst, self=self):
+ from ZServer.WebDAVSrcHandler import WebDAVSrcHandler
+ handler = WebDAVSrcHandler(self._module, '', self._env)
+ inst.install_handler(handler)
+ if section.force_connection_close:
+ handler._force_connection_close = 1
+ serverfactory = Factory('ZServer.zhttp_server', callback,
+ ip=addr, port=port,
+ resolver=self._resolver,
+ logger_object=self._logger)
+ l.append(serverfactory)
+ return l
+
+ def ftp_server(self, section):
+ l = []
+ for addr, port in section.ports:
+ serverfactory = Factory('ZServer.FTPServer', None,
+ module=self._module, ip=addr, port=port,
+ resolver=self._resolver,
+ logger_object=self._logger)
+ l.append(serverfactory)
+ return l
+
+ def pcgi_server(self, section):
+ if not self._read_only:
+ serverfactory = Factory('ZServer.PCGIServer', None,
+ module=self._module,
+ ip=self._default_ip,
+ pcgi_file=section.file,
+ resolver=self._resolver,
+ logger_object=self._logger)
+ return [serverfactory]
+ return []
+
+ def fcgi_server(self, section):
+ if section.file and section.port:
+ raise ValueError, ("Must specify either 'port' or 'file' in "
+ "fcgi server configuration, but not both")
+ if section.port:
+ addr = section.port[0]
+ port = section.port[1]
+ else:
+ addr = port = None
+ file = section.file
+ if not self._read_only:
+ serverfactory = Factory('ZServer.FCGIServer', None,
+ module=self._module, ip=addr, port=port,
+ socket_file=file, resolver=self._resolver,
+ logger_object=self._logger)
+ return [serverfactory]
+ return []
+
+ def monitor_server(self, section):
+ if self._pw is None:
+ import zLOG
+ zLOG.LOG("z2", zLOG.WARNING, 'Monitor server not started'
+ ' because no emergency user exists.')
+ return []
+ l = []
+ for addr, port in section.ports:
+ serverfactory = Factory('ZServer.secure_monitor_server', None,
+ password=self._pw,
+ hostname=addr,
+ port=port)
+ l.append(serverfactory)
+ return l
+
+ def icp_server(self, section):
+ l = []
+ for addr, port in section.ports:
+ serverfactory = Factory('ZServer.ICPServer.ICPServer', None,
+ addr, port)
+ l.append(serverfactory)
+ return l
+
+def handleConfig(config, multihandler, options):
+ handlers = {}
+ for name, value in globals().items():
+ if not name.startswith('_'):
+ handlers[name] = value
+ root_handler = _RootHandler(options)
+ handlers['root_handler'] = root_handler
+ return multihandler(handlers)
=== Zope/lib/python/Zope/Startup/zopeschema.xml 1.1 => 1.2 ===
--- /dev/null Wed Jan 29 15:25:49 2003
+++ Zope/lib/python/Zope/Startup/zopeschema.xml Wed Jan 29 15:25:15 2003
@@ -0,0 +1,232 @@
+<schema prefix="Zope.Startup.datatypes" handler="root_handler">
+
+ <!-- type definitions -->
+
+ <import package="zLOG"/>
+
+
+ <abstracttype name="server"/>
+
+ <sectiontype name="http-server"
+ implements="server">
+ <multikey name="port" attribute="ports" datatype="inet-address"/>
+ <key name="force-connection-close" datatype="boolean" default="off"/>
+ </sectiontype>
+
+ <sectiontype name="ftp-server"
+ implements="server">
+ <multikey name="port" attribute="ports" datatype="inet-address"/>
+ </sectiontype>
+
+ <sectiontype name="webdav-source-server"
+ implements="server">
+ <multikey name="port" attribute="ports" datatype="inet-address"/>
+ <key name="force-connection-close" datatype="boolean" default="off"/>
+ </sectiontype>
+
+ <sectiontype name="pcgi-server"
+ implements="server">
+ <key name="file" datatype="existing-file"/>
+ </sectiontype>
+
+ <sectiontype name="fcgi-server"
+ implements="server">
+ <key name="port" datatype="inet-address"/>
+ <key name="file" datatype="existing-dirpath"/>
+ </sectiontype>
+
+ <sectiontype name="monitor-server"
+ implements="server">
+ <multikey name="port" attribute="ports" datatype="inet-address"/>
+ </sectiontype>
+
+ <sectiontype name="icp-server"
+ implements="server">
+ <multikey name="port" attribute="ports" datatype="inet-address"/>
+ </sectiontype>
+
+
+ <sectiontype name="logger" datatype=".logger">
+ <description>
+ This "logger" type only applies to access and request ("trace")
+ logging; event logging is handled by the zLOG package, which
+ provides the loghandler type used here.
+ </description>
+ <key name="level" datatype="zLOG.datatypes.logging_level" default="info"/>
+ <multisection type="loghandler" attribute="handlers" name="*"
+ required="yes"/>
+ </sectiontype>
+
+ <!-- the types that follow will be replaced by an import from the
+ ZODB package -->
+ <abstracttype name="storage"/>
+
+ <sectiontype name="filestorage" datatype=".filestorage"
+ implements="storage">
+ <key name="path" required="yes"/>
+ <key name="create" datatype="boolean"/>
+ <key name="read-only" datatype="boolean"/>
+ <key name="stop"/>
+ <key name="quota" datatype="byte-size"/>
+ </sectiontype>
+
+ <sectiontype name="mappingstorage" datatype=".mappingstorage"
+ implements="storage">
+ <key name="name" default="Mapping Storage"/>
+ </sectiontype>
+
+ <sectiontype name="clientstorage" datatype=".clientstorage"
+ implements="storage">
+ <key name="addr" datatype="inet-address" required="yes"/>
+ <key name="storage" default="1"/>
+ <key name="cache-size" datatype="byte-size" default="20MB"/>
+ <key name="name" default=""/>
+ <key name="client"/>
+ <key name="debug" datatype="boolean"/>
+ <key name="var" datatype="existing-directory"/>
+ <key name="min-disconnect-poll" datatype="time-interval" default="5S"/>
+ <key name="max-disconnect-poll" datatype="time-interval" default="300S"/>
+ <key name="wait" datatype="boolean" default="on"/>
+ <key name="read-only" datatype="boolean" default="off"/>
+ <key name="read-only-fallback" datatype="boolean" default="off"/>
+ </sectiontype>
+
+
+ <sectiontype name="zodb" datatype=".database">
+ <multisection type="storage" name="*" attribute="storages"/>
+ <multikey name="mount-point" attribute="mount_points"
+ datatype=".mount_point"/>
+ <key name="db-class" default="ZODB.DB"/>
+ <key name="cache-size" datatype="integer" default="5000"/>
+ <key name="pool-size" datatype="integer" default="7"/>
+ <key name="cache-deactivate-after" datatype="time-interval" default="60S"/>
+ <key name="version-pool-size" datatype="integer" default="3"/>
+ <key name="version-cache-size" datatype="integer" default="100"/>
+ <key name="version-cache-deactivate-after" datatype="time-interval"
+ default="10S"/>
+ </sectiontype>
+
+ <!-- end of type definitions -->
+
+ <!-- schema begins -->
+
+ <key name="instance-home" datatype="existing-directory"
+ required="yes" handler="instance_home"/>
+
+ <key name="software-home" datatype="existing-directory"
+ required="yes" handler="software_home"/>
+
+ <key name="zope-home" datatype="existing-directory"
+ handler="zope_home"/>
+
+ <key name="client-home" datatype="existing-directory"
+ handler="client_home"/>
+
+ <key name="pid-filename" datatype="existing-dirpath"/>
+
+ <key name="lock-filename" datatype="existing-dirpath"/>
+
+ <key name="debug-mode" datatype="boolean" default="on"
+ handler="debug_mode"/>
+
+ <key name="effective-user"/>
+
+ <key name="enable-product-installation" datatype="boolean" default="on"
+ handler="enable_product_installation"/>
+
+ <key name="locale" datatype="locale" handler="locale"/>
+
+ <key name="zserver-threads" datatype="integer" default="4"/>
+
+ <key name="python-check-interval" datatype="integer" default="500">
+ <description>
+ Value passed to Python's sys.setcheckinterval() function. The
+ higher this is, the less frequently the Python interpreter
+ checks for keyboard interrupts. Setting this to higher values
+ also reduces the frequency of potential thread switches, which
+ can improve the performance of a busy server.
+ </description>
+ </key>
+
+ <key name="use-daemon-process" datatype=".use_daemon_process" default="on"
+ handler="use_daemon_process"/>
+
+ <key name="zserver-read-only-mode" datatype="boolean" default="off"
+ handler="zserver_read_only_mode"/>
+
+ <key name="structured-text-header-level" datatype="integer" default="3"
+ handler="structured_text_header_level"/>
+
+ <key name="maximum-security-manager-stack-size" datatype="integer"
+ default="100" handler="maximum_security_manager_stack_size"/>
+
+ <key name="publisher-profile-file" handler="publisher_profile_file"/>
+
+ <key name="webdav-source-user-agents"/>
+
+ <multikey name="cgi-environment-variable" datatype="key-value"
+ attribute="cgi_environment_variables"/>
+
+ <key name="dns-ip-address" datatype="ipaddr-or-hostname"/>
+
+ <key name="ip-address" datatype="ipaddr-or-hostname"/>
+
+ <key name="http-realm" default="Zope" handler="http_realm"/>
+
+ <key name="automatically-quote-dtml-request-data" datatype="boolean"
+ default="on" handler="automatically_quote_dtml_request_data"/>
+
+ <key name="security-policy-implementation"
+ datatype=".security_policy_implementation"
+ default="C" handler="security_policy_implementation"/>
+
+ <key name="skip-authentication-checking" datatype="boolean"
+ default="off" handler="skip_authentication_checking"/>
+
+ <key name="skip-ownership-checking" datatype="boolean"
+ default="off" handler="skip_ownership_checking"/>
+
+ <key name="maximum-number-of-session-objects" datatype="integer"
+ default="1000" handler="maximum_number_of_session_objects"/>
+
+ <key name="session-add-notify-script-path"
+ handler="session_add_notify_script_path"/>
+
+ <key name="session-delete-notify-script-path"
+ handler="session_add_notify_script_path"/>
+
+ <key name="session-timeout-minutes" datatype="integer"
+ default="20" handler="session_timeout_minutes"/>
+
+ <key name="suppress-all-access-rules" datatype="boolean"
+ default="off" handler="suppress_all_access_rules"/>
+
+ <key name="suppress-all-site-roots" datatype="boolean"
+ default="off" handler="suppress_all_site_roots"/>
+
+ <key name="database-quota-size" datatype="byte-size"
+ handler="database_quota_size"/>
+
+ <key name="read-only-database" datatype="boolean"
+ handler="read_only_database"/>
+
+ <key name="zeo-client-name"
+ handler="zeo_client_name"/>
+
+ <section type="eventlog" name="*" attribute="eventlog">
+ <description>
+ Describes the logging performed by zLOG.LOG() calls.
+ </description>
+ </section>
+
+ <section type="logger" name="access"/>
+
+ <section type="logger" name="trace"/>
+
+ <multisection type="server" name="*" attribute="servers"/>
+
+ <multisection type="zodb" name="*" attribute="databases"/>
+
+ <!-- schema ends -->
+
+</schema>