From: Ondrej Lichtner olichtne@redhat.com
Exceptions raised during execution of triggers are now catched and transformed into XmlProcessing exceptions. This gives the user additional information about where the problem occured during parsing of the recipe.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- NetTest/NetTestParse.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/NetTest/NetTestParse.py b/NetTest/NetTestParse.py index fbe5adc..4c46b0c 100644 --- a/NetTest/NetTestParse.py +++ b/NetTest/NetTestParse.py @@ -139,8 +139,11 @@ class NetMachineConfigParse(RecipeParser):
info["system_config"] = {}
- self._trigger_event("machine_info_ready", - {"machine_id": self._machine_id}) + try: + self._trigger_event("machine_info_ready", + {"machine_id": self._machine_id}) + except Exception, exc: + raise XmlProcessingError(str(exc), node)
def _netdevices(self, node, params): scheme = {"netdevice": self._netdevice, @@ -179,8 +182,11 @@ class NetMachineConfigParse(RecipeParser): self._has_attribute(node, "libvirt_bridge"): dev["libvirt_bridge"] = self._get_attribute(node, "libvirt_bridge")
- self._trigger_event("netdevice_ready", {"machine_id": self._machine_id, - "dev_id": phys_id}) + try: + self._trigger_event("netdevice_ready", + {"machine_id": self._machine_id, "dev_id": phys_id}) + except Exception, exc: + raise XmlProcessingError(str(exc), node)
class NetConfigParse(RecipeParser): @@ -230,9 +236,12 @@ class NetConfigParse(RecipeParser):
self._process_child_nodes(node, scheme, params)
- self._trigger_event("interface_config_ready", - {"machine_id": self._machine_id, - "netdev_config_id": dev_id}) + try: + self._trigger_event("interface_config_ready", + {"machine_id": self._machine_id, + "netdev_config_id": dev_id}) + except Exception, exc: + raise XmlProcessingError(str(exc), node)
def _process_phys_id_attr(self, node, dev): netconfig = self._netconfig
From: Ondrej Lichtner olichtne@redhat.com
Since machine preparation is done during recipe parsing, exceptions result in a crash of the application without cleaning up the partial changes. This commit fixes that by calling cleanup functions after an exception was raised.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- NetTest/NetTestController.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py index 296150d..839d51c 100644 --- a/NetTest/NetTestController.py +++ b/NetTest/NetTestController.py @@ -276,7 +276,14 @@ class NetTestController: def _prepare(self): # All the perparations are made within the recipe parsing # This is achieved by handling parser events (by registering - self._ntparse.parse_recipe() + try: + self._ntparse.parse_recipe() + except Exception, exc: + logging.debug("Exception raised during recipe parsing. "\ + "Deconfiguring machines.") + self._deconfigure_slaves() + self._disconnect_slaves() + raise exc
def _run_command(self, command): machine_id = command["machine_id"]
From: Ondrej Lichtner olichtne@redhat.com
Currently cleanup expects that all the machines were configured without problems. However, this isn't true when an error occured during recipe parsing.
This commit fixes that by skipping parts that were not configured yet. It skips machines that don't yet have an rpc connection initialized because these couldn't have been configured previously. It also introduces a new list info["created_devices"] which contains all properly created dynamic devices that need to be removed.
Both of these were added because recipe parsing can fail after creating data structures for the machine/devices but before actually storing data in them. This can result in exceptions during cleanup which is again unwanted behaviour. I don't know if this is the best solution so if you have a better idea I am open for discussion.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- NetTest/NetTestController.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py index 839d51c..72233c5 100644 --- a/NetTest/NetTestController.py +++ b/NetTest/NetTestController.py @@ -136,6 +136,10 @@ class NetTestController: % (dev_id, dev["hwaddr"], machine_id) raise NetTestError(msg)
+ if 'created_devices' not in info: + info['created_devices'] = [] + info['created_devices'].append((dev_id, dev)) + phys_devs = rpc.get_devices_by_hwaddr(dev["hwaddr"]) if len(phys_devs) == 1: pass @@ -247,18 +251,20 @@ class NetTestController: def _deconfigure_slaves(self): for machine_id in self._recipe["machines"]: info = self._get_machineinfo(machine_id) + if "rpc" not in info: + continue rpc = self._get_machinerpc(machine_id) for if_id in reversed(info["configured_interfaces"]): rpc.deconfigure_interface(if_id)
# detach dynamically created devices - machine = self._recipe["machines"][machine_id] - for dev_id, dev in machine["netdevices"].iteritems(): - if dev["create"] == "libvirt": - logging.info("Removing netdevice %d (%s) from machine %d", - dev_id, dev["hwaddr"], machine_id) - domain_ctl = info["virt_domain_ctl"] - domain_ctl.detach_interface(dev["hwaddr"]) + if "created_devices" not in info: + continue + for dev_id, dev in reversed(info["created_devices"]): + logging.info("Removing netdevice %d (%s) from machine %d", + dev_id, dev["hwaddr"], machine_id) + domain_ctl = info["virt_domain_ctl"] + domain_ctl.detach_interface(dev["hwaddr"])
# remove dynamically created bridges networks = self._recipe["networks"]
lnst-developers@lists.fedorahosted.org