From: Ondrej Lichtner olichtne@redhat.com
This commit fixes a bug that appears when a test option is missing in the recipe. When such a situation appears, the slave throws an exception that wasn't handled anywhere and resulted in the crash of the controller.
After this commit the commands can either return properly- the have a result, end with a KeyboardInterrupt or be killed - a default result is set, or a different exception is raised - the command result is set to fail and the exception is saved in result data. This shows up nicely in results on the controller.
The missing option exception now also says which option is missing.
Another problem that appears is when an unexpected exception is raised on the slave and is not handled- in such a situation the controller will crash, and nothing nice can be written to the results. This situation is now handled and the results will contain an exception logged into debug logs (on the slave and sent to controller), and the controller will report an unexpected exception being raised on a certain slave machine.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Common/NetTestCommand.py | 18 ++++++++---------- lnst/Common/TestsCommon.py | 2 +- lnst/Controller/NetTestController.py | 6 +++++- lnst/Slave/NetTestSlave.py | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/lnst/Common/NetTestCommand.py b/lnst/Common/NetTestCommand.py index 965f675..fa36d29 100644 --- a/lnst/Common/NetTestCommand.py +++ b/lnst/Common/NetTestCommand.py @@ -144,21 +144,18 @@ class NetTestCommand: result = {} try: self._cmd_cls.run() - res_data = self._cmd_cls.get_result() - result["type"] = "result" - result["cmd_id"] = self._id - result["result"] = res_data except KeyboardInterrupt: + pass + except: + type, value, tb = sys.exc_info() + data = {"Exception": "%s" % value} + self._cmd_cls.set_fail(data) + finally: res_data = self._cmd_cls.get_result() result["type"] = "result" result["cmd_id"] = self._id result["result"] = res_data - except: - type, value, tb = sys.exc_info() - result = {"type": "exception", - "cmd_id": self._id, - "Exception": ''.join(traceback.format_exception(type, - value, tb))} + send_data(self._write_pipe, result) self._write_pipe.close()
@@ -243,6 +240,7 @@ def NetTestCommandTest(command, resource_table): test_name = command["module"] if not test_name in resource_table["module"]: msg = "Test module '%s' not found" % test_name + raise Exception(msg)
module_path = resource_table["module"][test_name] module_name = "Test%s" % test_name diff --git a/lnst/Common/TestsCommon.py b/lnst/Common/TestsCommon.py index 3008e81..01ae678 100644 --- a/lnst/Common/TestsCommon.py +++ b/lnst/Common/TestsCommon.py @@ -105,7 +105,7 @@ class TestGeneric(NetTestCommandGeneric): option = self._command["options"][name] except KeyError: if mandatory: - raise TestOptionMissing + raise TestOptionMissing("Missing option '%s'!" % name) if multi: return [default] else: diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py index a88058f..2d562e0 100644 --- a/lnst/Controller/NetTestController.py +++ b/lnst/Controller/NetTestController.py @@ -597,7 +597,11 @@ class NetTestController: try: cmd_res = machine.run_command(command) except Exception as exc: - cmd_res = {"passed": False, "err_msg": "Exception raised."} + cmd_res = {"passed": False, + "res_data": {"Exception": str(exc)}, + "msg": "Exception raised.", + "res_header": "EXCEPTION", + "report": str(exc)} raise finally: if self._res_serializer: diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index cbb3958..f68b96f 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -511,7 +511,7 @@ class NetTestSlave: % msg["cmd_id"]) else: logging.debug("Recieved an exception from foreground command") - logging.error(msg["Exception"]) + logging.debug(msg["Exception"]) cmd = self._cmd_context.get_cmd(msg["cmd_id"]) cmd.join() self._cmd_context.del_cmd(cmd)
lnst-developers@lists.fedorahosted.org