commit 28f087c9ed39f0813ed9ef0e6e2783b9bb14da98 Author: Jiri Pirko jpirko@redhat.com Date: Thu Jun 30 14:05:52 2011 +0200
NetTest: introduce result XML serialization
Signed-off-by: Jiri Pirko jpirko@redhat.com
NetTest/NetTestCommand.py | 6 +- NetTest/NetTestController.py | 8 +++- NetTest/NetTestResultSerializer.py | 75 ++++++++++++++++++++++++++++++++++++ nettestctl.py | 31 +++++++++++---- 4 files changed, 107 insertions(+), 13 deletions(-) --- diff --git a/NetTest/NetTestCommand.py b/NetTest/NetTestCommand.py index a6dca5b..0c9bc54 100644 --- a/NetTest/NetTestCommand.py +++ b/NetTest/NetTestCommand.py @@ -19,12 +19,12 @@ import pickle, traceback from Common.ExecCmd import exec_cmd, ExecCmdFail
def str_command(command): - out = ("type "%s", machine_id "%d", value "%s"" + out = ("type (%s), machine_id (%d), value (%s)" % (command["type"], command["machine_id"], command["value"])) if "timeout" in command: - out += ", timeout "%d"" % command["timeout"] + out += ", timeout (%d)" % command["timeout"] if "bg_id" in command: - out += ", bg_id "%d"" % command["bg_id"] + out += ", bg_id (%d)" % command["bg_id"] return out
class CommandException(Exception): diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py index 7161fd7..b0480e4 100644 --- a/NetTest/NetTestController.py +++ b/NetTest/NetTestController.py @@ -1,5 +1,5 @@ """ -This module defines NetConfigController class which does the controlling +This module defines NetTestController class which does the controlling part of network testing.
Copyright 2011 Red Hat, Inc. @@ -23,13 +23,15 @@ from NetTestCommand import NetTestCommand, str_command from Common.LoggingServer import LoggingServer
class NetTestController: - def __init__(self, recipe_path, remoteexec=False, cleanup=False): + def __init__(self, recipe_path, remoteexec=False, cleanup=False, + res_serializer=None): ntparse = NetTestParse(recipe_path) ntparse.parse_recipe() self._recipe = ntparse.get_recipe() self._ntparse = ntparse self._remoteexec = remoteexec self._docleanup = cleanup + self._res_serializer = res_serializer
def _get_machineinfo(self, machine_id): return self._recipe["machines"][machine_id]["info"] @@ -162,6 +164,8 @@ class NetTestController: for command in sequence: logging.info("Executing command: [%s]" % str_command(command)) cmd_res = self._run_command(command) + if self._res_serializer: + self._res_serializer.add_cmd_result(command, cmd_res) logging.debug("Result: %s" % str(cmd_res)) if "res_data" in cmd_res: res_data = pformat(cmd_res["res_data"]) diff --git a/NetTest/NetTestResultSerializer.py b/NetTest/NetTestResultSerializer.py new file mode 100644 index 0000000..c5e7d1a --- /dev/null +++ b/NetTest/NetTestResultSerializer.py @@ -0,0 +1,75 @@ +""" +This module defines NetTestResultSerializer class which serves for serializing +results of command sequence to XML + +Copyright 2011 Red Hat, Inc. +Licensed under the GNU General Public License, version 2 as +published by the Free Software Foundation; see COPYING for details. +""" + +__author__ = """ +jpirko@redhat.com (Jiri Pirko) +""" + +from NetTestCommand import str_command +from xml.dom.minidom import getDOMImplementation + +def serialize_obj(obj, dom, el, upper_name="unnamed"): + if isinstance(obj, dict): + for key in obj: + new_el = dom.createElement(key) + el.appendChild(new_el) + serialize_obj(obj[key], dom, new_el, upper_name=key) + elif isinstance(obj, list): + for one in obj: + new_el = dom.createElement("%s_item" % upper_name) + el.appendChild(new_el) + serialize_obj(one, dom, new_el) + else: + text = dom.createTextNode(str(obj)) + el.appendChild(text) + +class NetTestResultSerializer: + def __init__(self): + impl = getDOMImplementation() + self._dom = impl.createDocument(None, "results", None) + self._top_el = self._dom.documentElement + self._cur_recipe_el = None + + def __str__(self): + return self._dom.toprettyxml() + + def add_recipe(self, name): + recipe_el = self._dom.createElement("recipe") + recipe_el.setAttribute("name", name) + self._top_el.appendChild(recipe_el) + self._cur_recipe_el = recipe_el + + def add_cmd_result(self, command, cmd_res): + command_el = self._dom.createElement("command") + self._cur_recipe_el.appendChild(command_el) + + for key in command: + if key == "options": + continue + command_el.setAttribute(key, str(command[key])) + + result_el = self._dom.createElement("result") + command_el.appendChild(result_el) + + if cmd_res["passed"]: + res = "PASS" + else: + res = "FAIL" + result_el.setAttribute("result", res) + + if "err_msg" in cmd_res: + err_el = self._dom.createElement("error_message") + err_text = self._dom.createTextNode(cmd_res["err_msg"]) + err_el.appendChild(err_text) + result_el.appendChild(err_el) + + if "res_data" in cmd_res: + res_data_el = self._dom.createElement("result_data") + serialize_obj(cmd_res["res_data"], self._dom, res_data_el) + command_el.appendChild(res_data_el) diff --git a/nettestctl.py b/nettestctl.py index 1d49f37..614f2fc 100755 --- a/nettestctl.py +++ b/nettestctl.py @@ -17,6 +17,7 @@ import logging import os import re from NetTest.NetTestController import NetTestController +from NetTest.NetTestResultSerializer import NetTestResultSerializer from Common.Logs import Logs from Common.LoggingServer import LoggingServer import Common.ProcessManager @@ -37,11 +38,13 @@ def usage(): " application on slaves" print " -c, --cleanup perform config cleanup\n" \ " machines" + print " -x, --result=FILE file to write xml_result" sys.exit()
-def process_recipe(args, file_path, remoteexec, cleanup): +def process_recipe(args, file_path, remoteexec, cleanup, res_serializer): nettestctl = NetTestController(os.path.realpath(file_path), - remoteexec=remoteexec, cleanup=cleanup) + remoteexec=remoteexec, cleanup=cleanup, + res_serializer=res_serializer) action = args[0] if action == "run": return nettestctl.run_recipe() @@ -70,11 +73,12 @@ def print_summary(summary): logging.info("*%s* %s" % (res, recipe_file)) logging.info("=====================================================")
-def get_recipe_result(args, file_path, remoteexec, cleanup): +def get_recipe_result(args, file_path, remoteexec, cleanup, res_serializer): + res_serializer.add_recipe(file_path) Logs.set_logging_root_path(file_path) loggingServer = LoggingServer(LoggingServer.DEFAULT_PORT, Logs.root_path, Logs.debug) loggingServer.start() - res = process_recipe(args, file_path, remoteexec, cleanup) + res = process_recipe(args, file_path, remoteexec, cleanup, res_serializer) loggingServer.stop() return ((file_path, res))
@@ -85,8 +89,8 @@ def main(): try: opts, args = getopt.getopt( sys.argv[1:], - "dhr:ec", - ["debug", "help", "recipe=", "remoteexec", "cleanup"] + "dhr:ecx:", + ["debug", "help", "recipe=", "remoteexec", "cleanup", "result"] ) except getopt.GetoptError, err: print str(err) @@ -97,6 +101,7 @@ def main(): recipe_path = None remoteexec = False cleanup = False + result_path = None for opt, arg in opts: if opt in ("-d", "--debug"): debug += 1 @@ -108,6 +113,8 @@ def main(): remoteexec = True elif opt in ("-c", "--cleanup"): cleanup = True + elif opt in ("-x", "--result"): + result_path = arg
Logs(debug)
@@ -121,6 +128,7 @@ def main():
summary = []
+ res_serializer = NetTestResultSerializer() if os.path.isdir(recipe_path): all_files = [] for root, dirs, files in os.walk(recipe_path): @@ -133,13 +141,20 @@ def main(): if re.match(r'^.*.xml$', recipe_file): logging.info("Processing recipe file "%s"" % recipe_file) summary.append(get_recipe_result(args, recipe_file, - remoteexec, cleanup)) + remoteexec, cleanup, + res_serializer)) else: summary.append(get_recipe_result(args, recipe_path, - remoteexec, cleanup)) + remoteexec, cleanup, res_serializer)) Logs.set_logging_root_path(clean=False)
print_summary(summary)
+ if result_path: + result_path = os.path.expanduser(result_path) + handle = open(result_path, "w") + handle.write(str(res_serializer)) + handle.close() + if __name__ == "__main__": main()
lnst-developers@lists.fedorahosted.org