summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2011-03-23 13:16:38 +0000
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2011-03-23 13:16:38 +0000
commit6dce8af0d6e1677950940c11c4b25ec2d1216a79 (patch)
tree6b1c186b65a4fc97b8199124f4ea59ee909cb560
parentfff400379f15390fbf90a75a1748f230bbdf0ee6 (diff)
downloadpykolab-6dce8af0d6e1677950940c11c4b25ec2d1216a79.tar.gz
Enhance configuration subsystem, and drop runtime
-rw-r--r--pykolab/conf/__init__.py203
-rw-r--r--pykolab/conf/defaults.py28
-rw-r--r--pykolab/conf/runtime.py23
3 files changed, 114 insertions, 140 deletions
diff --git a/pykolab/conf/__init__.py b/pykolab/conf/__init__.py
index d1bffd1..ccb0bfe 100644
--- a/pykolab/conf/__init__.py
+++ b/pykolab/conf/__init__.py
@@ -25,23 +25,27 @@ from optparse import OptionParser
from ConfigParser import SafeConfigParser
import pykolab
+
from pykolab.conf.defaults import Defaults
-from pykolab.conf.runtime import Runtime
+
from pykolab.constants import *
from pykolab.translate import _
+log = pykolab.getLogger('pykolab.conf')
+
class Conf(object):
def __init__(self):
"""
- self.args == Arguments passed on the CLI
- self.cli_options == Parser results (again, CLI)
- self.parser == The actual Parser (from OptionParser)
+ self.cli_args == Arguments passed on the CLI
+ self.cli_keywords == Parser results (again, CLI)
+ self.cli_parser == The actual Parser (from OptionParser)
self.plugins == Our Kolab Plugins
"""
- self.args = None
- self.cli_options = None
- self.parser = None
+ self.cli_parser = None
+ self.cli_args = None
+ self.cli_keywords = None
+
self.plugins = None
# The location where our configuration parser is going to end up
@@ -51,6 +55,8 @@ class Conf(object):
self.create_options()
def finalize_conf(self):
+
+ self.create_options_from_plugins()
self.parse_options()
# At this point, 'self' isn't much yet, so:
@@ -64,9 +70,6 @@ class Conf(object):
# Create logger
self.create_logger()
- # Let the logger know about cfg (it needs a ConfigStore instance!)
- self.log.set_config(self)
-
# The defaults can some from;
# - a file we ship with the packages
# - a customly supplied file (by customer)
@@ -78,36 +81,28 @@ class Conf(object):
# But, they should be available in our class as well
for option in self.defaults.__dict__.keys():
- self.log.debug(_("Setting %s to %r (from defaults)") %(option, self.defaults.__dict__[option]), level=9)
+ log.debug(_("Setting %s to %r (from defaults)") %(option, self.defaults.__dict__[option]), level=8)
setattr(self,option,self.defaults.__dict__[option])
# This is where we check our parser for the defaults being set there.
self.set_defaults_from_cli_options()
- # There is also a number of runtime specific variables
- self.runtime = Runtime(self.plugins, self.defaults)
-
- # Which should also be available here
- for option in self.runtime.__dict__.keys():
- self.log.debug(_("Setting %s to %r (from runtime)") %(option, self.runtime.__dict__[option]), level=9)
- setattr(self,option,self.runtime.__dict__[option])
-
self.options_set_from_config()
# Also set the cli options
- for option in self.cli_options.__dict__.keys():
+ for option in self.cli_keywords.__dict__.keys():
if hasattr(self, "check_setting_%s" %(option)):
- exec("retval = self.check_setting_%s(%r)" % (option, self.cli_options.__dict__[option]))
+ exec("retval = self.check_setting_%s(%r)" % (option, self.cli_keywords.__dict__[option]))
# The warning, error or confirmation dialog is in the check_setting_%s() function
if not retval:
continue
- self.log.debug(_("Setting %s to %r (from CLI, verified)") %(option, self.cli_options.__dict__[option]), level=9)
- setattr(self,option,self.cli_options.__dict__[option])
+ log.debug(_("Setting %s to %r (from CLI, verified)") %(option, self.cli_keywords.__dict__[option]), level=8)
+ setattr(self,option,self.cli_keywords.__dict__[option])
else:
- self.log.debug(_("Setting %s to %r (from CLI, not checked)") %(option, self.cli_options.__dict__[option]), level=9)
- setattr(self,option,self.cli_options.__dict__[option])
+ log.debug(_("Setting %s to %r (from CLI, not checked)") %(option, self.cli_keywords.__dict__[option]), level=8)
+ setattr(self,option,self.cli_keywords.__dict__[option])
def load_config(self, config):
"""
@@ -151,9 +146,9 @@ class Conf(object):
if not self.defaults.__dict__[section][key] == value:
setattr(self,"%s_%s" %(section,key),value)
if key.count('password') >= 1:
- self.log.debug(_("Setting %s_%s to '****' (from configuration file)") %(section,key), level=9)
+ log.debug(_("Setting %s_%s to '****' (from configuration file)") %(section,key), level=8)
else:
- self.log.debug(_("Setting %s_%s to %r (from configuration file)") %(section,key,value), level=9)
+ log.debug(_("Setting %s_%s to %r (from configuration file)") %(section,key,value), level=8)
def options_set_from_config(self):
"""
@@ -162,12 +157,12 @@ class Conf(object):
customized using the --config CLI option
"""
- self.log.debug(_("Setting options from configuration file"), level=4)
+ log.debug(_("Setting options from configuration file"), level=4)
# Check from which configuration file we should get the defaults
# Other then default?
- if not self.cli_options.config_file == self.defaults.config_file:
- self.config_file = self.cli_options.config_file
+ if not self.cli_keywords.config_file == self.defaults.config_file:
+ self.config_file = self.cli_keywords.config_file
else:
self.config_file = self.defaults.config_file
@@ -205,9 +200,9 @@ class Conf(object):
setattr(self,"%s_%s" %('testing',key),value)
if key.count('password') >= 1:
- self.log.debug(_("Setting %s_%s to '****' (from configuration file)") %('testing',key), level=9)
+ log.debug(_("Setting %s_%s to '****' (from configuration file)") %('testing',key), level=8)
else:
- self.log.debug(_("Setting %s_%s to %r (from configuration file)") %('testing',key,value), level=9)
+ log.debug(_("Setting %s_%s to %r (from configuration file)") %('testing',key,value), level=8)
def check_config(self, val=None):
"""
@@ -221,20 +216,35 @@ class Conf(object):
config_file = self.config_file
if not os.access(config_file, os.R_OK):
- self.log.error(_("Configuration file %s not readable") % config_file, recoverable=False)
+ log.error(_("Configuration file %s not readable") % config_file, recoverable=False)
config = SafeConfigParser()
- self.log.debug(_("Reading configuration file %s") % config_file, level=9)
+ log.debug(_("Reading configuration file %s") % config_file, level=8)
try:
config.read(config_file)
except:
- self.log.error(_("Invalid configuration file %s") % config_file, recoverable=False)
+ log.error(_("Invalid configuration file %s") % config_file, recoverable=False)
if not config.has_section("kolab"):
- self.log.warning(_("No master configuration section [revisor] in configuration file %s") % config_file)
+ log.warning(_("No master configuration section [revisor] in configuration file %s") % config_file)
return config
+ def add_cli_parser_option_group(self, name):
+ return self.cli_parser.add_option_group(name)
+
+ def create_options_from_plugins(self):
+ """
+ Create options from plugins.
+
+ This function must be called seperately from Conf.__init__(), or
+ the configuration store is not yet done initializing when the
+ plugins class and the plugins themselves go look for it.
+ """
+ import pykolab.plugins
+ self.plugins = pykolab.plugins.KolabPlugins()
+ self.plugins.add_options(self.cli_parser)
+
def create_options(self, load_plugins=True):
"""
Create the OptionParser for the options passed to us from runtime
@@ -243,14 +253,14 @@ class Conf(object):
# Enterprise Linux 5 does not have an "epilog" parameter to OptionParser
try:
- self.parser = OptionParser(epilog=epilog)
+ self.cli_parser = OptionParser(epilog=epilog)
except:
- self.parser = OptionParser()
+ self.cli_parser = OptionParser()
##
## Runtime Options
##
- runtime_group = self.parser.add_option_group(_("Runtime Options"))
+ runtime_group = self.cli_parser.add_option_group(_("Runtime Options"))
runtime_group.add_option( "-c", "--config",
dest = "config_file",
action = "store",
@@ -281,19 +291,12 @@ class Conf(object):
default = False,
help = _("Answer yes to all questions."))
- ##
- ## Get options from plugins
- ##
- if load_plugins:
- self.plugins = pykolab.plugins.KolabPlugins(init=True, conf=self)
- self.plugins.add_options(self.parser)
-
def parse_options(self):
"""
Parse options passed to our call.
"""
- (self.cli_options, self.args) = self.parser.parse_args()
+ (self.cli_keywords, self.cli_args) = self.cli_parser.parse_args()
def run(self):
"""
@@ -302,10 +305,10 @@ class Conf(object):
exitcode = 0
- if self.args:
- if len(self.args) >= 1:
- if hasattr(self,"command_%s" % self.args[0].replace('-','_')):
- exec("self.command_%s(%r)" % (self.args[0].replace('-','_'), self.args[1:]))
+ if self.cli_args:
+ if len(self.cli_args) >= 1:
+ if hasattr(self,"command_%s" % self.cli_args[0].replace('-','_')):
+ exec("self.command_%s(%r)" % (self.cli_args[0].replace('-','_'), self.cli_args[1:]))
else:
print >> sys.stderr, _("No command supplied")
@@ -351,7 +354,7 @@ class Conf(object):
"""
if not value:
- value = self.cli_options.config_file
+ value = self.cli_keywords.config_file
self.cfg_parser = SafeConfigParser()
self.cfg_parser.read(value)
@@ -389,13 +392,13 @@ class Conf(object):
self.read_config()
if not len(args) == 3:
- self.log.error(_("Insufficient options. Need section, key and value -in that order."), recoverable=False)
+ log.error(_("Insufficient options. Need section, key and value -in that order."), recoverable=False)
if not self.cfg_parser.has_section(args[0]):
- self.log.error(_("No section '%s' exists.") %(args[0]))
+ log.error(_("No section '%s' exists.") %(args[0]))
self.cfg_parser.set(args[0], args[1], args[2])
- fp = open(self.cli_options.config_file, "w+")
+ fp = open(self.cli_keywords.config_file, "w+")
self.cfg_parser.write(fp)
fp.close()
@@ -404,25 +407,25 @@ class Conf(object):
Create a logger instance using cli_options.debuglevel
"""
- if not self.cli_options.debuglevel == None:
+ if not self.cli_keywords.debuglevel == None:
loglevel = logging.DEBUG
else:
loglevel = logging.INFO
- self.cli_options.debuglevel = 0
+ self.cli_keywords.debuglevel = 0
# Initialize logger
- self.log = pykolab.logger.Logger(loglevel=loglevel, debuglevel=self.cli_options.debuglevel, logfile=self.cli_options.logfile)
+ log = pykolab.logger.Logger(loglevel=loglevel, debuglevel=self.cli_keywords.debuglevel, logfile=self.cli_keywords.logfile)
def set_defaults_from_cli_options(self):
- for long_opt in self.parser.__dict__['_long_opt'].keys():
+ for long_opt in self.cli_parser.__dict__['_long_opt'].keys():
if long_opt == "--help":
continue
- setattr(self.defaults,self.parser._long_opt[long_opt].dest,self.parser._long_opt[long_opt].default)
+ setattr(self.defaults,self.cli_parser._long_opt[long_opt].dest,self.cli_parser._long_opt[long_opt].default)
# But, they should be available in our class as well
- for option in self.parser.values.__dict__.keys():
- self.log.debug(_("Setting %s to %r (from the default values for CLI options)") %(option, self.parser._long_opt[long_opt].default), level=9)
- setattr(self,option,self.parser._long_opt[long_opt].default)
+ for option in self.cli_parser.defaults.keys():
+ log.debug(_("Setting %s to %r (from the default values for CLI options)") %(option, self.cli_parser.defaults[option]), level=8)
+ setattr(self,option,self.cli_parser.defaults[option])
def has_section(self, section):
return self.cfg_parser.has_section(section)
@@ -438,28 +441,44 @@ class Conf(object):
return self.cfg_parser.get(section,key, 1)
def get(self, section, key, quiet=False):
+ """
+ Get a configuration option from our store, the configuration file,
+ or an external source if we have some sort of function for it.
+
+ TODO: Include getting the value from plugins through a hook.
+ """
+
if not self.cfg_parser:
self.read_config()
if self.cfg_parser.has_option(section, key):
return self.cfg_parser.get(section,key)
+
+ if hasattr(self, "get_%s_%s" %(section,key)):
+ try:
+ exec("retval = self.get_%s_%s(quiet)" %(section,key))
+ except Exception, e:
+ log.error(_("Could not execute configuration function: %s") %("get_%s_%s(quiet=%r)" %(section,key,quiet)))
+ return None
+
+ return retval
+
+ if quiet:
+ return ""
else:
- if quiet:
- return ""
- else:
- self.log.warning(_("Option %s/%s does not exist in config file %s, pulling from defaults") %(section, key, self.config_file))
- if hasattr(self.defaults, "%s_%s" %(section,key)):
- return getattr(self.defaults, "%s_%s" %(section,key))
- elif hasattr(self.defaults, "%s" %(section)):
- if key in getattr(self.defaults, "%s" %(section)):
- _dict = getattr(self.defaults, "%s" %(section))
- return _dict[key]
- else:
- self.log.warning(_("Option does not exist in defaults."))
- return _("Not available")
+ log.warning(_("Option %s/%s does not exist in config file %s, pulling from defaults") %(section, key, self.config_file))
+ if hasattr(self.defaults, "%s_%s" %(section,key)):
+ return getattr(self.defaults, "%s_%s" %(section,key))
+ elif hasattr(self.defaults, "%s" %(section)):
+ if key in getattr(self.defaults, "%s" %(section)):
+ _dict = getattr(self.defaults, "%s" %(section))
+ return _dict[key]
else:
- self.log.warning(_("Option does not exist in defaults."))
+ log.warning(_("Option does not exist in defaults."))
return _("Not available")
+ else:
+ log.warning(_("Option does not exist in defaults."))
+ return _("Not available")
def check_setting_config_file(self, value):
if os.path.isfile(value):
@@ -468,21 +487,21 @@ class Conf(object):
self.config_file = value
return True
else:
- self.log.error(_("Configuration file %s not readable.") %(value), recoverable=False)
+ log.error(_("Configuration file %s not readable.") %(value), recoverable=False)
return False
else:
- self.log.error(_("Configuration file %s does not exist.") %(value), recoverable=False)
+ log.error(_("Configuration file %s does not exist.") %(value), recoverable=False)
return False
def check_setting_debuglevel(self, value):
if value < 0:
- self.log.info(_("WARNING: A negative debug level value does not make this program be any more silent."))
+ log.info(_("WARNING: A negative debug level value does not make this program be any more silent."))
elif value == 0:
return True
elif value <= 9:
return True
else:
- self.log.info(_("WARNING: This program has 9 levels of verbosity. Using the maximum of 9."))
+ log.warning(_("This program has 9 levels of verbosity. Using the maximum of 9."))
return True
def check_setting_saslauth_mode(self, value):
@@ -490,13 +509,13 @@ class Conf(object):
# TODO: I suppose this is platform specific
if os.path.isfile("/var/run/saslauthd/mux"):
if os.path.isfile("/var/run/saslauthd/saslauthd.pid"):
- self.log.error(_("Cannot start SASL authentication daemon"))
+ log.error(_("Cannot start SASL authentication daemon"))
return False
else:
try:
os.remove("/var/run/saslauthd/mux")
except IOError, e:
- self.log.error(_("Cannot start SASL authentication daemon"))
+ log.error(_("Cannot start SASL authentication daemon"))
return False
return True
@@ -507,7 +526,7 @@ class Conf(object):
setattr(self,"use_imap",value)
return True
except ImportError, e:
- self.log.error(_("No imaplib library found."))
+ log.error(_("No imaplib library found."))
return False
def check_setting_use_lmtp(self, value):
@@ -517,7 +536,7 @@ class Conf(object):
setattr(self,"use_lmtp",value)
return True
except ImportError, e:
- self.log.error(_("No LMTP class found in the smtplib library."))
+ log.error(_("No LMTP class found in the smtplib library."))
return False
def check_setting_use_mail(self, value):
@@ -527,7 +546,7 @@ class Conf(object):
setattr(self,"use_mail",value)
return True
except ImportError, e:
- self.log.error(_("No SMTP class found in the smtplib library."))
+ log.error(_("No SMTP class found in the smtplib library."))
return False
def check_setting_test_suites(self, value):
@@ -537,8 +556,8 @@ class Conf(object):
if "zpush" in value:
selectively = False
for item in [ 'calendar', 'contacts', 'mail' ]:
- if self.cli_options.__dict__[item]:
- self.log.debug(_("Found you specified a specific set of items to test: %s") %(item), level=9)
+ if self.cli_keywords.__dict__[item]:
+ log.debug(_("Found you specified a specific set of items to test: %s") %(item), level=8)
selectively = item
if not selectively:
@@ -546,25 +565,25 @@ class Conf(object):
self.contacts = True
self.mail = True
else:
- self.log.debug(_("Selectively selecting: %s") %(selectively), level=9)
+ log.debug(_("Selectively selecting: %s") %(selectively), level=8)
setattr(self, selectively, True)
self.test_suites.append('zpush')
def check_setting_calendar(self, value):
- if self.parser._long_opt['--calendar'].default == value:
+ if self.cli_parser._long_opt['--calendar'].default == value:
return False
else:
return True
def check_setting_contacts(self, value):
- if self.parser._long_opt['--contacts'].default == value:
+ if self.cli_parser._long_opt['--contacts'].default == value:
return False
else:
return True
def check_setting_mail(self, value):
- if self.parser._long_opt['--mail'].default == value:
+ if self.cli_parser._long_opt['--mail'].default == value:
return False
else:
return True
diff --git a/pykolab/conf/defaults.py b/pykolab/conf/defaults.py
index af5e7e1..9e3a8ec 100644
--- a/pykolab/conf/defaults.py
+++ b/pykolab/conf/defaults.py
@@ -17,30 +17,8 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
+import logging
+
class Defaults(object):
def __init__(self, plugins=None):
- # Each possible section in the configuration has a dict here.
-
- # The default authentication mechanism
- self.kolab = {
- 'auth_mechanism': 'ldap',
- }
-
- # The default LDAP URI. Note that these are
- # prefixed with the section name.
- self.ldap = {
- 'uri': "ldap://localhost",
- 'base_dn': "dc=localhost,dc=localdomain",
- 'bind_dn': "",
- 'bind_pw': "",
- 'user_base_dn': "ou=People,%(base_dn)s",
- 'group_base_dn': "ou=Groups,%(base_dn)s",
- 'kolab_user_filter': '(objectClass=*)'
- }
-
- self.testing = {
- 'admin_password': 'secret',
- 'admin_login': 'manager',
- 'server': '127.0.0.1',
- 'users': []
- } \ No newline at end of file
+ self.loglevel = logging.CRITICAL
diff --git a/pykolab/conf/runtime.py b/pykolab/conf/runtime.py
deleted file mode 100644
index 7994f9e..0000000
--- a/pykolab/conf/runtime.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2010-2011 Kolab Systems AG (http://www.kolabsys.com)
-#
-# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 3 or, at your option, any later version
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Library General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-
-class Runtime(object):
- def __init__(self, plugins, defaults):
- self.test_suites = []
-