[lnst] SlavePool: Check for duplicate configs
by Jiří Pírko
commit 2ed4e1e80de597309833a2b144682a63fcea3e74
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Sep 20 12:53:46 2013 +0200
SlavePool: Check for duplicate configs
This commit adds a checkf for machine duplicity in the pool. Sometimes,
one might forget an old slavemachine in the pool. Having two configs
reference the same machine will most likely lead to lockups.
This situation is very hard to debug, so we're adding a check for it.
Signed-off-by: Radek Pazdera <rpazdera(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 301ea60..ebd3c2a 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -84,6 +84,17 @@ class SlavePool:
xml_data = parser.parse()
machine_spec = self._process_machine_xml_data(m_id, xml_data)
+ # Check if there isn't any machine with the same
+ # hostname or libvirt_domain already in the pool
+ for pm_id, m in self._pool.iteritems():
+ pm = m["params"]
+ rm = machine_spec["params"]
+ if pm["hostname"] == rm["hostname"] or \
+ pm["libvirt_domain"] == rm["libvirt_domain"]:
+ msg = "You have the same machine listed twice in " \
+ "your pool ('%s' and '%s')." % (m_id, pm_id)
+ raise SlaveMachineError(msg)
+
if self._pool_checks:
available = False
10 years, 7 months
[lnst] SlavePool: fix object initialization
by Jiří Pírko
commit 10db214eba1faf3c6b9b0670922381a3249b350a
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Sep 20 12:50:32 2013 +0200
SlavePool: fix object initialization
Object specific attributes have to be initialized in the constructor. If
they are initialized under the class definition, the attribute objects
will be shared between instances.
This caused a bug to appear- when running multiple recipes, if a slave
machine is available during one recipe, but becomes unavailable before
the next recipe it will still be considered during machine matching for
the next recipe.
This commit fixes that bug.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/SlavePool.py | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
---
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index bd81f81..301ea60 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -32,19 +32,16 @@ class SlavePool:
This class is responsible for managing test machines that
are available at the controler and can be used for testing.
"""
+ def __init__(self, pool_dirs, allow_virtual=False, pool_checks=True):
+ self._map = {}
+ self._pool = {}
- _map = {}
- _pool = {}
-
- _machine_matches = []
- _network_matches = []
-
- _allow_virt = False
- _pool_checks = True
+ self._machine_matches = []
+ self._network_matches = []
- def __init__(self, pool_dirs, allow_virtual=False, pool_checks=True):
self._allow_virt = allow_virtual
self._pool_checks = pool_checks
+
logging.info("Checking machine pool availability.")
for pool_dir in pool_dirs:
self.add_dir(pool_dir)
10 years, 7 months
[lnst] Machine: exceptions during deconfiguration fix
by Jiří Pírko
commit 017f3d21aa78e2ed6e6ef0ee3a0ff3e18d148adc
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Sep 20 12:50:10 2013 +0200
Machine: exceptions during deconfiguration fix
This patch adds a few try-except blocks for machine deconfiguration. The
important part is that the slave is always disconnected in the end, and
that dynamic devices get detached when something fails.
Exceptions during deconfiguration caused that the controller never
disconnected from the slave, and the slave would be locked listening on
this socket. This would cause problems when there are multiple recipes
being processed in a single lnst-ctl call.
It is also important to continue the cleanup of remaining machines when
cleanup on one machine fails.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/Machine.py | 30 ++++++++++++++++++------------
lnst/Controller/NetTestController.py | 5 ++++-
2 files changed, 22 insertions(+), 13 deletions(-)
---
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index fdd400a..4ac7d2f 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -158,24 +158,30 @@ class Machine(object):
#connection to the slave was closed
if not self._msg_dispatcher.get_connection(self._id):
- #we still need to remove virtual interfaces
- if deconfigure:
- for iface in reversed(self._interfaces):
- if isinstance(iface, VirtualInterface):
- iface.cleanup()
return
- self._rpc_call("kill_cmds")
+ try:
+ self._rpc_call("kill_cmds")
- if deconfigure:
+ if deconfigure:
+ for iface in reversed(self._interfaces):
+ iface.deconfigure()
+ iface.cleanup()
+
+ self._rpc_call("bye")
+ except:
+ #cleanup is only meaningful on dynamic interfaces, and should
+ #always be called when deconfiguration happens- especially
+ #when something on the slave breaks during deconfiguration
for iface in reversed(self._interfaces):
- iface.deconfigure()
+ if not isinstance(iface, VirtualInterface):
+ continue
iface.cleanup()
+ raise
+ finally:
+ self._msg_dispatcher.disconnect_slave(self.get_id())
- self._rpc_call("bye")
- self._msg_dispatcher.disconnect_slave(self.get_id())
-
- self._configured = False
+ self._configured = False
def _timeout_handler(self, signum, frame):
msg = "RPC connection to machine %s timed out" % self.get_id()
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index c2d7d65..a88058f 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -405,7 +405,10 @@ class NetTestController:
for machine_id, machine in self._machines.iteritems():
if machine.is_configured():
- machine.cleanup(deconfigure)
+ try:
+ machine.cleanup(deconfigure)
+ except:
+ pass
#clean-up slave logger
self._log_ctl.remove_slave(machine_id)
10 years, 7 months
[lnst] Machine: remember original hwaddr for virt devices
by Jiří Pírko
commit 6cfe9e37c4fdef7b9276f6ce6342b9f4846d3442
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Sep 20 12:49:42 2013 +0200
Machine: remember original hwaddr for virt devices
Since the controller now recieves updates about interface hwaddrs from
the slave, we need to remember the original hwaddr of dynamically
created devices, because it's the only one we can use for deleting the
interface later.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/Machine.py | 10 +++++++++-
lnst/Controller/NetTestController.py | 2 +-
2 files changed, 10 insertions(+), 2 deletions(-)
---
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 22d1f0b..fdd400a 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -484,6 +484,13 @@ class VirtualInterface(Interface):
def __init__(self, machine, if_id, if_type):
super(VirtualInterface, self).__init__(machine, if_id, if_type)
+ def get_orig_hwaddr(self):
+ if not self._orig_hwaddr:
+ msg = "Hardware address is not available for interface '%s'" \
+ % self.get_id()
+ raise MachineError(msg)
+ return self._orig_hwaddr
+
def initialize(self):
domain_ctl = self._machine.get_domain_ctl()
@@ -513,6 +520,7 @@ class VirtualInterface(Interface):
logging.info("Creating interface %s (%s) on machine %s",
self.get_id(), self._hwaddr, self._machine.get_id())
+ self._orig_hwaddr = self._hwaddr
domain_ctl.attach_interface(self._hwaddr, br_name)
@@ -533,7 +541,7 @@ class VirtualInterface(Interface):
def cleanup(self):
domain_ctl = self._machine.get_domain_ctl()
- domain_ctl.detach_interface(self._hwaddr)
+ domain_ctl.detach_interface(self._orig_hwaddr)
def is_ready(self):
ifaces = self._machine._rpc_call('get_devices_by_hwaddr', self._hwaddr)
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index fd7692d..c2d7d65 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -426,7 +426,7 @@ class NetTestController:
machine["interfaces"] = []
for i in m._interfaces:
- hwaddr = i.get_hwaddr()
+ hwaddr = i.get_orig_hwaddr()
machine["interfaces"].append(hwaddr)
10 years, 7 months
[lnst] NmConfigDevice: soft device removal not needed for new NM
by Jiří Pírko
commit 8328f0029cccb044349a3cae9fa185cb3771299a
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Fri Sep 20 12:49:03 2013 +0200
NmConfigDevice: soft device removal not needed for new NM
This commit encapsulates the removal of soft devices in a try-except
block. The cade is there only because the current version of NM doesn't
remove these devices on its own. In the future however NM will handle
it, and it already works on the current git build. In these cases the
device removal would fail with an exception which is unwanted.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NmConfigDevice.py | 33 +++++++++++++++++++++------------
1 files changed, 21 insertions(+), 12 deletions(-)
---
diff --git a/lnst/Slave/NmConfigDevice.py b/lnst/Slave/NmConfigDevice.py
index 3d12c55..a2ad57f 100644
--- a/lnst/Slave/NmConfigDevice.py
+++ b/lnst/Slave/NmConfigDevice.py
@@ -391,9 +391,12 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
self._nm_rm_connection(netdev["con_obj_path"])
netdev["con_obj_path"] = ""
- #NM doesn't know how to remove soft devices...
- bond_masters = "/sys/class/net/bonding_masters"
- exec_cmd('echo "-%s" > %s' % (netdev["name"], bond_masters))
+ #older versions of NM don't know how to remove soft devices...
+ try:
+ bond_masters = "/sys/class/net/bonding_masters"
+ exec_cmd('echo "-%s" > %s' % (netdev["name"], bond_masters))
+ except:
+ pass
def _add_slaves(self):
for slave in get_slaves(self._netdev):
@@ -501,9 +504,12 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
self._nm_rm_connection(netdev["con_obj_path"])
netdev["con_obj_path"] = ""
- #NM doesn't know how to remove soft devices...
- exec_cmd("ip link set %s down" % netdev["name"])
- exec_cmd("brctl delbr %s " % netdev["name"])
+ #older versions of NM don't know how to remove soft devices...
+ try:
+ exec_cmd("ip link set %s down" % netdev["name"])
+ exec_cmd("brctl delbr %s " % netdev["name"])
+ except:
+ pass
def _add_slave(self, slave):
netdev = self._config[slave]
@@ -640,13 +646,16 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
self._nm_rm_connection(netdev["con_obj_path"])
netdev["con_obj_path"] = ""
- #NM doesn't know how to remove soft devices...
+ #older versions of NM don't know how to remove soft devices...
#and lnst will break when multiple devices with the same mac exist
- dev_name = self._get_vlan_info()[0]
- if self._check_ip_link_add():
- exec_cmd("ip link del %s" % dev_name)
- else:
- exec_cmd("vconfig rem %s" % dev_name)
+ try:
+ dev_name = self._get_vlan_info()[0]
+ if self._check_ip_link_add():
+ exec_cmd("ip link del %s" % dev_name)
+ else:
+ exec_cmd("vconfig rem %s" % dev_name)
+ except:
+ pass
class NmConfigDeviceTeam(NmConfigDeviceGeneric):
#Not supported by NetworkManager yet
10 years, 7 months
[lnst] schema: Fixing address and alias bugs
by Jiří Pírko
commit a784fea75d133073ff4e0fc9e8e5ecee127c9c06
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Thu Sep 19 15:15:31 2013 +0200
schema: Fixing address and alias bugs
The scheme cover situations when we omit the value of the address tag
and replace it with text instead:
<address value="1.2.3.4/32"/>
<address>1.2.3.4/32</address>
The same problem occured with defining aliases. This patch fixes those
issues.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Common/XmlParser.py | 5 +++--
lnst/Common/XmlTemplates.py | 8 ++++++--
schema-recipe.rng | 12 ++++++++----
3 files changed, 17 insertions(+), 8 deletions(-)
---
diff --git a/lnst/Common/XmlParser.py b/lnst/Common/XmlParser.py
index e50a2f2..51f7273 100644
--- a/lnst/Common/XmlParser.py
+++ b/lnst/Common/XmlParser.py
@@ -109,10 +109,11 @@ class XmlParser(object):
return attr in element.attrib
def _get_attribute(self, element, attr):
- return self._template_proc.expand_functions(element.attrib[attr])
+ text = element.attrib[attr].strip()
+ return self._template_proc.expand_functions(text)
def _get_content(self, element):
- text = etree.tostring(element, method="text")
+ text = etree.tostring(element, method="text").strip()
return self._template_proc.expand_functions(text)
def _expand_xinclude(self, elem, base_url=""):
diff --git a/lnst/Common/XmlTemplates.py b/lnst/Common/XmlTemplates.py
index a2afd05..1d7a9fd 100644
--- a/lnst/Common/XmlTemplates.py
+++ b/lnst/Common/XmlTemplates.py
@@ -22,6 +22,7 @@ rpazdera(a)redhat.com (Radek Pazdera)
"""
import re
+from lxml import etree
from lnst.Common.XmlProcessing import XmlTemplateString
class XmlTemplateError(Exception):
@@ -319,8 +320,11 @@ class XmlTemplates:
if element.tag == "define":
for alias in element.getchildren():
- name = alias.attrib["name"]
- value = alias.attrib["value"]
+ name = alias.attrib["name"].strip()
+ if "value" in alias.attrib:
+ value = alias.attrib["value"].strip()
+ else:
+ value = etree.tostring(element, method="text").strip()
self.define_alias(name, value)
parent = element.getparent()
parent.remove(element)
diff --git a/schema-recipe.rng b/schema-recipe.rng
index 7e417cb..34ab1fd 100644
--- a/schema-recipe.rng
+++ b/schema-recipe.rng
@@ -21,8 +21,10 @@
<oneOrMore>
<element name="alias">
<attribute name="name"/>
- <attribute name="value"/>
- <text/>
+ <choice>
+ <attribute name="value"/>
+ <text/>
+ </choice>
</element>
</oneOrMore>
</element>
@@ -248,8 +250,10 @@
<zeroOrMore>
<element name="address">
- <attribute name="value"/>
- <text/>
+ <choice>
+ <attribute name="value"/>
+ <text/>
+ </choice>
</element>
</zeroOrMore>
</interleave>
10 years, 7 months
[PATCH] NetTestController: Check tasks before configuration
by Radek Pazdera
The tasks were checked after all the machines were configured. And in
case there was some trivial error in the task (such as a wrong path),
the whole network configuration was just a plain waste of time.
This commit moves the checks before the configuration is processed.
Issue #36
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
lnst/Controller/NetTestController.py | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index fd7692d..bcdd4c1 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -167,9 +167,6 @@ class NetTestController:
def _prepare_network(self):
recipe = self._recipe
- mreq = self._get_machine_requirements()
- self._prepare_provisioning(mreq)
-
machines = self._machines
for m_id in machines.keys():
self._prepare_machine(m_id)
@@ -179,7 +176,8 @@ class NetTestController:
for iface_xml_data in machine_xml_data["interfaces"]:
self._prepare_interface(m_id, iface_xml_data)
- def _prepare_provisioning(self, mreq):
+ def _prepare_provisioning(self):
+ mreq = self._get_machine_requirements()
sp = self._slave_pool
machines = self._machines
if not sp.provision_machines(mreq, machines):
@@ -477,13 +475,13 @@ class NetTestController:
os.remove("/tmp/.lnst_virt_conf")
def match_setup(self):
- mreq = self._get_machine_requirements()
- self._prepare_provisioning(mreq)
+ self._prepare_provisioning()
return {"passed": True}
def config_only_recipe(self):
try:
+ self._prepare_provisioning()
self._prepare_network()
except (KeyboardInterrupt, Exception) as exc:
msg = "Exception raised during configuration."
@@ -500,8 +498,9 @@ class NetTestController:
def run_recipe(self, packet_capture=False):
try:
- self._prepare_network()
+ self._prepare_provisioning()
self._prepare_tasks()
+ self._prepare_network()
except (KeyboardInterrupt, Exception) as exc:
msg = "Exception raised during configuration."
logging.error(msg)
--
1.8.3.1
10 years, 7 months
[PATCH] smoke: remove source references
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit removes the old source attributes, since we moved to using
XInclude. But since using XInclude for such simple recipe generation is
a bit of an overkill the generation script uses simple string replacing.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
recipes/smoke/generate-recipes.py | 61 +++++++++------------------------------
recipes/smoke/lib/recipe-temp.xml | 8 ++---
2 files changed, 18 insertions(+), 51 deletions(-)
diff --git a/recipes/smoke/generate-recipes.py b/recipes/smoke/generate-recipes.py
index c7eedb9..2361aab 100755
--- a/recipes/smoke/generate-recipes.py
+++ b/recipes/smoke/generate-recipes.py
@@ -45,48 +45,6 @@ def replace_variables(recipe, name1, name2, variables):
recipe = recipe.replace("#%s#" % name, val)
return recipe
-def handleNode(node):
- if node.nodeType == node.ELEMENT_NODE:
- if node.hasAttribute("source"):
- src_file_name = node.getAttribute("source")
- loaded_dom = xml.dom.minidom.parse(src_file_name)
- loaded_node = None
- try:
- loaded_node = loaded_dom.getElementsByTagName(node.nodeName)[0]
- except Exception:
- msg = ("No '%s' element present in included file '%s'."
- % (node.nodeName, src_file_name))
- raise Exception(msg, node)
-
- old_attrs = node.attributes
-
- parent = node.parentNode
- parent.replaceChild(loaded_node, node)
- node = loaded_node
-
- # copy all of the original attributes to the sourced node
- for i in range(old_attrs.length):
- attr = old_attrs.item(i)
- # do not overwrite sourced attributes
- if not node.hasAttribute(attr.name) and attr.name != "source":
- node.setAttribute(attr.name, attr.value)
-
- handleNode(node)
- else:
- childNodes = list(node.childNodes)
- for child in childNodes:
- if child.nodeType == node.TEXT_NODE and child.data.isspace():
- node.removeChild(child)
- else:
- handleNode(child)
-
-def expand_sources(recipe):
- document = xml.dom.minidom.parseString(recipe)
- for child in document.childNodes:
- handleNode(child)
- recipe = document.toprettyxml()
- return recipe
-
def main():
DIR = "tests/"
LIB = "../lib/"
@@ -104,7 +62,11 @@ def main():
if not re.match("task-.*", seq):
continue
print "Found a task: %s%s" % (LIB, seq)
- sequences += "\n <task source=\"%s%s\"/>" % (LIB, seq)
+
+ task_f = open("%s/%s" % (LIB, seq), 'r')
+ task = task_f.read()
+
+ sequences += "\n%s" % task
conf_files = [LIB+i for i in os.listdir(LIB) if re.match("conf-.*", i)]
for conf in conf_files:
@@ -123,11 +85,16 @@ def main():
recipe_name = "recipe-%s-%s.xml" % (name1, name2)
print "Generating %s%s..." % (DIR, recipe_name),
- recipe = template.replace("#CONF1#", machine1)\
- .replace("#CONF2#", machine2)\
- .replace("#SEQUENCES#", sequences)
+ m1_f = open(machine1, 'r')
+ m1 = m1_f.read()
+
+ m2_f = open(machine2, 'r')
+ m2 = m2_f.read()
- recipe = expand_sources(recipe)
+
+ recipe = template.replace("#CONF1#", m1)\
+ .replace("#CONF2#", m2)\
+ .replace("#SEQUENCES#", sequences)
recipe = replace_variables(recipe, name1, name2, variables)
diff --git a/recipes/smoke/lib/recipe-temp.xml b/recipes/smoke/lib/recipe-temp.xml
index 954b7ef..ad03a3f 100644
--- a/recipes/smoke/lib/recipe-temp.xml
+++ b/recipes/smoke/lib/recipe-temp.xml
@@ -1,17 +1,17 @@
-<lnstrecipe>
+<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude">
<machines>
<machine id="1">
<define>
<alias name="testip" value="192.168.100.240/24"/>
</define>
- <interfaces source="#CONF1#"/>
+ #CONF1#
</machine>
<machine id="2">
<define>
<alias name="testip" value="192.168.100.215/24"/>
</define>
- <interfaces source="#CONF2#"/>
+ #CONF2#
</machine>
</machines>
#SEQUENCES#
-</lnstrecipe>
\ No newline at end of file
+</lnstrecipe>
--
1.8.3.1
10 years, 7 months
[PATCH] NetTestController: print value of slave exceptions
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
Previously the controller would only print that there was an exception
raised on a certain slave machine, and there would be a traceback in
debug logs from that slave. Now the value of the exception will be added
to our controller logs, that makes it easier to spot what went wrong
without looking up the traceback.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/NetTestController.py | 2 +-
lnst/Controller/NetTestResultSerializer.py | 2 +-
lnst/Slave/NetTestSlave.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 2d562e0..2928595 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -756,7 +756,7 @@ class MessageDispatcher(ConnectionHandler):
machine = self._machines[message[0]]
machine.interface_update(message[1])
elif message[1]["type"] == "exception":
- msg = "Recieved an exception from slave: %s" % message[0]
+ msg = "Slave %s: %s" % (message[0], message[1]["Exception"])
raise CommandException(msg)
elif message[1]["type"] == "error":
msg = "Recieved an error message from slave %s: %s" %\
diff --git a/lnst/Controller/NetTestResultSerializer.py b/lnst/Controller/NetTestResultSerializer.py
index 514988b..9c26dfc 100644
--- a/lnst/Controller/NetTestResultSerializer.py
+++ b/lnst/Controller/NetTestResultSerializer.py
@@ -76,7 +76,7 @@ class NetTestResultSerializer:
if recipe["result"] == "FAIL" and \
"err_msg" in recipe and recipe["err_msg"] != "":
err_msg = recipe["err_msg"]
- output_pairs.append((4*" " + "error message:" + err_msg, ""))
+ output_pairs.append((4*" " + "error message: " + err_msg, ""))
seq_num = 1
for task in recipe["tasks"]:
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index b867db2..76359d5 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -489,7 +489,7 @@ class NetTestSlave:
type, value, tb = sys.exc_info()
exc_trace = ''.join(traceback.format_exception(type,
value, tb))
- response = {"type": "exception", "Exception": exc_trace}
+ response = {"type": "exception", "Exception": value}
self._server_handler.send_data_to_ctl(response)
return
--
1.8.3.1
10 years, 7 months
[PATCH] Machine: default command timeout
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
We used to have a default timeout for commands with the previous rpc
implementation, but didn't implement it in the new one. This commit adds
a default timeout for commands, the time is set in the DEFAULT_TIMEOUT
constant, which for now is 60 seconds.
This also fixes result reporting for killed commands.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Common/NetTestCommand.py | 8 ++++----
lnst/Controller/Machine.py | 12 +++++++++---
lnst/Slave/NetTestSlave.py | 2 +-
3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/lnst/Common/NetTestCommand.py b/lnst/Common/NetTestCommand.py
index fa36d29..9e1708d 100644
--- a/lnst/Common/NetTestCommand.py
+++ b/lnst/Common/NetTestCommand.py
@@ -187,13 +187,13 @@ class NetTestCommand:
def get_result(self):
if self._killed:
- result = {}
+ self._cmd_cls.set_pass()
+ result = self._cmd_cls.get_result()
result["passed"] = True
result["msg"] = "Command killed."
- else:
- result = self._result
+ self._result = result
- return result
+ return self._result
def set_result(self, result):
if self._control_cmd != None:
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 4ac7d2f..36c9d52 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -29,6 +29,8 @@ from lnst.Common.Utils import wait_for, md5sum, dir_md5sum, create_tar_archive
from lnst.Common.ConnectionHandler import send_data, recv_data
from lnst.Common.ConnectionHandler import ConnectionHandler
+DEFAULT_TIMEOUT = 60
+
class MachineError(Exception):
pass
@@ -196,15 +198,19 @@ class Machine(object):
timeout = command["timeout"]
logging.debug("Setting timeout to \"%d\"", timeout)
signal.alarm(timeout)
+ else:
+ logging.debug("Setting default timeout (%ds)." % DEFAULT_TIMEOUT)
+ signal.alarm(DEFAULT_TIMEOUT)
try:
cmd_res = self._rpc_call("run_command", command)
except MachineError as exc:
if "bg_id" in command:
- self._rpc_call("kill_command", command["bg_id"])
+ cmd_res = self._rpc_call("kill_command", command["bg_id"])
else:
- self._rpc_call("kill_command", None)
- cmd_res = {"passed": False, "err_msg": str(exc)}
+ cmd_res = self._rpc_call("kill_command", None)
+ cmd_res["passed"] = False
+ cmd_res["msg"] = str(exc)
signal.alarm(0)
signal.signal(signal.SIGALRM, prev_handler)
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index f68b96f..b867db2 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -287,7 +287,7 @@ class SlaveMethods:
cmd = self._command_context.get_cmd(id)
cmd.kill(None)
self._command_context.del_cmd(cmd)
- return True
+ return cmd.get_result()
def machine_cleanup(self):
logging.info("Performing machine cleanup.")
--
1.8.3.1
10 years, 7 months