[PATCH 0/2] Introducing prefix method to get netmask part of an address
by Jan Tluka
This patchset introduces a small change in the way the ip address is obtained
for an interface from the recipe. Template function ip() returned the full
address with the netmask, too. The change is that it will now return only
address part stripping the network prefix.
The prefix can be obtained using new template function prefix() with the same
parameters as the ip() function, e.g:
<run machine="m1" command="echo {prefix(m1,nic1)}" />
Additionally, I changed the TaskAPI, so the user can obtain the network prefix
by calling get_prefix() method from a python program, e.g:
from lnst.Controller.Task import ctl
m = ctl.get_machine("lb")
addr = m.get_ip("nic1")
prefix = m.get_prefix("nic1")
Jan Tluka (2):
Adding prefix template function
Adding prefix method to TaskAPI
lnst/Common/XmlTemplates.py | 53 ++++++++++++++++++++++++++++++++++++++++++++-
lnst/Controller/Machine.py | 11 +++++++++-
lnst/Controller/Task.py | 25 +++++++++++++++++++++
3 files changed, 87 insertions(+), 2 deletions(-)
--
1.8.1.4
10 years, 7 months
[PATCH] lnst-ctl: Adding return value
by Radek Pazdera
The lnst-ctl always exited with 0. This is impractical, especially for
scripting. This commit adds return values to the lnst-ctl command that
properly reflect what happened during the execution.
Currently supported return values:
* RETVAL_PASS = 0: When everything passed with no error
* RETVAL_FAIL = 1: One or more tests failed
* RETVAL_ERR = 2: There was an error in the recipe, during the
matching or configuration
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst-ctl | 51 +++++++++++++++++++++++++++++++++------------------
1 file changed, 33 insertions(+), 18 deletions(-)
diff --git a/lnst-ctl b/lnst-ctl
index 46969c6..ccfa684 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -23,7 +23,10 @@ from lnst.Common.Colours import load_presets_from_config
from lnst.Controller.NetTestController import NetTestController, NetTestError
from lnst.Controller.NetTestResultSerializer import NetTestResultSerializer
-def usage():
+RETVAL_PASS = 0
+RETVAL_FAIL = 1
+RETVAL_ERR = 2
+def usage(retval=0):
"""
Print usage of this app
"""
@@ -43,7 +46,7 @@ def usage():
print " -c, --cleanup perform config cleanup\n" \
" machines"
print " -x, --result=FILE file to write xml_result"
- sys.exit()
+ sys.exit(retval)
def process_recipe(action, file_path, cleanup, res_serializer,
packet_capture, log_ctl, pool_checks):
@@ -62,6 +65,8 @@ def get_recipe_result(args, file_path, cleanup, res_serializer, packet_capture,
res_serializer.add_recipe(file_path)
log_ctl.set_recipe(file_path)
+ retval = RETVAL_PASS
+
res = {}
try:
res = process_recipe(args, file_path, cleanup, res_serializer,
@@ -71,10 +76,15 @@ def get_recipe_result(args, file_path, cleanup, res_serializer, packet_capture,
logging.error(err)
res["passed"] = False
res["err_msg"] = str(err)
+ retval = RETVAL_ERR
res_serializer.set_recipe_result(res)
- return ((file_path, res))
+ # The test failed, but don't override erro
+ if not res["passed"] and retval < RETVAL_FAIL:
+ retval = RETVAL_FAIL
+
+ return (file_path, res, retval)
def main():
"""
@@ -89,8 +99,7 @@ def main():
)
except getopt.GetoptError as err:
print str(err)
- usage()
- sys.exit()
+ usage(RETVAL_ERR)
lnst_config.controller_init()
dirname = os.path.dirname(sys.argv[0])
@@ -120,7 +129,7 @@ def main():
if opt in ("-d", "--debug"):
debug += 1
elif opt in ("-h", "--help"):
- usage()
+ usage(RETVAL_PASS)
elif opt in ("-c", "--cleanup"):
cleanup = True
elif opt in ("-x", "--result"):
@@ -141,15 +150,16 @@ def main():
if len(args) <= 0:
logging.error("No action specified")
- usage()
+ usage(RETVAL_ERR)
action = args.pop()
if not action in ['run', 'config_only', 'match_setup']:
logging.error("Action '%s' not recognised" % action)
- usage()
+ usage(RETVAL_ERR)
summary = []
+ retval = RETVAL_PASS
res_serializer = NetTestResultSerializer()
for recipe_path in args:
if os.path.isdir(recipe_path):
@@ -163,16 +173,19 @@ def main():
recipe_file = os.path.join(recipe_path, f)
if re.match(r'^.*\.xml$', recipe_file):
logging.info("Processing recipe file \"%s\"" % recipe_file)
- summary.append(get_recipe_result(action, recipe_file,
- cleanup,
- res_serializer,
- packet_capture,
- log_ctl, pool_checks))
+ fp, res, rv = get_recipe_result(action, recipe_file,
+ cleanup, res_serializer,
+ packet_capture,
+ log_ctl, pool_checks)
else:
- summary.append(get_recipe_result(action, recipe_path,
- cleanup, res_serializer,
- packet_capture,
- log_ctl, pool_checks))
+ fp, res, rv = get_recipe_result(action, recipe_path,
+ cleanup, res_serializer,
+ packet_capture,
+ log_ctl, pool_checks)
+
+ summary.append((fp, res))
+ if rv > retval:
+ retval = rv
log_ctl.set_recipe("", clean=False)
@@ -184,5 +197,7 @@ def main():
handle.write(res_serializer.get_result_xml())
handle.close()
+ return retval
+
if __name__ == "__main__":
- main()
+ sys.exit(main())
--
1.8.3.1
10 years, 7 months
[lnst] lnst-ctl: Adding return value
by Jiří Pírko
commit d87a023b9b96b98c13d8d79e9752b7935787e2e2
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Mon Sep 9 13:05:32 2013 +0200
lnst-ctl: Adding return value
The lnst-ctl always exited with 0. This is impractical, especially for
scripting. This commit adds return values to the lnst-ctl command that
properly reflect what happened during the execution.
Currently supported return values:
* RETVAL_PASS = 0: When everything passed with no error
* RETVAL_FAIL = 1: One or more tests failed
* RETVAL_ERR = 2: There was an error in the recipe, during the
matching or configuration
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst-ctl | 51 +++++++++++++++++++++++++++++++++------------------
1 files changed, 33 insertions(+), 18 deletions(-)
---
diff --git a/lnst-ctl b/lnst-ctl
index 46969c6..ccfa684 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -23,7 +23,10 @@ from lnst.Common.Colours import load_presets_from_config
from lnst.Controller.NetTestController import NetTestController, NetTestError
from lnst.Controller.NetTestResultSerializer import NetTestResultSerializer
-def usage():
+RETVAL_PASS = 0
+RETVAL_FAIL = 1
+RETVAL_ERR = 2
+def usage(retval=0):
"""
Print usage of this app
"""
@@ -43,7 +46,7 @@ def usage():
print " -c, --cleanup perform config cleanup\n" \
" machines"
print " -x, --result=FILE file to write xml_result"
- sys.exit()
+ sys.exit(retval)
def process_recipe(action, file_path, cleanup, res_serializer,
packet_capture, log_ctl, pool_checks):
@@ -62,6 +65,8 @@ def get_recipe_result(args, file_path, cleanup, res_serializer, packet_capture,
res_serializer.add_recipe(file_path)
log_ctl.set_recipe(file_path)
+ retval = RETVAL_PASS
+
res = {}
try:
res = process_recipe(args, file_path, cleanup, res_serializer,
@@ -71,10 +76,15 @@ def get_recipe_result(args, file_path, cleanup, res_serializer, packet_capture,
logging.error(err)
res["passed"] = False
res["err_msg"] = str(err)
+ retval = RETVAL_ERR
res_serializer.set_recipe_result(res)
- return ((file_path, res))
+ # The test failed, but don't override erro
+ if not res["passed"] and retval < RETVAL_FAIL:
+ retval = RETVAL_FAIL
+
+ return (file_path, res, retval)
def main():
"""
@@ -89,8 +99,7 @@ def main():
)
except getopt.GetoptError as err:
print str(err)
- usage()
- sys.exit()
+ usage(RETVAL_ERR)
lnst_config.controller_init()
dirname = os.path.dirname(sys.argv[0])
@@ -120,7 +129,7 @@ def main():
if opt in ("-d", "--debug"):
debug += 1
elif opt in ("-h", "--help"):
- usage()
+ usage(RETVAL_PASS)
elif opt in ("-c", "--cleanup"):
cleanup = True
elif opt in ("-x", "--result"):
@@ -141,15 +150,16 @@ def main():
if len(args) <= 0:
logging.error("No action specified")
- usage()
+ usage(RETVAL_ERR)
action = args.pop()
if not action in ['run', 'config_only', 'match_setup']:
logging.error("Action '%s' not recognised" % action)
- usage()
+ usage(RETVAL_ERR)
summary = []
+ retval = RETVAL_PASS
res_serializer = NetTestResultSerializer()
for recipe_path in args:
if os.path.isdir(recipe_path):
@@ -163,16 +173,19 @@ def main():
recipe_file = os.path.join(recipe_path, f)
if re.match(r'^.*\.xml$', recipe_file):
logging.info("Processing recipe file \"%s\"" % recipe_file)
- summary.append(get_recipe_result(action, recipe_file,
- cleanup,
- res_serializer,
- packet_capture,
- log_ctl, pool_checks))
+ fp, res, rv = get_recipe_result(action, recipe_file,
+ cleanup, res_serializer,
+ packet_capture,
+ log_ctl, pool_checks)
else:
- summary.append(get_recipe_result(action, recipe_path,
- cleanup, res_serializer,
- packet_capture,
- log_ctl, pool_checks))
+ fp, res, rv = get_recipe_result(action, recipe_path,
+ cleanup, res_serializer,
+ packet_capture,
+ log_ctl, pool_checks)
+
+ summary.append((fp, res))
+ if rv > retval:
+ retval = rv
log_ctl.set_recipe("", clean=False)
@@ -184,5 +197,7 @@ def main():
handle.write(res_serializer.get_result_xml())
handle.close()
+ return retval
+
if __name__ == "__main__":
- main()
+ sys.exit(main())
10 years, 7 months
[PATCH] SlavePool: check corner cases
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit adds checks for two corner cases in machine pool matching:
* recipe contains an isolated machine
* recipe describes a network topology with a network that contains just
* a single machine
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/SlavePool.py | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index a6eb794..cd9e508 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -325,15 +325,21 @@ class SetupMapper:
if dev_info["network"] == net_name:
devs_in_net.append(dev_id)
+ net_in_use = False
for neighbour in net:
n_m_id = neighbour[0]
n_dev_id = neighbour[1]
if n_m_id != m_id:
+ net_in_use = True
for dev_in_net in devs_in_net:
nc = (n_m_id, net_name, dev_in_net)
if not nc in topology[m_id]:
topology[m_id].append(nc)
+ if not net_in_use:
+ msg = "Network '%s' contains only one machine!" % net_name
+ raise SlaveMachineError(msg)
+
return topology
@staticmethod
@@ -586,6 +592,11 @@ class SetupMapper:
template_topology = self._get_topology(template_machines)
pool_topology = self._get_topology(pool_machines)
+ for m, cons in template_topology.iteritems():
+ if len(cons) == 0:
+ msg = "Isolated machine in template topology: '%s'" % m
+ raise SlaveMachineError(msg)
+
if self._map_setup(template_topology, pool_topology):
machine_map = [(tm, pm, self._iface_map[tm]) \
for tm, pm in self._machine_map]
--
1.8.3.1
10 years, 7 months
[PATCH] lnst-ctl: Removing the 'dump' action
by Radek Pazdera
Due to the refactoring of the NetTestController class that was done
recently, the 'dump' action is no longer relevant (as the resources it
uses no longer exist in a proper form).
This patch removes the action altogether.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
install/lnst-ctl.1.in | 14 +++++++-------
lnst-ctl | 6 ++----
lnst/Controller/NetTestController.py | 8 --------
3 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/install/lnst-ctl.1.in b/install/lnst-ctl.1.in
index fb5add9..d29ebab 100644
--- a/install/lnst-ctl.1.in
+++ b/install/lnst-ctl.1.in
@@ -58,10 +58,10 @@ available at LNST wiki (link is listed on
bellow).
.I ACTION
-can be one from
+can be one of
.BR "run",
.BR "config_only" ", and"
-.BR "dump".
+.BR "match_setup".
When it is set to
.BR "run",
@@ -79,12 +79,12 @@ the configuration specified in a recipe file.
At last, when the
.I ACTION
-chosen is
-.BR "dump",
-the network will be configured as specified in the recipe.
+is set to
+.BR "match_setup",
.B lnst-ctl
-will then dump contents of its internal data structures to the standard
-output. This feature can be used for debugging recipes or network setups.
+will only try to match the configuration in the recipe with its local
+pools and print the resulting match, in case it was successful or an
+appropriate error message, in case it was not.
.SH CONFIGURATION
.B lnst-ctl
will look for configuration in the following locations:
diff --git a/lnst-ctl b/lnst-ctl
index 55e2dd1..19c02ef 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -29,7 +29,7 @@ def usage():
"""
print "Usage: %s [OPTION...] [RECIPE...] ACTION" % sys.argv[0]
print ""
- print "ACTION = [run | dump | config_only | match_setup]"
+ print "ACTION = [run | config_only | match_setup]"
print ""
print "OPTIONS"
print " -d, --debug emit debugging messages"
@@ -52,8 +52,6 @@ def process_recipe(action, file_path, cleanup, res_serializer,
pool_checks=pool_checks)
if action == "run":
return nettestctl.run_recipe(packet_capture)
- elif action == "dump":
- return nettestctl.dump_recipe()
elif action == "config_only":
return nettestctl.config_only_recipe()
elif action == "match_setup":
@@ -146,7 +144,7 @@ def main():
usage()
action = args.pop()
- if not action in ['run', 'dump', 'config_only', 'match_setup']:
+ if not action in ['run', 'config_only', 'match_setup']:
logging.error("Action '%s' not recognised" % action)
usage()
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 33ead31..4f0aea3 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -20,7 +20,6 @@ import tempfile
import imp
from time import sleep
from xmlrpclib import Binary
-from pprint import pprint, pformat
from lnst.Common.XmlRpc import ServerProxy, ServerException
from lnst.Common.NetUtils import MacPool
from lnst.Common.VirtUtils import VirtNetCtl, VirtDomainCtl, BridgeCtl
@@ -391,13 +390,6 @@ class NetTestController:
for bridge in self._network_bridges.itervalues():
bridge.cleanup()
- # TODO: This should go away.
- def dump_recipe(self):
- self._prepare_network()
- pprint(self._recipe)
- self._cleanup_slaves()
- return {"passed": True}
-
def match_setup(self):
mreq = self._get_machine_requirements()
self._prepare_provisioning(mreq)
--
1.8.3.1
10 years, 7 months
[PATCH] RecipeParser: Fixing the Comments Bug
by Radek Pazdera
The previous fix of the bug with comments proved ineffective (there are
problems with the comment tags on multiple places). This patch reverts
the previous change and adds a simple preprocessing of the element tree
to remove all comments before it is processed.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst/Controller/RecipeParser.py | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/lnst/Controller/RecipeParser.py b/lnst/Controller/RecipeParser.py
index 9311b4a..2bd6c38 100644
--- a/lnst/Controller/RecipeParser.py
+++ b/lnst/Controller/RecipeParser.py
@@ -34,6 +34,13 @@ class RecipeParser(XmlParser):
def _process(self, lnst_recipe):
recipe = XmlData(lnst_recipe)
+ # remove all comments from the document
+ comments = lnst_recipe.xpath('//comment()')
+ for c in comments:
+ p = c.getparent()
+ if p is not None:
+ p.remove(c)
+
# machines
machines_tag = lnst_recipe.find("machines")
if machines_tag is not None:
@@ -158,10 +165,6 @@ class RecipeParser(XmlParser):
if len(task_tag) > 0:
task["commands"] = XmlCollection(task_tag)
for cmd_tag in task_tag:
- # Ignore comments
- if cmd_tag.tag is etree.Comment:
- continue
-
if cmd_tag.tag == "run":
cmd = self._process_run_cmd(cmd_tag)
elif cmd_tag.tag == "config":
--
1.8.3.1
10 years, 7 months
[lnst] SlavePool: check corner cases
by Jiří Pírko
commit 3d16d397d3c31ce12d119730b7168a00ceabdd27
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Sep 6 14:14:47 2013 +0200
SlavePool: check corner cases
This commit adds checks for two corner cases in machine pool matching:
* recipe contains an isolated machine
* recipe describes a network topology with a network that contains just
* a single machine
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/SlavePool.py | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
---
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index a6eb794..cd9e508 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -325,15 +325,21 @@ class SetupMapper:
if dev_info["network"] == net_name:
devs_in_net.append(dev_id)
+ net_in_use = False
for neighbour in net:
n_m_id = neighbour[0]
n_dev_id = neighbour[1]
if n_m_id != m_id:
+ net_in_use = True
for dev_in_net in devs_in_net:
nc = (n_m_id, net_name, dev_in_net)
if not nc in topology[m_id]:
topology[m_id].append(nc)
+ if not net_in_use:
+ msg = "Network '%s' contains only one machine!" % net_name
+ raise SlaveMachineError(msg)
+
return topology
@staticmethod
@@ -586,6 +592,11 @@ class SetupMapper:
template_topology = self._get_topology(template_machines)
pool_topology = self._get_topology(pool_machines)
+ for m, cons in template_topology.iteritems():
+ if len(cons) == 0:
+ msg = "Isolated machine in template topology: '%s'" % m
+ raise SlaveMachineError(msg)
+
if self._map_setup(template_topology, pool_topology):
machine_map = [(tm, pm, self._iface_map[tm]) \
for tm, pm in self._machine_map]
10 years, 7 months
[PATCH 1/2] NetTestController: Delayed Task Processing
by Radek Pazdera
The way the controller task processing was implemented was blocking the
updates of configuration data, that are distributed from the slaves to
the controller.
This patch delays the processing of individual commands so we can take
the full advantage from the updates.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst/Controller/NetTestController.py | 163 +++++++++++++++++++----------------
1 file changed, 91 insertions(+), 72 deletions(-)
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 33ead31..7d69ca9 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -239,10 +239,9 @@ class NetTestController:
iface.configure()
def _prepare_tasks(self):
- recipe = self._recipe
+ self._tasks = []
for task_data in self._recipe["tasks"]:
task = {}
-
task["quit_on_fail"] = False
if "quit_on_fail" in task_data:
task["quit_on_fail"] = bool_it(task_data["quit_on_fail"])
@@ -255,10 +254,13 @@ class NetTestController:
if not os.path.isfile(path):
msg = "Task file '%s' not found." % path
raise RecipeError(msg, task_data)
+
+ self._tasks.append(task)
continue
- task["commands"] = []
- for cmd_data in task_data["commands"]:
+ task["commands"] = task_data["commands"]
+ task["skeleton"] = []
+ for cmd_data in task["commands"]:
cmd = {"type": cmd_data["type"]}
if "machine" in cmd_data:
@@ -267,79 +269,96 @@ class NetTestController:
msg = "Invalid machine id '%s'." % cmd["machine"]
raise RecipeError(msg, cmd_data)
- if "expect" in cmd_data:
- expect = cmd_data["expect"]
- if expect not in ["pass", "fail"]:
- msg = "Illegal expect attribute value."
- raise RecipeError(msg, cmd_data)
- cmd["expect"] = expect == "pass"
+ if cmd["type"] in ["test", "exec"]:
+ if "bg_id" in cmd_data:
+ cmd["bg_id"] = cmd_data["bg_id"]
+ elif cmd["type"] in ["wait", "intr", "kill"]:
+ cmd["proc_id"] = cmd_data["bg_id"]
- if cmd["type"] == "test":
- cmd["module"] = cmd_data["module"]
+ task["skeleton"].append(cmd)
- cmd_opts = {}
- if "options" in cmd_data:
- for opt in cmd_data["options"]:
- name = opt["name"]
- val = opt["value"]
+ if self._check_task(task):
+ raise RecipeError("Incorrect command sequence.", task_data)
- if name not in cmd_opts:
- cmd_opts[name] = []
+ self._tasks.append(task)
- cmd_opts[name].append({"value": val})
- cmd["options"] = cmd_opts
- elif cmd["type"] == "exec":
+ def _prepare_command(self, cmd_data):
+ cmd = {"type": cmd_data["type"]}
+ if "machine" in cmd_data:
+ cmd["machine"] = cmd_data["machine"]
+ if cmd["machine"] not in self._machines:
+ msg = "Invalid machine id '%s'." % cmd["machine"]
+ raise RecipeError(msg, cmd_data)
+
+ if "expect" in cmd_data:
+ expect = cmd_data["expect"]
+ if expect not in ["pass", "fail"]:
+ msg = "Illegal expect attribute value."
+ raise RecipeError(msg, cmd_data)
+ cmd["expect"] = expect == "pass"
+
+ if cmd["type"] == "test":
+ cmd["module"] = cmd_data["module"]
+
+ cmd_opts = {}
+ if "options" in cmd_data:
+ for opt in cmd_data["options"]:
+ name = opt["name"]
+ val = opt["value"]
+
+ if name not in cmd_opts:
+ cmd_opts[name] = []
+
+ cmd_opts[name].append({"value": val})
+ cmd["options"] = cmd_opts
+ elif cmd["type"] == "exec":
+ cmd["command"] = cmd_data["command"]
+
+ if "from" in cmd_data:
+ tool = cmd_data["from"]
+ if tool in self._resource_table["tools"]:
cmd["command"] = cmd_data["command"]
-
- if "from" in cmd_data:
- tool = cmd_data["from"]
- if tool in self._resource_table["tools"]:
- cmd["command"] = cmd_data["command"]
- else:
- msg = "Tool '%s' not found on the controller" % tool
- raise RecipeError(msg, cmd_data)
- elif cmd["type"] in ["wait", "intr", "kill"]:
- # XXX The internal name (proc_id) is different, because
- # bg_id is already used by LNST in a different context
- cmd["proc_id"] = cmd_data["bg_id"]
- elif cmd["type"] == "config":
- cmd["persistent"] = False
- if "persistent" in cmd_data:
- cmd["persistent"] = bool_it(cmd_data["persistent"])
-
- cmd["options"] = []
- for opt in cmd_data["options"]:
- name = opt["name"]
- value = opt["value"]
- cmd["options"].append({"name": name, "value": value})
- elif cmd["type"] == "ctl_wait":
- cmd["seconds"] = int(cmd_data["seconds"])
else:
- msg = "Unknown command type '%s'" % cmd["type"]
+ msg = "Tool '%s' not found on the controller" % tool
raise RecipeError(msg, cmd_data)
+ elif cmd["type"] in ["wait", "intr", "kill"]:
+ # XXX The internal name (proc_id) is different, because
+ # bg_id is already used by LNST in a different context
+ cmd["proc_id"] = cmd_data["bg_id"]
+ elif cmd["type"] == "config":
+ cmd["persistent"] = False
+ if "persistent" in cmd_data:
+ cmd["persistent"] = bool_it(cmd_data["persistent"])
+
+ cmd["options"] = []
+ for opt in cmd_data["options"]:
+ name = opt["name"]
+ value = opt["value"]
+ cmd["options"].append({"name": name, "value": value})
+ elif cmd["type"] == "ctl_wait":
+ cmd["seconds"] = int(cmd_data["seconds"])
+ else:
+ msg = "Unknown command type '%s'" % cmd["type"]
+ raise RecipeError(msg, cmd_data)
- if cmd["type"] in ["test", "exec"]:
- if "bg_id" in cmd_data:
- cmd["bg_id"] = cmd_data["bg_id"]
-
- if "timeout" in cmd_data:
- try:
- cmd["timeout"] = int(cmd_data["timeout"])
- except ValueError:
- msg = "Timeout value must be an integer."
- raise RecipeError(msg, cmd_data)
+ if cmd["type"] in ["test", "exec"]:
+ if "bg_id" in cmd_data:
+ cmd["bg_id"] = cmd_data["bg_id"]
- task["commands"].append(cmd)
+ if "timeout" in cmd_data:
+ try:
+ cmd["timeout"] = int(cmd_data["timeout"])
+ except ValueError:
+ msg = "Timeout value must be an integer."
+ raise RecipeError(msg, cmd_data)
- if self._check_task(task):
- raise RecipeError("Incorrect command sequence.", task_data)
- self._tasks.append(task)
+ return cmd
def _check_task(self, task):
err = False
bg_ids = {}
- for i, command in enumerate(task["commands"]):
+ for i, command in enumerate(task["skeleton"]):
if command["type"] == "ctl_wait":
continue
@@ -439,13 +458,9 @@ class NetTestController:
overall_res = {"passed": True}
for task in self._tasks:
+ self._res_serializer.add_task()
try:
- self._res_serializer.add_task()
- if "python" in task:
- res = self._run_python_task(task)
- else:
- res = self._run_task(task)
-
+ res = self._run_task(task)
except CommandException as exc:
logging.debug(exc)
overall_res["passed"] = False
@@ -465,7 +480,7 @@ class NetTestController:
return overall_res
def _run_python_task(self, task):
- # Initialize the API handle
+ # Initialize the API handlu
Task.ctl = Task.ControllerAPI(self, self._machines)
name = os.path.basename(task["python"]).split(".")[0]
@@ -473,9 +488,13 @@ class NetTestController:
return module.ctl._result
def _run_task(self, task):
+ if "python" in task:
+ return self._run_python_task(task)
+
seq_passed = True
- for command in task["commands"]:
- cmd_res = self._run_command(command)
+ for cmd_data in task["commands"]:
+ cmd = self._prepare_command(cmd_data)
+ cmd_res = self._run_command(cmd)
if not cmd_res["passed"]:
seq_passed = False
@@ -499,7 +518,7 @@ class NetTestController:
cmd_res = machine.run_command(command)
except Exception as exc:
cmd_res = {"passed": False, "err_msg": "Exception raised."}
- raise exc
+ raise
finally:
if self._res_serializer:
self._res_serializer.add_cmd_result(command, cmd_res)
--
1.8.3.1
10 years, 7 months
[lnst] lnst-ctl: Removing the 'dump' action
by Jiří Pírko
commit a541f8ef4617cfa1bfb095cf6e031c9e838d97f7
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Sep 6 12:58:37 2013 +0200
lnst-ctl: Removing the 'dump' action
Due to the refactoring of the NetTestController class that was done
recently, the 'dump' action is no longer relevant (as the resources it
uses no longer exist in a proper form).
This patch removes the action altogether.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
install/lnst-ctl.1.in | 14 +++++++-------
lnst-ctl | 6 ++----
lnst/Controller/NetTestController.py | 8 --------
3 files changed, 9 insertions(+), 19 deletions(-)
---
diff --git a/install/lnst-ctl.1.in b/install/lnst-ctl.1.in
index fb5add9..d29ebab 100644
--- a/install/lnst-ctl.1.in
+++ b/install/lnst-ctl.1.in
@@ -58,10 +58,10 @@ available at LNST wiki (link is listed on
bellow).
.I ACTION
-can be one from
+can be one of
.BR "run",
.BR "config_only" ", and"
-.BR "dump".
+.BR "match_setup".
When it is set to
.BR "run",
@@ -79,12 +79,12 @@ the configuration specified in a recipe file.
At last, when the
.I ACTION
-chosen is
-.BR "dump",
-the network will be configured as specified in the recipe.
+is set to
+.BR "match_setup",
.B lnst-ctl
-will then dump contents of its internal data structures to the standard
-output. This feature can be used for debugging recipes or network setups.
+will only try to match the configuration in the recipe with its local
+pools and print the resulting match, in case it was successful or an
+appropriate error message, in case it was not.
.SH CONFIGURATION
.B lnst-ctl
will look for configuration in the following locations:
diff --git a/lnst-ctl b/lnst-ctl
index 43770b2..46969c6 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -29,7 +29,7 @@ def usage():
"""
print "Usage: %s [OPTION...] [RECIPE...] ACTION" % sys.argv[0]
print ""
- print "ACTION = [run | dump | config_only | match_setup]"
+ print "ACTION = [run | config_only | match_setup]"
print ""
print "OPTIONS"
print " -d, --debug emit debugging messages"
@@ -52,8 +52,6 @@ def process_recipe(action, file_path, cleanup, res_serializer,
pool_checks=pool_checks)
if action == "run":
return nettestctl.run_recipe(packet_capture)
- elif action == "dump":
- return nettestctl.dump_recipe()
elif action == "config_only":
return nettestctl.config_only_recipe()
elif action == "match_setup":
@@ -146,7 +144,7 @@ def main():
usage()
action = args.pop()
- if not action in ['run', 'dump', 'config_only', 'match_setup']:
+ if not action in ['run', 'config_only', 'match_setup']:
logging.error("Action '%s' not recognised" % action)
usage()
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 30f5599..5404284 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -20,7 +20,6 @@ import tempfile
import imp
from time import sleep
from xmlrpclib import Binary
-from pprint import pprint, pformat
from lnst.Common.XmlRpc import ServerProxy, ServerException
from lnst.Common.NetUtils import MacPool
from lnst.Common.VirtUtils import VirtNetCtl, VirtDomainCtl, BridgeCtl
@@ -411,13 +410,6 @@ class NetTestController:
for bridge in self._network_bridges.itervalues():
bridge.cleanup()
- # TODO: This should go away.
- def dump_recipe(self):
- self._prepare_network()
- pprint(self._recipe)
- self._cleanup_slaves()
- return {"passed": True}
-
def match_setup(self):
mreq = self._get_machine_requirements()
self._prepare_provisioning(mreq)
10 years, 7 months
[lnst] RecipeParser: Fixing the Comments Bug
by Jiří Pírko
commit 1fb8afc1721ac25fa34492c0768da747e77b26b8
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Sep 6 12:46:41 2013 +0200
RecipeParser: Fixing the Comments Bug
The previous fix of the bug with comments proved ineffective (there are
problems with the comment tags on multiple places). This patch reverts
the previous change and adds a simple preprocessing of the element tree
to remove all comments before it is processed.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/RecipeParser.py | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
---
diff --git a/lnst/Controller/RecipeParser.py b/lnst/Controller/RecipeParser.py
index 9311b4a..2bd6c38 100644
--- a/lnst/Controller/RecipeParser.py
+++ b/lnst/Controller/RecipeParser.py
@@ -34,6 +34,13 @@ class RecipeParser(XmlParser):
def _process(self, lnst_recipe):
recipe = XmlData(lnst_recipe)
+ # remove all comments from the document
+ comments = lnst_recipe.xpath('//comment()')
+ for c in comments:
+ p = c.getparent()
+ if p is not None:
+ p.remove(c)
+
# machines
machines_tag = lnst_recipe.find("machines")
if machines_tag is not None:
@@ -158,10 +165,6 @@ class RecipeParser(XmlParser):
if len(task_tag) > 0:
task["commands"] = XmlCollection(task_tag)
for cmd_tag in task_tag:
- # Ignore comments
- if cmd_tag.tag is etree.Comment:
- continue
-
if cmd_tag.tag == "run":
cmd = self._process_run_cmd(cmd_tag)
elif cmd_tag.tag == "config":
10 years, 7 months