Author: tmckay
Date: 2011-02-18 21:19:34 +0000 (Fri, 18 Feb 2011)
New Revision: 4538
Modified:
trunk/cumin/bin/cumin
trunk/cumin/etc/sysvinit-cumin
trunk/cumin/python/cumin/config.py
trunk/parsley/python/parsley/config.py
Log:
Add option for strict section checking in cumin apps. This will
raise an exception if a configuration section is referenced which
is not defined in a config file.
Give cumin/bin/cumin an --init-only option for validation on start.
Change init.d script to use --init-only option for cumin/bin/cumin
on start if $CUMIN_OPTIONS has been set before real launch.
These changes are to support error checking on service start.
BZ672583
Modified: trunk/cumin/bin/cumin
===================================================================
--- trunk/cumin/bin/cumin 2011-02-18 15:01:40 UTC (rev 4537)
+++ trunk/cumin/bin/cumin 2011-02-18 21:19:34 UTC (rev 4538)
@@ -21,6 +21,9 @@
else:
signal.signal(signal.SIGTERM, func)
+class InitCheckException(Exception):
+ pass
+
def main():
# tuple indices, for clarity
@@ -30,6 +33,8 @@
parser = OptionParser()
+ parser.add_option("--init-only", dest="init_only",
action="store_true", default=False)
+
parser.add_option("--webs", dest="webs",
default="web",
help="Configuration section names for cumin-web
instances."\
"\nEach value implies a separate cumin-web
instance.")
@@ -40,7 +45,7 @@
(options, args) = parser.parse_args()
- # Get our list cumin-web and data instances
+ # Get our list of cumin-web and data instances
# create list elements to hold the process object, section arg, and app
apps = []
for app in options.webs.split(','):
@@ -49,20 +54,30 @@
for app in options.datas.split(','):
apps.append([None, app, "cumin-data"])
- # Launch and babysit
- try:
- while True:
+ # If we are just checking startup flags, invoke each instance
+ # with "--init-only" and return status to caller
+ if options.init_only:
+ for app in apps:
+ arg = [app[PROGRAM], "--init-only", "--section=" +
app[SECTION]]
+ app[PROCESS] = subprocess.Popen(arg)
+ exit_code = app[PROCESS].wait()
+ if exit_code != 0:
+ raise InitCheckException
+ else:
+ # Launch and babysit
+ try:
+ while True:
+ for app in apps:
+ if not app[PROCESS] or app[PROCESS].poll():
+ arg = [app[PROGRAM], "--section=" + app[SECTION]]
+ app[PROCESS] = subprocess.Popen(arg)
+ sleep(30)
+
+ finally:
for app in apps:
- if not app[PROCESS] or app[PROCESS].poll():
- arg = "--section=" + app[SECTION]
- app[PROCESS] = subprocess.Popen([app[PROGRAM], arg])
- sleep(30)
+ if app[PROCESS]:
+ os.kill(app[PROCESS].pid, signal.SIGTERM)
- finally:
- for app in apps:
- if app[PROCESS]:
- os.kill(app[PROCESS].pid, signal.SIGTERM)
-
if __name__ == "__main__":
# This is necessary so that on a SIGTERM we can call sys.exit()
# and cause the finally block to be executed. Ctrl-C will
Modified: trunk/cumin/etc/sysvinit-cumin
===================================================================
--- trunk/cumin/etc/sysvinit-cumin 2011-02-18 15:01:40 UTC (rev 4537)
+++ trunk/cumin/etc/sysvinit-cumin 2011-02-18 21:19:34 UTC (rev 4538)
@@ -37,16 +37,17 @@
start() {
echo -n $"Starting cumin: "
+ # If it's already running, be happy and return success
status $processname &> /dev/null
- RETVAL=$?
- if [ $RETVAL -eq 0 ] ; then
- success
- else
- daemon --user cumin --check $servicename $processname $CUMIN_OPTIONS \&
- RETVAL=$?
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$servicename
+ [ $? -eq 0 ] && success && echo && return
+ # Invoke in foreground with arguments to test validity, if args have been set
+ if [ -n "$CUMIN_OPTIONS" ] ; then
+ daemon --user cumin --check $servicename $processname "--init-only
"$CUMIN_OPTIONS
+ [ $? -ne 0 ] && failure && echo && return
fi
- echo
+ # Launch for real now...
+ daemon --user cumin --check $servicename $processname $CUMIN_OPTIONS \&
+ [ $? -eq 0 ] && touch /var/lock/subsys/$servicename && echo
}
stop() {
Modified: trunk/cumin/python/cumin/config.py
===================================================================
--- trunk/cumin/python/cumin/config.py 2011-02-18 15:01:40 UTC (rev 4537)
+++ trunk/cumin/python/cumin/config.py 2011-02-18 21:19:34 UTC (rev 4538)
@@ -33,13 +33,13 @@
return self.parse_files(paths)
class CuminWebConfig(CuminConfig):
- def __init__(self, section_name):
+ def __init__(self, section_name, strict_section):
super(CuminWebConfig, self).__init__()
- self.create_section(section_name)
-
- def create_section(self, name):
- web = CuminConfigSection(self, name)
+ self.create_section(section_name, strict_section)
+
+ def create_section(self, name, strict_section):
+ web = CuminConfigSection(self, name, strict_section)
web.log_file.default = os.path.join(self.home, "log", name +
".log")
param = ConfigParameter(web, "update-interval", int)
@@ -68,13 +68,13 @@
param.default = 5 * 1024 #MB
class CuminDataConfig(CuminConfig):
- def __init__(self, section_name):
+ def __init__(self, section_name, strict_section):
super(CuminDataConfig, self).__init__()
- self.create_section(section_name)
+ self.create_section(section_name, strict_section)
- def create_section(self, name):
- data = CuminConfigSection(self, name)
+ def create_section(self, name, strict_section):
+ data = CuminConfigSection(self, name, strict_section)
data.log_file.default = os.path.join(self.home, "log", name +
".log")
param = ConfigParameter(data, "packages", str)
@@ -89,8 +89,8 @@
param.default = 60 * 60 # 1 hour
class CuminConfigSection(ConfigSection):
- def __init__(self, config, name):
- super(CuminConfigSection, self).__init__(config, name)
+ def __init__(self, config, name, strict_section=False):
+ super(CuminConfigSection, self).__init__(config, name, strict_section)
param = ConfigParameter(self, "database", str)
param.default = "dbname=cumin user=cumin host=localhost"
@@ -164,7 +164,9 @@
opts, args = parser.parse_args()
if hasattr(opts, "section"):
# Create config object with the given section and parse config files
- config = ConfigType(opts.section)
+ # Allow the section named in the default value of "--section" to be
missing
+ # from the configuration file; specifically named sections are required.
+ config = ConfigType(opts.section, strict_section = opts.section !=
parser.defaults["section"])
values = config.parse()
if hasattr(values, opts.section):
# Reset defaults and parse again
Modified: trunk/parsley/python/parsley/config.py
===================================================================
--- trunk/parsley/python/parsley/config.py 2011-02-18 15:01:40 UTC (rev 4537)
+++ trunk/parsley/python/parsley/config.py 2011-02-18 21:19:34 UTC (rev 4538)
@@ -21,24 +21,20 @@
sections = ConfigValues()
for section in self.sections:
- try:
- values = section.parse(parser)
- except NoSectionError:
- values = None
-
+ values = section.parse(parser)
sections[section.name] = values
return sections
class ConfigSection(object):
- def __init__(self, config, name):
+ def __init__(self, config, name, strict_section=False):
assert isinstance(config, Config)
self.config = config
self.config.sections.append(self)
self.name = name
-
+ self.strict_section = strict_section
self.parameters = list()
def parse(self, parser):
@@ -49,6 +45,8 @@
try:
items = parser.items(section)
except NoSectionError:
+ if self.strict_section:
+ raise
continue
in_values.update(items)