[asterisk-scf-commits] asterisk-scf/integration/configurator.git branch "retry_deux" created.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Thu Apr 12 09:35:54 CDT 2012
branch "retry_deux" has been created
at 30e4d200128171712c9dbaab84a96c3c98bcba97 (commit)
- Log -----------------------------------------------------------------
commit 30e4d200128171712c9dbaab84a96c3c98bcba97
Author: Brent Eagles <beagles at digium.com>
Date: Thu Apr 12 12:04:48 2012 -0230
A very simple, straight modification for operation context... good enough
to get going, but there may be a better way to do this. Not tested for all
supported configuration operations (just setting so far).
diff --git a/Configurator.py b/Configurator.py
index a11a076..9a8862b 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -22,15 +22,18 @@ import sys
sys.path.append('/opt/Ice-3.4/python')
-import ConfigParser, traceback, os, Ice, getopt
+import ConfigParser, traceback, os, Ice, getopt, uuid
# Load and make the configuration interface available, we require it
-Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/slice/slice/AsteriskSCF/System/Component/ConfigurationIf.ice\"")
-Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/slice/slice/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice\"")
+Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/System/Component/ConfigurationIf.ice\"")
+Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice\"")
import AsteriskSCF.System.Configuration.V1
import AsteriskSCF.Core.Discovery.V1
+def uuidstr():
+ return str(uuid.uuid1())
+
# Exception class used within the configurator application
class ConfiguratorError(Exception):
def __init__(self, value):
@@ -207,8 +210,12 @@ class ConfiguratorApp(Ice.Application):
# There is a race condition here where another component could modify the groups present, but if two
# components are altering the configuration we are best effort to begin with
try:
+ context = AsteriskSCF.System.V1.OperationContext()
+ context.id = uuidstr()
+ context.transactionId = context.id
+
groups = configurationService.getConfigurationGroups()
- configurationService.removeConfigurationGroups(groups)
+ configurationService.removeConfigurationGroups(context, groups)
except:
print >> sys.stderr, "Configuration could not be wiped - Failed to contact component"
traceback.print_exc()
@@ -218,7 +225,10 @@ class ConfiguratorApp(Ice.Application):
try:
# print self.visitor.groups # <- Handiest debug aid ever.
- configurationService.setConfiguration(self.visitor.groups)
+ context = AsteriskSCF.System.V1.OperationContext()
+ context.id = uuidstr()
+ context.transactionId = context.id
+ configurationService.setConfiguration(context, self.visitor.groups)
print "Configuration applied"
except:
print "Exception calling setConfiguration: ", sys.exc_info()[0]
commit ca857b6d911fe4defcfe25cbaec1957c14dcf17d
Author: Darren Sessions <dsessions at digium.com>
Date: Fri Jan 13 13:47:06 2012 -0600
Updated the Configurator python script to reflect new file paths and naming conventions. Added a quick system path append command for /opt/Ice-3.4/python to make the script work straight from the gitall/configurator directory. Added a README.txt file with a quick note about needing to set the ASTSCF_HOME env variable which is required within the script to find slice dependancies.
diff --git a/Configurator.py b/Configurator.py
index cf7c449..a11a076 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -18,11 +18,16 @@
# Asterisk SCF Configurator Module
-import ConfigParser, traceback, os, Ice, getopt, sys
+import sys
+
+sys.path.append('/opt/Ice-3.4/python')
+
+import ConfigParser, traceback, os, Ice, getopt
# Load and make the configuration interface available, we require it
-Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/System/Component/ConfigurationIf.ice\"")
-Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice\"")
+Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/slice/slice/AsteriskSCF/System/Component/ConfigurationIf.ice\"")
+Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/slice/slice/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice\"")
+
import AsteriskSCF.System.Configuration.V1
import AsteriskSCF.Core.Discovery.V1
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..2f7d4ac
--- /dev/null
+++ b/README.txt
@@ -0,0 +1 @@
+Please set the 'ASTSCF_HOME' environment variable to the Asterisk SCF 'gitall' directory path.
commit 9c000ddde667e634c4bb393b190af2d20fd438d0
Author: Ken Hunt <ken.hunt at digium.com>
Date: Thu Sep 22 13:01:18 2011 -0500
Make the script friendler when spaces are in the path.
diff --git a/Configurator.py b/Configurator.py
index c794980..cf7c449 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -21,8 +21,8 @@
import ConfigParser, traceback, os, Ice, getopt, sys
# Load and make the configuration interface available, we require it
-Ice.loadSlice("-I" + os.environ["ASTSCF_HOME"] + " -I" + Ice.getSliceDir() + " --all " + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/System/Component/ConfigurationIf.ice")
-Ice.loadSlice("-I" + os.environ["ASTSCF_HOME"] + " -I" + Ice.getSliceDir() + " --all " + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice")
+Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/System/Component/ConfigurationIf.ice\"")
+Ice.loadSlice("-I\"" + os.environ["ASTSCF_HOME"] + "\" -I\"" + Ice.getSliceDir() + "\" --all \"" + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice\"")
import AsteriskSCF.System.Configuration.V1
import AsteriskSCF.Core.Discovery.V1
@@ -212,10 +212,11 @@ class ConfiguratorApp(Ice.Application):
print "Applying configuration"
try:
+ # print self.visitor.groups # <- Handiest debug aid ever.
configurationService.setConfiguration(self.visitor.groups)
print "Configuration applied"
except:
- print "Configuration could not be applied - Failed to contact component"
+ print "Exception calling setConfiguration: ", sys.exc_info()[0]
traceback.print_exc()
else:
commit 1a8be87a1573715a18281bddfbbd66148a7147e0
Author: Kevin P. Fleming <kpfleming at digium.com>
Date: Tue Jun 21 06:59:50 2011 -0500
Improve loading of API Slice files.
* Use Ice.getSliceDir() to find the Ice-provided Slice files.
* (for now) Allow an environment variable called ASTSCF_HOME to be set to
to tell the script where to find the Asterisk SCF Slice files.
diff --git a/Configurator.py b/Configurator.py
index f379a0b..c794980 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -21,8 +21,8 @@
import ConfigParser, traceback, os, Ice, getopt, sys
# Load and make the configuration interface available, we require it
-Ice.loadSlice('-I. --all ConfigurationIf.ice')
-Ice.loadSlice('-I. -I/opt/Ice-3.4.1/slice --all ServiceLocatorIf.ice')
+Ice.loadSlice("-I" + os.environ["ASTSCF_HOME"] + " -I" + Ice.getSliceDir() + " --all " + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/System/Component/ConfigurationIf.ice")
+Ice.loadSlice("-I" + os.environ["ASTSCF_HOME"] + " -I" + Ice.getSliceDir() + " --all " + os.environ["ASTSCF_HOME"] + "/AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice")
import AsteriskSCF.System.Configuration.V1
import AsteriskSCF.Core.Discovery.V1
commit 277654d75b173d4b7c394f43e3ba6f66be33e4dc
Author: Ken Hunt <ken.hunt at digium.com>
Date: Thu May 26 10:47:47 2011 -0500
Added traceback for the exceptions that we can't work around.
diff --git a/Configurator.py b/Configurator.py
index 831441f..f379a0b 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -18,7 +18,7 @@
# Asterisk SCF Configurator Module
-import ConfigParser, os, Ice, getopt, sys
+import ConfigParser, traceback, os, Ice, getopt, sys
# Load and make the configuration interface available, we require it
Ice.loadSlice('-I. --all ConfigurationIf.ice')
@@ -206,6 +206,7 @@ class ConfiguratorApp(Ice.Application):
configurationService.removeConfigurationGroups(groups)
except:
print >> sys.stderr, "Configuration could not be wiped - Failed to contact component"
+ traceback.print_exc()
return -1
print "Applying configuration"
@@ -215,6 +216,7 @@ class ConfiguratorApp(Ice.Application):
print "Configuration applied"
except:
print "Configuration could not be applied - Failed to contact component"
+ traceback.print_exc()
else:
print "No configuration to apply"
commit 5652963f45288888f1716b32d4784b89d208b8cc
Author: Joshua Colp <jcolp at digium.com>
Date: Tue May 24 13:02:01 2011 -0300
Output the filename of the script using the Configurator, not the Configurator filename itself.
diff --git a/Configurator.py b/Configurator.py
index 2b3f9a5..831441f 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -179,7 +179,7 @@ class ConfiguratorApp(Ice.Application):
configurationService = AsteriskSCF.System.Configuration.V1.ConfigurationServicePrx.uncheckedCast(service)
if configurationService == None:
- print >> sys.stderr, "No configuration service to configure. For usage details please run " + __file__ + " --help"
+ print >> sys.stderr, "No configuration service to configure. For usage details please run " + sys.argv[0] + " --help"
return -1
print "Reading configuration from file " + configFile
commit 31ffb84646d9608f6ed38c088335be459244b7d3
Author: Joshua Colp <jcolp at digium.com>
Date: Tue May 17 09:00:35 2011 -0300
Add support for using the service locator to find a configuration service.
diff --git a/Configurator.py b/Configurator.py
index 718f16a..2b3f9a5 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -22,7 +22,9 @@ import ConfigParser, os, Ice, getopt, sys
# Load and make the configuration interface available, we require it
Ice.loadSlice('-I. --all ConfigurationIf.ice')
+Ice.loadSlice('-I. -I/opt/Ice-3.4.1/slice --all ServiceLocatorIf.ice')
import AsteriskSCF.System.Configuration.V1
+import AsteriskSCF.Core.Discovery.V1
# Exception class used within the configurator application
class ConfiguratorError(Exception):
@@ -102,7 +104,7 @@ class OptionMapper():
# Common configurator application logic
class ConfiguratorApp(Ice.Application):
- def __init__(self, defaultConfigFile, visitor, configurationService = None):
+ def __init__(self, defaultConfigFile, visitor, configurationService = None, serviceLocatorParams = None):
"""Common configuration utility class"""
if defaultConfigFile == '':
@@ -111,6 +113,7 @@ class ConfiguratorApp(Ice.Application):
self.defaultConfigFile = defaultConfigFile
self.visitor = visitor
self.configurationService = configurationService
+ self.serviceLocatorParams = serviceLocatorParams
def usage(self):
"""Print usage information for the configuration utility"""
@@ -122,13 +125,15 @@ class ConfiguratorApp(Ice.Application):
print "-h, --help display help information"
print "-c, --config=FILENAME use specified configuration file instead of " + self.defaultConfigFile
print "-p, --proxy=PROXY use specified proxy instead of locating component"
+ print "-l, --locator=PROXY use specified proxy for service locator"
+ print "-n, --name=NAME use name when finding configuration service"
print "-w, --wipe remove existing configuration before applying new one"
def run(self, args):
"""Parse options, read configuration file, produce configuration data, and submit it"""
try:
- opts, arguments = getopt.getopt(args[1:], "hc:p:w", ["help", "config=", "proxy=", "wipe"])
+ opts, arguments = getopt.getopt(args[1:], "hc:p:l:n:w", ["help", "config=", "proxy=", "locator=", "name=", "wipe"])
except getopt.GetoptError, err:
print str(err)
self.usage()
@@ -137,6 +142,9 @@ class ConfiguratorApp(Ice.Application):
configFile = self.defaultConfigFile
configurationService = self.configurationService
configurationWipe = False
+ configurationServiceName = ""
+ serviceLocator = None
+ serviceLocatorParams = self.serviceLocatorParams
for o, a in opts:
if o in ("-h", "--help"):
@@ -149,9 +157,27 @@ class ConfiguratorApp(Ice.Application):
elif o in ("-p", "--proxy"):
configurationService = AsteriskSCF.System.Configuration.V1.ConfigurationServicePrx.checkedCast(self.communicator().stringToProxy(a))
+ elif o in ("-l", "--locator"):
+ serviceLocator = AsteriskSCF.Core.Discovery.V1.ServiceLocatorPrx.checkedCast(self.communicator().stringToProxy(a))
+
+ elif o in ("-n", "--name"):
+ configurationServiceName = a
+
elif o in ("-w", "--wipe"):
configurationWipe = True
+ if serviceLocator:
+ # Populate params with the name
+ setattr(serviceLocatorParams, "name", configurationServiceName)
+
+ try:
+ service = serviceLocator.locate(serviceLocatorParams)
+ except AsteriskSCF.Core.Discovery.V1.ServiceNotFound:
+ print >> sys.stderr, "Configuration service could not be found in service locator."
+ return -1
+
+ configurationService = AsteriskSCF.System.Configuration.V1.ConfigurationServicePrx.uncheckedCast(service)
+
if configurationService == None:
print >> sys.stderr, "No configuration service to configure. For usage details please run " + __file__ + " --help"
return -1
commit 3af0760b0e3d33267a7eaaf02c8e63a17bacc729
Author: Joshua Colp <jcolp at digium.com>
Date: Mon Apr 11 14:47:48 2011 -0300
Tweak message so that people can know to specify --help for usage details if nothing is specified.
diff --git a/Configurator.py b/Configurator.py
index 2b1c5da..718f16a 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -153,7 +153,7 @@ class ConfiguratorApp(Ice.Application):
configurationWipe = True
if configurationService == None:
- print >> sys.stderr, "No configuration service to configure."
+ print >> sys.stderr, "No configuration service to configure. For usage details please run " + __file__ + " --help"
return -1
print "Reading configuration from file " + configFile
commit 15138e4da8d4a3eb286a4d3bd60a564608d1349f
Author: Joshua Colp <jcolp at digium.com>
Date: Sun Mar 20 11:16:47 2011 -0300
I do believe we are in the year 2011 these days.
diff --git a/Configurator.py b/Configurator.py
index 4c3d2fc..2b1c5da 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -3,7 +3,7 @@
#
# Asterisk SCF -- An open-source communications framework.
#
-# Copyright (C) 2010, Digium, Inc.
+# Copyright (C) 2011, Digium, Inc.
#
# See http://www.asterisk.org for more information about
# the Asterisk SCF project. Please do not directly contact
commit 99764b169d9f01c407605797b7e1903a5007699c
Author: Joshua Colp <jcolp at digium.com>
Date: Sun Mar 20 11:08:47 2011 -0300
Incorporate even more code review feedback.
diff --git a/Configurator.py b/Configurator.py
index 84a45a4..4c3d2fc 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -1,5 +1,21 @@
#!/usr/bin/env python
+#
+# Asterisk SCF -- An open-source communications framework.
+#
+# Copyright (C) 2010, Digium, Inc.
+#
+# See http://www.asterisk.org for more information about
+# the Asterisk SCF project. Please do not directly contact
+# any of the maintainers of this project for assistance;
+# the project provides a web site, mailing lists and IRC
+# channels for your use.
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License Version 2. See the LICENSE.txt file
+# at the top of the source tree.
+#
+
# Asterisk SCF Configurator Module
import ConfigParser, os, Ice, getopt, sys
@@ -45,18 +61,19 @@ class OptionMapper():
def map(self, option, object, item, item_name, method, default = None):
setattr(object, item, default)
- self.options[option] = [ object, item, item_name, method, default ]
+ self.options[option] = { 'object': object, 'item': item, 'item_name': item_name, 'method': method, 'default': default }
def execute(self, group, section, option):
"""Map options to configuration items based on options set"""
try:
- object = self.options[option][0]
+ object = self.options[option]['object']
except:
return
- item = self.options[option][1]
- item_name = self.options[option][2]
- method = self.options[option][3]
- default = self.options[option][4]
+
+ item = self.options[option]['item']
+ item_name = self.options[option]['item_name']
+ method = self.options[option]['method']
+ default = self.options[option]['default']
try:
setattr(object, item, method(section, option))
@@ -77,8 +94,8 @@ class OptionMapper():
def finish(self, group):
"""Finish mapping options by finding ones that should have a value but do not"""
for option in self.options:
- item = self.options[option][1]
- default = self.options[option][4]
+ item = self.options[option]['item']
+ default = self.options[option]['default']
if default == None:
if item == None:
print "Option '" + option + "' requires a value to be set and no default value exists."
commit a9710935203651fdbe13bd2bd147bdc3c5df3a4f
Author: Joshua Colp <jcolp at digium.com>
Date: Sun Mar 20 10:59:24 2011 -0300
Incorporate feedback from code review.
diff --git a/Configurator.py b/Configurator.py
index 8bef119..84a45a4 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -2,7 +2,7 @@
# Asterisk SCF Configurator Module
-import ConfigParser, os, Ice, getopt
+import ConfigParser, os, Ice, getopt, sys
# Load and make the configuration interface available, we require it
Ice.loadSlice('-I. --all ConfigurationIf.ice')
@@ -33,7 +33,7 @@ class SectionVisitors():
def visit_unsupported(self, config, section):
"""Handle an unsupported configuration section"""
- print "Unsupported configuration section " + section
+ print >> sys.stderr, "Unsupported configuration section " + section
# Common option to item mapper implementation
class OptionMapper():
@@ -136,8 +136,8 @@ class ConfiguratorApp(Ice.Application):
configurationWipe = True
if configurationService == None:
- print "No configuration service to configure."
- return 0
+ print >> sys.stderr, "No configuration service to configure."
+ return -1
print "Reading configuration from file " + configFile
config = ConfigParser.ConfigParser()
@@ -146,8 +146,8 @@ class ConfiguratorApp(Ice.Application):
try:
config.readfp(open(configFile))
except IOError:
- print "Specified configuration file " + configFile + " could not be loaded."
- return 0
+ print >> sys.stderr, "Specified configuration file " + configFile + " could not be loaded."
+ return -1
print "Building configuration changes to send to component"
for section in config.sections():
@@ -162,8 +162,8 @@ class ConfiguratorApp(Ice.Application):
groups = configurationService.getConfigurationGroups()
configurationService.removeConfigurationGroups(groups)
except:
- print "Configuration could not be wiped - Failed to contact component"
- return 0
+ print >> sys.stderr, "Configuration could not be wiped - Failed to contact component"
+ return -1
print "Applying configuration"
commit 38dd03fdce2ff014ad6de91788439b71af0e5f24
Author: Joshua Colp <jcolp at digium.com>
Date: Wed Mar 2 10:50:34 2011 -0400
Don't require every option in a config file to be mapped.
diff --git a/Configurator.py b/Configurator.py
index 7737542..8bef119 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -49,7 +49,10 @@ class OptionMapper():
def execute(self, group, section, option):
"""Map options to configuration items based on options set"""
- object = self.options[option][0]
+ try:
+ object = self.options[option][0]
+ except:
+ return
item = self.options[option][1]
item_name = self.options[option][2]
method = self.options[option][3]
commit eaafaf0a795eedeb446b612217f5970b49340dbc
Author: Joshua Colp <jcolp at digium.com>
Date: Tue Mar 1 17:14:12 2011 -0400
Use setattr to set the value of the variable on the object and not the variable holding where the object is.
diff --git a/Configurator.py b/Configurator.py
index 04061bf..7737542 100755
--- a/Configurator.py
+++ b/Configurator.py
@@ -43,19 +43,20 @@ class OptionMapper():
"""Generic class meant to perform option to item mapping"""
self.options = { }
- def map(self, option, item, item_name, method, default = None):
- item = default
- self.options[option] = [ item, item_name, method, default ]
+ def map(self, option, object, item, item_name, method, default = None):
+ setattr(object, item, default)
+ self.options[option] = [ object, item, item_name, method, default ]
def execute(self, group, section, option):
"""Map options to configuration items based on options set"""
- item = self.options[option][0]
- item_name = self.options[option][1]
- method = self.options[option][2]
- default = self.options[option][3]
+ object = self.options[option][0]
+ item = self.options[option][1]
+ item_name = self.options[option][2]
+ method = self.options[option][3]
+ default = self.options[option][4]
try:
- item = method(section, option)
+ setattr(object, item, method(section, option))
except ValueError:
# This is not a fatal error since we just use the default value.
@@ -63,18 +64,18 @@ class OptionMapper():
print "The specified value for option '" + option + "' is not valid and no default value exists."
else:
print "The specified value for option '" + option + "' is not valid. Using default value."
- item = default
+ setattr(object, item, default)
# This has the potential to overwrite an existing item but this is done on purpose so that
# configuration options that all map to a single item can happily exist
if item != None:
- group.configurationItems[item_name] = item
+ group.configurationItems[item_name] = object
def finish(self, group):
"""Finish mapping options by finding ones that should have a value but do not"""
for option in self.options:
- item = self.options[option][0]
- default = self.options[option][3]
+ item = self.options[option][1]
+ default = self.options[option][4]
if default == None:
if item == None:
print "Option '" + option + "' requires a value to be set and no default value exists."
@@ -126,7 +127,7 @@ class ConfiguratorApp(Ice.Application):
configFile = a
elif o in ("-p", "--proxy"):
- configurationService = AsteriskSCF.System.Configuration.V1.ConfigurationServicePrx.uncheckedCast(self.communicator().stringToProxy(a))
+ configurationService = AsteriskSCF.System.Configuration.V1.ConfigurationServicePrx.checkedCast(self.communicator().stringToProxy(a))
elif o in ("-w", "--wipe"):
configurationWipe = True
diff --git a/ExampleConfigurator.py b/ExampleConfigurator.py
index bf53cdb..ac27850 100755
--- a/ExampleConfigurator.py
+++ b/ExampleConfigurator.py
@@ -20,12 +20,12 @@ class ExampleSectionVisitors(Configurator.SectionVisitors):
mapper = Configurator.OptionMapper()
# Enable is easy
- mapper.map('enable', AsteriskSCF.System.Configuration.Example.V1.EnableItem().enabled, 'enabled', config.getboolean, False)
+ mapper.map('enable', AsteriskSCF.System.Configuration.Example.V1.EnableItem(), 'enabled', 'enabled', config.getboolean, False)
# What will be the name and how many of them?
item = AsteriskSCF.System.Configuration.Example.V1.InstanceInfoItem()
- mapper.map('name', item.name, 'instance_info', config.get, None)
- mapper.map('instances', item.num, 'instance_info', config.getint, 1)
+ mapper.map('name', item, 'name', 'instance_info', config.get, None)
+ mapper.map('instances', item, 'num', 'instance_info', config.getint, 1)
# Map all the options to the corresponding items and stuff them in the group!
for option in config.options(section):
@@ -42,8 +42,8 @@ class ExampleSectionVisitors(Configurator.SectionVisitors):
# Create an option mapper, put our options in, and map them
mapper = Configurator.OptionMapper()
- mapper.map('ipv4', AsteriskSCF.System.Configuration.Example.V1.EnableItem().enabled, 'ipv4_enabled', config.getboolean, False)
- mapper.map('ipv6', AsteriskSCF.System.Configuration.Example.V1.EnableItem().enabled, 'ipv6_enabled', config.getboolean, False)
+ mapper.map('ipv4', AsteriskSCF.System.Configuration.Example.V1.EnableItem(), 'enabled', 'ipv4_enabled', config.getboolean, False)
+ mapper.map('ipv6', AsteriskSCF.System.Configuration.Example.V1.EnableItem(), 'enabled', 'ipv6_enabled', config.getboolean, False)
for option in config.options(section):
mapper.execute(group, section, option)
commit 1e20913bf7364a4f91beadc7e94934472a55204a
Author: Joshua Colp <jcolp at digium.com>
Date: Fri Feb 18 09:01:30 2011 -0400
Add Configurator python module with example.
diff --git a/Configurator.py b/Configurator.py
new file mode 100755
index 0000000..04061bf
--- /dev/null
+++ b/Configurator.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+
+# Asterisk SCF Configurator Module
+
+import ConfigParser, os, Ice, getopt
+
+# Load and make the configuration interface available, we require it
+Ice.loadSlice('-I. --all ConfigurationIf.ice')
+import AsteriskSCF.System.Configuration.V1
+
+# Exception class used within the configurator application
+class ConfiguratorError(Exception):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return repr(self.value)
+
+# Common section visitor pattern implementation
+class SectionVisitors():
+ def __init__(self):
+ """Generic class meant to be inherited from for section visitors"""
+ self.groups = []
+
+ def visit(self, config, section):
+ """Execute the visit_ function corresponding to the section name"""
+ try:
+ method = getattr(self, 'visit_' + section)
+ except AttributeError:
+ self.visit_unsupported(config, section)
+ else:
+ method(config, section);
+
+ def visit_unsupported(self, config, section):
+ """Handle an unsupported configuration section"""
+ print "Unsupported configuration section " + section
+
+# Common option to item mapper implementation
+class OptionMapper():
+ options = { }
+
+ def __init(self):
+ """Generic class meant to perform option to item mapping"""
+ self.options = { }
+
+ def map(self, option, item, item_name, method, default = None):
+ item = default
+ self.options[option] = [ item, item_name, method, default ]
+
+ def execute(self, group, section, option):
+ """Map options to configuration items based on options set"""
+ item = self.options[option][0]
+ item_name = self.options[option][1]
+ method = self.options[option][2]
+ default = self.options[option][3]
+
+ try:
+ item = method(section, option)
+
+ except ValueError:
+ # This is not a fatal error since we just use the default value.
+ if default == None:
+ print "The specified value for option '" + option + "' is not valid and no default value exists."
+ else:
+ print "The specified value for option '" + option + "' is not valid. Using default value."
+ item = default
+
+ # This has the potential to overwrite an existing item but this is done on purpose so that
+ # configuration options that all map to a single item can happily exist
+ if item != None:
+ group.configurationItems[item_name] = item
+
+ def finish(self, group):
+ """Finish mapping options by finding ones that should have a value but do not"""
+ for option in self.options:
+ item = self.options[option][0]
+ default = self.options[option][3]
+ if default == None:
+ if item == None:
+ print "Option '" + option + "' requires a value to be set and no default value exists."
+
+# Common configurator application logic
+class ConfiguratorApp(Ice.Application):
+ def __init__(self, defaultConfigFile, visitor, configurationService = None):
+ """Common configuration utility class"""
+
+ if defaultConfigFile == '':
+ raise ConfiguratorError('Configuration utility implementation issue - No default configuration filename specified.')
+
+ self.defaultConfigFile = defaultConfigFile
+ self.visitor = visitor
+ self.configurationService = configurationService
+
+ def usage(self):
+ """Print usage information for the configuration utility"""
+
+ print "Usage: " + self.appName() + " [--config=filename] [--proxy=stringified configuration service proxy] [--wipe]"
+ print "Push a configuration to a component."
+ print ""
+ print "Mandatory arguments to long options are mandatory for short options too."
+ print "-h, --help display help information"
+ print "-c, --config=FILENAME use specified configuration file instead of " + self.defaultConfigFile
+ print "-p, --proxy=PROXY use specified proxy instead of locating component"
+ print "-w, --wipe remove existing configuration before applying new one"
+
+ def run(self, args):
+ """Parse options, read configuration file, produce configuration data, and submit it"""
+
+ try:
+ opts, arguments = getopt.getopt(args[1:], "hc:p:w", ["help", "config=", "proxy=", "wipe"])
+ except getopt.GetoptError, err:
+ print str(err)
+ self.usage()
+ return 1
+
+ configFile = self.defaultConfigFile
+ configurationService = self.configurationService
+ configurationWipe = False
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ self.usage()
+ return 1
+
+ elif o in ("-c", "--config"):
+ configFile = a
+
+ elif o in ("-p", "--proxy"):
+ configurationService = AsteriskSCF.System.Configuration.V1.ConfigurationServicePrx.uncheckedCast(self.communicator().stringToProxy(a))
+
+ elif o in ("-w", "--wipe"):
+ configurationWipe = True
+
+ if configurationService == None:
+ print "No configuration service to configure."
+ return 0
+
+ print "Reading configuration from file " + configFile
+ config = ConfigParser.ConfigParser()
+
+ # This purposely uses open and readfp so that the file is required to be present
+ try:
+ config.readfp(open(configFile))
+ except IOError:
+ print "Specified configuration file " + configFile + " could not be loaded."
+ return 0
+
+ print "Building configuration changes to send to component"
+ for section in config.sections():
+ self.visitor.visit(config, section)
+
+ if self.visitor.groups:
+ if configurationWipe == True:
+ print "Wiping existing configuration before applying changes"
+ # There is a race condition here where another component could modify the groups present, but if two
+ # components are altering the configuration we are best effort to begin with
+ try:
+ groups = configurationService.getConfigurationGroups()
+ configurationService.removeConfigurationGroups(groups)
+ except:
+ print "Configuration could not be wiped - Failed to contact component"
+ return 0
+
+ print "Applying configuration"
+
+ try:
+ configurationService.setConfiguration(self.visitor.groups)
+ print "Configuration applied"
+ except:
+ print "Configuration could not be applied - Failed to contact component"
+
+ else:
+ print "No configuration to apply"
+
+ return 0
diff --git a/Example.config b/Example.config
new file mode 100644
index 0000000..9ca996e
--- /dev/null
+++ b/Example.config
@@ -0,0 +1,9 @@
+[general]
+enable=yes
+instances=10
+
+[network]
+ipv6=never ever
+ipv4=yes
+
+[bob]
diff --git a/ExampleConfigurationIf.ice b/ExampleConfigurationIf.ice
new file mode 100644
index 0000000..422deba
--- /dev/null
+++ b/ExampleConfigurationIf.ice
@@ -0,0 +1,71 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#pragma once
+
+#include "ConfigurationIf.ice"
+
+module AsteriskSCF
+{
+
+module System
+{
+
+module Configuration
+{
+
+module Example
+{
+
+["suppress"]
+module V1
+{
+
+ /* General configuration group for items that do not belong in any specific group */
+ class GeneralGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
+ {
+ };
+
+ /* Network configuration group for network specific items */
+ class NetworkGroup extends AsteriskSCF::System::Configuration::V1::ConfigurationGroup
+ {
+ };
+
+ /* Simple enable and disable item */
+ class EnableItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
+ {
+ bool enabled;
+ };
+
+ /* Instance information item */
+ class InstanceInfoItem extends AsteriskSCF::System::Configuration::V1::ConfigurationItem
+ {
+ /* Name of the instances */
+ string name;
+
+ /* How many there should be */
+ int num;
+ };
+
+}; /* End of namespace V1 */
+
+}; /* End of namespace Example */
+
+}; /* End of namespace Configuration */
+
+}; /* End of namespace System */
+
+}; /* End of namespace AsteriskSCF */
diff --git a/ExampleConfigurator.py b/ExampleConfigurator.py
new file mode 100755
index 0000000..bf53cdb
--- /dev/null
+++ b/ExampleConfigurator.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+# Example configurator
+
+# Bring in the common configuration infrastructure
+import Ice, Configurator, sys
+
+# Load our component specific configuration definitions
+Ice.loadSlice('-I. --all ExampleConfigurationIf.ice')
+import AsteriskSCF.System.Configuration.Example.V1
+
+# Add our own visitor implementations for the sections we support
+class ExampleSectionVisitors(Configurator.SectionVisitors):
+ def visit_general(self, config, section):
+ # Create the general group where items from this section will go
+ group = AsteriskSCF.System.Configuration.Example.V1.GeneralGroup()
+ group.configurationItems = { }
+
+ # Create an option mapper and make it aware of the options and their mappings
+ mapper = Configurator.OptionMapper()
+
+ # Enable is easy
+ mapper.map('enable', AsteriskSCF.System.Configuration.Example.V1.EnableItem().enabled, 'enabled', config.getboolean, False)
+
+ # What will be the name and how many of them?
+ item = AsteriskSCF.System.Configuration.Example.V1.InstanceInfoItem()
+ mapper.map('name', item.name, 'instance_info', config.get, None)
+ mapper.map('instances', item.num, 'instance_info', config.getint, 1)
+
+ # Map all the options to the corresponding items and stuff them in the group!
+ for option in config.options(section):
+ mapper.execute(group, section, option)
+ mapper.finish(group)
+
+ # Add the general group to the groups that will be pushed to the component
+ self.groups.append(group)
+
+ def visit_network(self, config, section):
+ # Create the network group where items from this section will go
+ group = AsteriskSCF.System.Configuration.Example.V1.NetworkGroup()
+ group.configurationItems = { }
+
+ # Create an option mapper, put our options in, and map them
+ mapper = Configurator.OptionMapper()
+ mapper.map('ipv4', AsteriskSCF.System.Configuration.Example.V1.EnableItem().enabled, 'ipv4_enabled', config.getboolean, False)
+ mapper.map('ipv6', AsteriskSCF.System.Configuration.Example.V1.EnableItem().enabled, 'ipv6_enabled', config.getboolean, False)
+ for option in config.options(section):
+ mapper.execute(group, section, option)
+
+ mapper.finish(group)
+
+ # Add the network group to the groups that will be pushed to the component
+ self.groups.append(group)
+
+ def visit_unsupported(self, config, section):
+ # If this function is not defined then the configurator will simply print an unsupported option message
+ print "Have unsupported option, should I create some sort of endpoint?"
+
+# Make a configurator application and let it run
+app = Configurator.ConfiguratorApp('Example.config', ExampleSectionVisitors())
+sys.exit(app.main(sys.argv))
-----------------------------------------------------------------------
--
asterisk-scf/integration/configurator.git
More information about the asterisk-scf-commits
mailing list