[Zope-Checkins] CVS: Zope/lib/python/Zope/Startup - ZctlLib.py:1.1.2.1 __init__.py:1.1.2.1 datatypes.py:1.1.2.1 handlers.py:1.1.2.1 zopeschema.xml:1.1.2.1
Chris McDonough
chrism@zope.com
Sat, 4 Jan 2003 23:01:41 -0500
Update of /cvs-repository/Zope/lib/python/Zope/Startup
In directory cvs.zope.org:/tmp/cvs-serv4133
Added Files:
Tag: chrism-install-branch
ZctlLib.py __init__.py datatypes.py handlers.py zopeschema.xml
Log Message:
Adding Startup to Zope package (moved from software_home).
=== Added File Zope/lib/python/Zope/Startup/ZctlLib.py === (644/744 lines abridged)
##############################################################################
#
# 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: 1.1.2.1 $'[11:-2]
import getopt
import os
import sys
import re
import signal
import cmd
import time
try:
import readline
except:
readline = None
from Zope.Startup import getSchemaKeys, configure
from Zope.Startup.misc import TextBlockFormatter
from Zope.Startup.misc.lock_file import lock_file
_marker = []
USAGE = """\
zctl: Zope appserver controller
Usage:
zctl [-h | --help] [--config=filepath or url]
Options:
-h or --help Print this message. Not compatible with the 'start'
or 'restart' command.
--config Use an alternate configuration from a local file.
or a URL. Default: 'zope.conf'.
[-=- -=- -=- 644 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
=== Added File Zope/lib/python/Zope/Startup/__init__.py ===
""" Startup package. Responsible for startup configuration of Zope """
import os
import sys
import socket
import re
import types
from ZConfig import ConfigurationError
from ZConfig import loadSchema, loadConfig
from misc.lock_file import lock_file
# global to hold config structure
_configuration = None
def getConfiguration():
return _configuration
def getSchemaLocation():
here = os.path.dirname(__file__)
schema = os.path.join(here, 'zopeschema.xml')
return schema
def getSchemaKeys():
f = getSchemaLocation()
schema = loadSchema(f)
return schema.getchildnames()
def configure(config_location, overrides):
f = getSchemaLocation()
schema = loadSchema(f)
import handlers
config, handler = loadConfig(schema, config_location)
handlers.handleConfig(config, handler)
## for name, value in overrides.items():
## key = config.getSub(KEY_TYPE, KEY_TYPE, name)
## key.setValue(value)
global _configuration
_configuration = config
return _configuration
def start_zope(config_location, overrides):
# caller must set configuration
check_python_version()
cfg = configure(config_location, overrides)
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 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 ('event', 'access', 'trace'):
factory = getattr(cfg, logger_name, None)
if factory:
logger = factory() # activate the logger
# flush buffered startup messages to event logger
if logger_name == 'event':
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
# too chicken to preclude 2.1 yet
python_version = sys.version.split()[0]
optimum_version = '2.2.2'
if python_version < '2.1':
raise ConfigurationError, 'Invalid python version %s' % python_version
if python_version[:3] == '2.1':
err = ('You are running Python version %s. Zope may work under this '
'Python version, but it may not. Consider upgrading to '
'Python %s\n' % (python_version, optimum_version))
sys.stderr.write(err)
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 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, types.StringType):
uid = pwd.getpwnam(UID)[2]
gid = pwd.getpwnam(UID)[3]
elif isinstance(UID, types.IntType):
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 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, pidfile=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 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 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
)
=== Added File Zope/lib/python/Zope/Startup/datatypes.py ===
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
# log-related datatypes
def log_format(value):
d = {
'name':'',
'levelno':'3',
'levelname':'DEBUG',
'pathname':'apath',
'filename':'afile',
'module':'amodule',
'lineno':1,
'created':1.1,
'asctime':'atime',
'msecs':1,
'relativeCreated':1,
'thread':1,
'message':'amessage',
}
try:
value % d
except (ValueError, KeyError):
raise ValueError, 'Invalid log format string %s' % value
value = ctrl_char_insert(value)
return value
def ctrl_char_insert(value):
chars = {r'\n':'\n', r'\t':'\t', r'\b':'\b', r'\f':'\f', r'\r':'\r'}
realvalue = value
for char in chars.keys():
l = realvalue.split(char)
realvalue = chars[char].join(l)
return realvalue
def file_handler(section):
file = section.file
format = section.format
dateformat = section.dateformat
level = section.level
formatter = Factory('logging.Formatter', None, format, dateformat)
def callback(inst, formatter=formatter, level=level):
inst.setFormatter(formatter())
inst.setLevel(level)
return Factory('zLOG.LogHandlers.FileHandler', callback, file)
def syslog_facility(value):
d = {
"auth":1,
"authpriv":1,
"cron":1,
"daemon":1,
"kern":1,
"lpr":1,
"mail":1,
"news":1,
"security":1,
"syslog":1,
"user":1,
"uucp":1,
"local0":1,
"local1":1,
"local2":1,
"local3":1,
"local4":1,
"local5":1,
"local6":1,
"local7":1,
}
value = value.lower()
if not d.has_key(value):
raise ValueError, "Syslog facility must be one of %s" % d.keys()
return value
def syslog_handler(section):
facility = section.facility
socket = section.socket
host = section.host
port = section.port
format = section.format
dateformat = section.dateformat
level = section.level
if socket and host:
raise ValueError, ('Only one of "socket" or "host" may be '
'specified in a syslog_handler section')
if not (socket or host):
raise ValueError, ('One of "socket" or "host" must be '
'specified in a syslog_handler section')
formatter = Factory('logging.Formatter', None, format, dateformat)
def callback(inst, formatter=formatter, level=level):
inst.setFormatter(formatter())
inst.setLevel(level)
klass = 'zLOG.LogHandlers.SysLogHandler'
if socket:
handler = Factory(klass, callback, socket, facility)
else:
handler = Factory(klass, callback, (host, port), facility)
return handler
def nteventlog_handler(section):
appname = section.appname
format = section.format
dateformat = section.dateformat
level = section.level
formatter = Factory('logging.Formatter', None, format, dateformat)
def callback(inst, formatter=formatter, level=level):
inst.setFormatter(formatter())
inst.setLevel(level)
return Factory('zLOG.LogHandlers.NTEventLogHandler', callback, appname)
def http_handler_url(value):
import urlparse
scheme, netloc, path, query, fragment = urlparse.urlsplit(value)
if scheme != 'http':
raise ValueError, 'url must be an http url'
if not netloc:
raise ValueError, 'url must specify a location'
if not path:
raise ValueError, 'url must specify a path'
q = []
if query:
q.append('?')
q.append(query)
if fragment:
q.append('#')
q.append(fragment)
return (netloc, path + ''.join(q))
def get_or_post(value):
value = value.upper()
if value not in ('GET', 'POST'):
raise ValueError, ('method must be "GET" or "POST", instead received '
'%s' % value)
return value
def http_handler(section):
host, url = section.url
method = section.method
format = section.format
dateformat = section.dateformat
level = section.level
formatter = Factory('logging.Formatter', None, format, dateformat)
def callback(inst, formatter=formatter, level=level):
inst.setFormatter(formatter())
inst.setLevel(level)
return Factory('zLOG.LogHandlers.HTTPHandler', callback, host, url, method)
def smtp_handler(section):
fromaddr = section.fromaddr
toaddrs = section.toaddrs
subject = section.subject
host, port = section.host
format = section.format
dateformat = section.dateformat
level = section.level
if not port:
mailhost = host
else:
mailhost = host, port
formatter = Factory('logging.Formatter', None, format, dateformat)
def callback(inst, formatter=formatter, level=level):
inst.setFormatter(formatter())
inst.setLevel(level)
return Factory('zLOG.LogHandlers.SMTPHandler', callback,
mailhost, fromaddr, toaddrs, subject)
def null_handler(section):
return Factory('zLOG.LogHandlers.NullHandler', None)
def custom_handler(section):
formatter_klass, formatter_pos, formatter_kw = section.formatter
handler_klass, handler_pos, handler_kw = section.constructor
level = section.level
formatter = Factory(formatter_klass, None, formatter_pos, formatter_kw)
def callback(inst, formatter=formatter, level=level):
inst.setFormatter(formatter())
inst.setLevel(level)
return Factory(handler_klass, callback, *handler_pos, **handler_kw)
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):
file_name = section.file_name
kw = {
'create':section.create,
'read_only':section.read_only,
'stop':section.stop,
'quota':section.quota,
}
return Factory('ZODB.FileStorage.FileStorage', None, file_name, **kw)
def mappingstorage(section):
name = section.name
return Factory('ZODB.MappingStorage.MappingStorage', None, name)
def clientstorage(section):
addr = section.addr
kw = {
'storage':section.create,
'cache_size':section.read_only,
'name':section.stop,
'client':section.quota,
'debug':section.quota,
'var':section.quota,
'min_disconnect_poll':section.quota,
'max_disconnect_poll':section.quota,
'wait':section.wait,
'read_only':section.read_only,
'read_only_fallback':section.read_only_fallback,
}
return Factory('ZEO.ClientStorage.ClientStorage', None, addr, **kw)
_marker = []
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
=== Added File Zope/lib/python/Zope/Startup/handlers.py ===
from misc.factory import Factory
import os
from os.path import dirname
pjoin = os.path.join
import types
# top-level key handlers
def _setenv(name, value):
if ( type(value) is types.StringType or
type(value) is types.UnicodeType ):
os.environ[name] = value
else:
os.environ[name] = `value`
def _append_slash(value):
if value is None:
return None
if not value.endswith('/'):
return value + '/'
return value
def null(value):
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 __call__(self, config):
""" Mutate the configuration with defaults and perform
fixups of values that require knowledge about configuration
values outside of their context. """
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._module = 'Zope' # no longer settable
# set up cgi overrides
self._env = {}
for pair in config.cgi_environment_variables:
key, value = pair
self._env[key] = value
config.cgi_environment_variables = self._env
# set up server factories via dispatch
l = []
for section in config.servers:
server_type = section.__type__.name
for server_factory in getattr(self, 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 = self.http_server(http)[0]
ftp = self.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(
dirname(dirname(config.software_home))
)
if config.client_home is None:
config.client_home = client_home(
pjoin(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 = pjoin(config.client_home, 'Z2.pid')
if config.lock_filename is None:
config.lock_filename = pjoin(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,
*[pjoin(config.client_home, 'Data.fs')], **{}
)
dbfactory = Factory('ZODB.DB', None, *[], **{})
databases.append((['/'], DBWrapper(dbfactory, storagefactory)))
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:
kw = make_dict(ip=addr, port=port,
resolver=self._resolver,
logger_object=self._logger)
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, *[], **kw)
l.append(serverfactory)
return l
def webdav_source_server(self, section):
l = []
for addr, port in section.ports:
kw = make_dict(ip=addr, port=port,
resolver=self._resolver,
logger_object=self._logger)
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, *[], **kw)
l.append(serverfactory)
return l
def ftp_server(self, section):
l = []
for addr, port in section.ports:
kw = make_dict(module=self._module, ip=addr, port=port,
resolver=self._resolver,
logger_object=self._logger)
serverfactory=Factory('ZServer.FTPServer', None, *[], **kw)
l.append(serverfactory)
return l
def pcgi_server(self, section):
if not self._read_only:
kw = make_dict(module=self._module,
ip=self._default_ip, pcgi_file=section.file,
resolver=self._resolver,
logger_object=self._logger)
serverfactory = Factory('ZServer.PCGIServer', None, *[], **kw)
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:
kw = make_dict(module=self._module, ip=addr, port=port,
socket_file=file, resolver=self._resolver,
logger_object=self._logger)
serverfactory = Factory('ZServer.FCGIServer', None, *[], **kw)
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:
kw = make_dict(password=self._pw, hostname=addr, port=port)
serverfactory = Factory(
'ZServer.secure_monitor_server', None, *[], **kw)
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
root_handler = _RootHandler()
def handleConfig(config, multihandler):
handlers = {}
for name, value in globals().items():
if not name.startswith('_'):
handlers[name] = value
return multihandler(handlers)
def make_dict(**kw):
return kw
=== Added File Zope/lib/python/Zope/Startup/zopeschema.xml ===
<schema prefix="Zope.Startup.datatypes" handler="root_handler">
<!-- type definitions -->
<sectiongroup type="handler">
<sectiontype type="file_handler" datatype=".file_handler">
<key name="file" required="yes"/>
<key name="format" default="------\n%(asctime)s %(message)s"
datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype="logging-level"/>
</sectiontype>
<sectiontype type="syslog_handler" datatype=".syslog_handler">
<key name="facility" default="user" datatype=".syslog_facility"/>
<key name="socket" datatype="existing-file"/>
<key name="port" default="514" datatype="port-number"/>
<key name="host" datatype="ipaddr-or-hostname"/>
<key name="format" default="%(message)s"
datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype="logging-level"/>
</sectiontype>
<sectiontype type="nteventlog_handler" datatype=".nteventlog_handler">
<key name="appname" default="Zope"/>
<key name="format" default="%(message)s"
datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype="logging-level"/>
</sectiontype>
<sectiontype type="http_handler" datatype=".http_handler">
<key name="url" default="localhost" datatype=".http_handler_url"/>
<key name="method" default="GET" datatype=".get_or_post"/>
<key name="format" default="%(asctime)s %(message)s"
datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype="logging-level"/>
</sectiontype>
<sectiontype type="smtp_handler" datatype=".smtp_handler">
<key name="fromaddr" required="yes"/>
<multikey name="toaddr" required="yes" attribute="toaddrs"/>
<key name="subject" default="Message from Zope"/>
<key name="host" default="localhost" datatype="inet-address"/>
<key name="format" default="%(asctime)s %(message)s"
datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype="logging-level"/>
</sectiontype>
<sectiontype type="null_handler" datatype=".null_handler">
</sectiontype>
<sectiontype type="custom_handler" datatype=".custom_handler">
<key name="constructor" datatype="constructor" required="yes"/>
<key name="formatter" datatype="constructor"
default="logging.Formatter()"/>
<key name="level" default="info" datatype="logging-level"/>
</sectiontype>
</sectiongroup>
<sectiontype type="logger" datatype=".logger">
<key name="level" datatype="logging-level" default="info"/>
<multisection type="handler" attribute="handlers" name="*"/>
</sectiontype>
<sectiongroup type="server">
<sectiontype type="http_server">
<multikey name="port" attribute="ports" datatype="inet-address"/>
<key name="force_connection_close" datatype="boolean" default="off"/>
</sectiontype>
<sectiontype type="ftp_server">
<multikey name="port" attribute="ports" datatype="inet-address"/>
</sectiontype>
<sectiontype type="webdav_source_server">
<multikey name="port" attribute="ports" datatype="inet-address"/>
<key name="force_connection_close" datatype="boolean" default="off"/>
</sectiontype>
<sectiontype type="pcgi_server">
<key name="file" datatype="existing-file"/>
</sectiontype>
<sectiontype type="fcgi_server">
<key name="port" datatype="inet-address"/>
<key name="file" datatype="existing-dirpath"/>
</sectiontype>
<sectiontype type="monitor_server">
<multikey name="port" attribute="ports" datatype="inet-address"/>
</sectiontype>
<sectiontype type="icp_server">
<multikey name="port" attribute="ports" datatype="inet-address"/>
</sectiontype>
</sectiongroup>
<sectiongroup type="storage">
<sectiontype type="filestorage" datatype=".filestorage">
<key name="file_name" required="yes"/>
<key name="create" datatype="boolean"/>
<key name="read_only" datatype="boolean"/>
<key name="stop"/>
<key name="quota" datatype="integer"/>
</sectiontype>
<sectiontype type="mappingstorage" datatype=".mappingstorage">
<key name="name" default="Mapping Storage"/>
</sectiontype>
<sectiontype type="clientstorage" datatype=".clientstorage">
<key name="addr" datatype="inet-address" required="yes"/>
<key name="storage" default="1"/>
<key name="cache_size" datatype="integer" default="20000000"/>
<key name="name" default=""/>
<key name="client"/>
<key name="debug" datatype="boolean"/>
<key name="var" datatype="existing-directory"/>
<key name="min_disconnect_poll" datatype="integer" default="5"/>
<key name="max_disconnect_poll" datatype="integer" default="300"/>
<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>
</sectiongroup>
<sectiontype type="database" 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="integer" default="60"/>
<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="integer"
default="10"/>
</sectiontype>
<!-- end of type definitions -->
<!-- schema begins -->
<key name="instance_home" datatype="existing-directory"
required="yes"/>
<key name="software_home" datatype="existing-directory"
required="yes"/>
<key name="zope_home" datatype="existing-directory"/>
<key name="client_home" datatype="existing-directory"/>
<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"/>
<key name="use_daemon_process" datatype="boolean" 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="integer"
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="logger" name="event"/>
<section type="logger" name="access"/>
<section type="logger" name="trace"/>
<multisection type="server" name="*" attribute="servers"/>
<multisection type="database" name="*" attribute="databases"/>
<!-- schema ends -->
</schema>