Commit f8cde89a authored by Chris McDonough's avatar Chris McDonough

Import tempstorage from its new location instead of from TemporaryFolder.

Implement new "environment" section in config file which allows the
setting of environment variables within the configuration file.

Implement new "path" section in config file which allows insertions into
the Python module search path within the configuration file.

Fix bug where $INSTANCE/Products was not inserted into the products
path by default.

Note that most of these changes are for more comprehensive Windows service
support.  Windows can't run a batch file as a service, and sometimes it
is necessary to both munge the python module search path and environment
at startup time.  Instead of writing an executable application to do this,
we rely on the configuration machinery.
parent 9ca3435d
...@@ -126,6 +126,8 @@ def root_config(section): ...@@ -126,6 +126,8 @@ def root_config(section):
swhome = os.path.dirname(os.path.dirname(here)) swhome = os.path.dirname(os.path.dirname(here))
section.softwarehome = swhome section.softwarehome = swhome
section.zopehome = os.path.dirname(os.path.dirname(swhome)) section.zopehome = os.path.dirname(os.path.dirname(swhome))
if section.environment is None:
section.environment = {}
if section.cgi_environment is None: if section.cgi_environment is None:
section.cgi_environment = {} section.cgi_environment = {}
if section.clienthome is None: if section.clienthome is None:
...@@ -223,7 +225,7 @@ def getDefaultDatabaseFactories(context): ...@@ -223,7 +225,7 @@ def getDefaultDatabaseFactories(context):
# and a temporary storage for session data # and a temporary storage for session data
from ZODB.Connection import Connection from ZODB.Connection import Connection
from ZODB.config import FileStorage from ZODB.config import FileStorage
from Products.TemporaryFolder.config import TemporaryStorage from tempstorage.config import TemporaryStorage
l = [] l = []
class dummy: class dummy:
...@@ -248,7 +250,8 @@ def getDefaultDatabaseFactories(context): ...@@ -248,7 +250,8 @@ def getDefaultDatabaseFactories(context):
l.append(main) l.append(main)
ts = dummy('temporary storage for sessioning') ts = dummy('temporary storage for sessioning')
temporary = ZopeDatabase(dummy('temporary', storage=TemporaryStorage(ts), temporary = ZopeDatabase(dummy('temporary',
storage=TemporaryStorage(ts),
cache_size=5000, pool_size=7, cache_size=5000, pool_size=7,
version_pool_size=3, version_cache_size=100, version_pool_size=3, version_cache_size=100,
mount_points=['/temp_folder'], mount_points=['/temp_folder'],
......
import os import os
import sys
# top-level key handlers # top-level key handlers
...@@ -126,15 +127,33 @@ def root_handler(config): ...@@ -126,15 +127,33 @@ def root_handler(config):
fixups of values that require knowledge about configuration fixups of values that require knowledge about configuration
values outside of their context. """ values outside of their context. """
# Set environment variables
for k,v in config.environment.items():
os.environ[k] = v
# Add directories to the pythonpath; always insert instancehome/lib/python
instancelib = os.path.join(config.instancehome, 'lib', 'python')
if instancelib not in config.path:
config.path.append(instancelib)
path = config.path[:]
path.reverse()
for dir in path:
sys.path.insert(0, dir)
# Add any product directories not already in Products.__path__. # Add any product directories not already in Products.__path__.
# Directories are added in the order # Directories are added in the order they are mentioned
if config.products: # Always insert instancehome.Products
import Products
L = [] instanceprod = os.path.join(config.instancehome, 'Products')
for d in config.products + Products.__path__: if instanceprod not in config.products:
if d not in L: config.products.append(instanceprod)
L.append(d)
Products.__path__[:] = L import Products
L = []
for d in config.products + Products.__path__:
if d not in L:
L.append(d)
Products.__path__[:] = L
# if no servers are defined, create default http server and ftp server # if no servers are defined, create default http server and ftp server
if not config.servers: if not config.servers:
......
...@@ -54,7 +54,7 @@ class StartupTestCase(unittest.TestCase): ...@@ -54,7 +54,7 @@ class StartupTestCase(unittest.TestCase):
os.rmdir(TEMPPRODUCTS) os.rmdir(TEMPPRODUCTS)
os.rmdir(TEMPNAME) os.rmdir(TEMPNAME)
self.assertEqual(conf.instancehome, TEMPNAME) self.assertEqual(conf.instancehome, TEMPNAME)
return conf return conf, handler
def test_load_config_template(self): def test_load_config_template(self):
schema = self.schema schema = self.schema
...@@ -66,7 +66,7 @@ class StartupTestCase(unittest.TestCase): ...@@ -66,7 +66,7 @@ class StartupTestCase(unittest.TestCase):
self.load_config_text(text) self.load_config_text(text)
def test_cgi_environment(self): def test_cgi_environment(self):
conf = self.load_config_text("""\ conf, handler = self.load_config_text("""\
# instancehome is here since it's required # instancehome is here since it's required
instancehome <<INSTANCE_HOME>> instancehome <<INSTANCE_HOME>>
<cgi-environment> <cgi-environment>
...@@ -78,9 +78,32 @@ class StartupTestCase(unittest.TestCase): ...@@ -78,9 +78,32 @@ class StartupTestCase(unittest.TestCase):
items.sort() items.sort()
self.assertEqual(items, [("ANOTHER", "value2"), ("HEADER", "value")]) self.assertEqual(items, [("ANOTHER", "value2"), ("HEADER", "value")])
def test_environment(self):
conf, handler = self.load_config_text("""\
# instancehome is here since it's required
instancehome <<INSTANCE_HOME>>
<environment>
FEARFACTORY rocks
NSYNC doesnt
</environment>
""")
items = conf.environment.items()
items.sort()
self.assertEqual(items, [("FEARFACTORY", "rocks"), ("NSYNC","doesnt")])
def test_path(self):
conf, handler = self.load_config_text("""\
# instancehome is here since it's required
instancehome <<INSTANCE_HOME>>
path /foo/bar
path /baz/bee
""")
items = conf.path
self.assertEqual(items, ['/foo/bar', '/baz/bee'])
def test_access_and_trace_logs(self): def test_access_and_trace_logs(self):
fn = tempfile.mktemp() fn = tempfile.mktemp()
conf = self.load_config_text(""" conf, handler = self.load_config_text("""
instancehome <<INSTANCE_HOME>> instancehome <<INSTANCE_HOME>>
<logger access> <logger access>
<logfile> <logfile>
...@@ -95,14 +118,14 @@ class StartupTestCase(unittest.TestCase): ...@@ -95,14 +118,14 @@ class StartupTestCase(unittest.TestCase):
def test_dns_resolver(self): def test_dns_resolver(self):
from ZServer.medusa import resolver from ZServer.medusa import resolver
conf = self.load_config_text("""\ conf, handler = self.load_config_text("""\
instancehome <<INSTANCE_HOME>> instancehome <<INSTANCE_HOME>>
dns-server localhost dns-server localhost
""") """)
self.assert_(isinstance(conf.dns_resolver, resolver.caching_resolver)) self.assert_(isinstance(conf.dns_resolver, resolver.caching_resolver))
def test_zodb_db(self): def test_zodb_db(self):
conf = self.load_config_text("""\ conf, handler = self.load_config_text("""\
instancehome <<INSTANCE_HOME>> instancehome <<INSTANCE_HOME>>
<zodb_db main> <zodb_db main>
<filestorage> <filestorage>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<import package="zLOG"/> <import package="zLOG"/>
<import package="ZODB"/> <import package="ZODB"/>
<import package="ZServer"/> <import package="ZServer"/>
<import package="Products.TemporaryFolder"/> <import package="tempstorage"/>
<sectiontype name="logger" datatype=".LoggerFactory"> <sectiontype name="logger" datatype=".LoggerFactory">
<description> <description>
...@@ -34,6 +34,20 @@ ...@@ -34,6 +34,20 @@
</key> </key>
</sectiontype> </sectiontype>
<sectiontype name="environment"
datatype=".cgi_environment"
keytype="identifier">
<description>
A section which allows you to define simple key-value pairs which
will be used as environment variable settings during startup.
</description>
<key name="+" attribute="environ">
<description>
Use any key/value pair, e.g. 'MY_PRODUCT_ENVVAR foo_bar'
</description>
</key>
</sectiontype>
<sectiontype name="zoperunner"> <sectiontype name="zoperunner">
<description> <description>
This section describes the options for zopectl. These options This section describes the options for zopectl. These options
...@@ -184,6 +198,15 @@ ...@@ -184,6 +198,15 @@
<!-- schema begins --> <!-- schema begins -->
<section type="environment" attribute="environment" name="*">
<description>
A section which allows a user to define arbitrary key-value pairs for
use as environment variables during Zope's run cycle. It
is not recommended to set system-related environment variables such as
PYTHONPATH within this section.
</description>
</section>
<key name="instancehome" datatype="existing-directory" <key name="instancehome" datatype="existing-directory"
required="yes"> required="yes">
<description> <description>
...@@ -207,6 +230,28 @@ ...@@ -207,6 +230,28 @@
<metadefault>$instancehome/var</metadefault> <metadefault>$instancehome/var</metadefault>
</key> </key>
<multikey name="products" datatype="existing-directory">
<description>
This specifies additional product directories which are added to
Products.__path__. Directories are added in the order in which
they are specified.
</description>
<metadefault>$instancehome/Products</metadefault>
</multikey>
<multikey name="path" datatype="existing-directory">
<description>
This specifies additional paths directories which are inserted into
the beginning of Python's module search path. The set of directories
specified is inserted into the beginning of the module search path in
the order which they are specified here. Note that the processing of
this directive may happen too late under some circumstances; it is
recommended that you use the PYTHONPATH environment variable if
using this directive doesn't work for you.
</description>
<metadefault>$instancehome/lib/python</metadefault>
</multikey>
<key name="pid-filename" datatype="existing-dirpath"> <key name="pid-filename" datatype="existing-dirpath">
<description> <description>
The full path to which the Zope process will write its The full path to which the Zope process will write its
...@@ -325,15 +370,6 @@ ...@@ -325,15 +370,6 @@
</description> </description>
</key> </key>
<multikey name="products" datatype="existing-directory">
<description>
This specifies additional product directories which are added to
Products.__path__. Directories are added in the order in which
they are specified.
</description>
<metadefault>$instancehome/Products</metadefault>
</multikey>
<key name="structured-text-header-level" datatype="integer" default="3" <key name="structured-text-header-level" datatype="integer" default="3"
handler="structured_text_header_level"> handler="structured_text_header_level">
<description> <description>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment