commit 28f087c9ed39f0813ed9ef0e6e2783b9bb14da98
Author: Jiri Pirko <jpirko(a)redhat.com>
Date: Thu Jun 30 14:05:52 2011 +0200
NetTest: introduce result XML serialization
Signed-off-by: Jiri Pirko <jpirko(a)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(a)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()