Friday, 13 September
2013
Fri, 13 Sep
'13
7:39 a.m.
This commit adds two CLI arguments to lnst-ctl:
-a, --define-alias
-A, --override-alias
Using these you can define or override an alias in the recipe you're
just executing. The difference between these two is in their effect.
Defied aliases (-a) can be overriden by the aliases that are defined in
the recie. The override aliases will replace all definitions of the
alias with the name in question within the entire recipe file.
Example:
lnst-ctl -A http_port=80 recipe.xml run
Issue #1.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst-ctl | 50 +++++++++++++++++++++++++++++-------
lnst/Common/XmlParser.py | 3 +++
lnst/Common/XmlTemplates.py | 13 +++++++++-
lnst/Controller/NetTestController.py | 4 ++-
4 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/lnst-ctl b/lnst-ctl
index e71ba83..c01762a 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -32,7 +32,7 @@ def usage(retval=0):
"""
print "Usage: %s [OPTION...] [RECIPE...] ACTION" % sys.argv[0]
print ""
- print "ACTION = [run | config_only | match_setup]"
+ print "ACTION = [ run | config_only | match_setup ]"
print ""
print "OPTIONS"
print " -d, --debug emit debugging messages"
@@ -45,13 +45,34 @@ def usage(retval=0):
" machines in the pool"
print " -c, --config=FILE load additional config file\n"
print " -x, --result=FILE file to write xml_result"
+ print " -a, --define-alias name=value define top-level alias"
+ print " -A, --override-alias name=value define top-level alias that\n" \
+ " will override any other\n"\
+ " definitions in the recipe"
sys.exit(retval)
+def store_alias(alias_def, aliases_dict):
+ try:
+ name, value = alias_def.split("=")
+ except:
+ msg = "The alias definition '%s' not supported. The proper" +
\
+ " format is alias_name=alias_value."
+ raise Exception(msg)
+
+ if name in aliases_dict:
+ msg = "The same alias %s was defined multiple times through CLI."
+ logging.warning(msg)
+
+ aliases_dict[name] = value
+
def process_recipe(action, file_path, res_serializer,
- packet_capture, log_ctl, pool_checks):
+ packet_capture, log_ctl, pool_checks,
+ defined_aliases, overriden_aliases):
nettestctl = NetTestController(file_path, log_ctl,
res_serializer=res_serializer,
- pool_checks=pool_checks)
+ pool_checks=pool_checks,
+ defined_aliases=defined_aliases,
+ overriden_aliases=overriden_aliases)
if action == "run":
return nettestctl.run_recipe(packet_capture)
elif action == "config_only":
@@ -60,7 +81,7 @@ def process_recipe(action, file_path, res_serializer,
return nettestctl.match_setup()
def get_recipe_result(args, file_path, res_serializer, packet_capture,
- log_ctl, pool_checks):
+ log_ctl, pool_checks, defined_aliases, overriden_aliases):
res_serializer.add_recipe(file_path)
log_ctl.set_recipe(file_path)
@@ -69,7 +90,8 @@ def get_recipe_result(args, file_path, res_serializer, packet_capture,
res = {}
try:
res = process_recipe(args, file_path, res_serializer,
- packet_capture, log_ctl, pool_checks)
+ packet_capture, log_ctl, pool_checks,
+ defined_aliases, overriden_aliases)
except Exception as err:
log_exc_traceback()
logging.error(err)
@@ -92,9 +114,10 @@ def main():
try:
opts, args = getopt.getopt(
sys.argv[1:],
- "dhr:c:x:pom",
+ "dhr:c:x:poma:A:",
["debug", "help", "recipe=",
"config", "result=",
- "packet-capture", "disable-pool-checks",
"no-colours"]
+ "packet-capture", "disable-pool-checks",
"no-colours",
+ "define_alias", "override_alias"]
)
except getopt.GetoptError as err:
print str(err)
@@ -124,6 +147,8 @@ def main():
packet_capture = False
pool_checks = True
coloured_output = True
+ defined_aliases = {}
+ overriden_aliases = {}
for opt, arg in opts:
if opt in ("-d", "--debug"):
debug += 1
@@ -139,6 +164,10 @@ def main():
pool_checks = False
elif opt in ("-m", "--no-colours"):
coloured_output = False
+ elif opt in ("-a", "--define-alias"):
+ store_alias(arg, defined_aliases)
+ elif opt in ("-A", "--override-alias"):
+ store_alias(arg, overriden_aliases)
if config_path is not None:
if not os.path.isfile(config_path):
@@ -187,12 +216,15 @@ def main():
fp, res, rv = get_recipe_result(action, recipe_file,
res_serializer,
packet_capture,
- log_ctl, pool_checks)
+ log_ctl, pool_checks,
+ defined_aliases,
+ overriden_aliases)
else:
fp, res, rv = get_recipe_result(action, recipe_path,
res_serializer,
packet_capture,
- log_ctl, pool_checks)
+ log_ctl, pool_checks,
+ defined_aliases, overriden_aliases)
summary.append((fp, res))
if rv > retval:
diff --git a/lnst/Common/XmlParser.py b/lnst/Common/XmlParser.py
index c404c0b..143b289 100644
--- a/lnst/Common/XmlParser.py
+++ b/lnst/Common/XmlParser.py
@@ -102,6 +102,9 @@ class XmlParser(object):
def set_machines(self, machines):
self._template_proc.set_machines(machines)
+ def set_aliases(self, defined, overriden):
+ self._template_proc.set_aliases(defined, overriden)
+
def _has_attribute(self, element, attr):
return attr in element.attrib
diff --git a/lnst/Common/XmlTemplates.py b/lnst/Common/XmlTemplates.py
index 41dbc0d..a2afd05 100644
--- a/lnst/Common/XmlTemplates.py
+++ b/lnst/Common/XmlTemplates.py
@@ -250,6 +250,14 @@ class XmlTemplates:
"""
self._machines = machines
+ def set_aliases(self, defined, overriden):
+ """ Set aliases defined or overriden from CLI """
+
+ for name, value in defined.iteritems():
+ self.define_alias(name, value)
+
+ self._overriden_aliases = overriden
+
def define_alias(self, name, value, skip_reserved_check=False):
""" Associate an alias name with some value
@@ -283,11 +291,14 @@ class XmlTemplates:
self._definitions.pop()
def _find_definition(self, name):
+ if name in self._overriden_aliases:
+ return self._overriden_aliases[name]
+
for level in reversed(self._definitions):
if name in level:
return level[name]
- err = "'%s' is not defined here" % name
+ err = "Alias '%s' is not defined here" % name
raise XmlTemplateError(err)
def process_aliases(self, element):
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 3379aef..910b40e 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -45,7 +45,8 @@ def ignore_event(**kwarg):
class NetTestController:
def __init__(self, recipe_path, log_ctl,
- res_serializer=None, pool_checks=True):
+ res_serializer=None, pool_checks=True,
+ defined_aliases=None, overriden_aliases=None):
self._res_serializer = res_serializer
self._remote_capture_files = {}
self._log_ctl = log_ctl
@@ -65,6 +66,7 @@ class NetTestController:
parser = RecipeParser(recipe_path)
parser.set_machines(self._machines)
+ parser.set_aliases(defined_aliases, overriden_aliases)
self._recipe = parser.parse()
modules_dirs = lnst_config.get_option('environment',
'module_dirs')
--
1.8.3.1