[lnst] introduce command context
by Jiří Pírko
commit 7eac2854b2bfd504a99a4f0cdcefd41c52fe73c4
Author: Jiri Pirko <jiri(a)resnulli.us>
Date: Tue Sep 11 17:02:26 2012 +0200
introduce command context
In this context, remember all background running commands. Kill them on
cleanup.
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
NetTest/NetTestCommand.py | 172 ++++++++++++++++++++++++-----------------
NetTest/NetTestController.py | 7 +-
NetTest/NetTestSlave.py | 18 +++--
3 files changed, 117 insertions(+), 80 deletions(-)
---
diff --git a/NetTest/NetTestCommand.py b/NetTest/NetTestCommand.py
index e89f606..4fde1ee 100644
--- a/NetTest/NetTestCommand.py
+++ b/NetTest/NetTestCommand.py
@@ -37,42 +37,90 @@ class CommandException(Exception):
def __str__(self):
return "CommandException: " + str(self.command)
-class BgProcessException(Exception):
- """Base class for client errors."""
+class BgCommandException(Exception):
+ """Base class for background command errors."""
def __init__(self, str):
self._str = str
def __str__(self):
- return "BgProcessError: " + self._str
-
-class BGProcesses:
- def __init__(self):
- self._dict = {}
-
- def add(self, bg_id, pid, pipe):
- if bg_id in self._dict:
- raise Exception
- self._dict[bg_id] = {"pid": pid, "pipe": pipe}
+ return "BgCommandError: " + self._str
- def get_pid(self, bg_id):
- return self._dict[bg_id]["pid"]
+class BgCommand:
+ def __init__(self, bg_id, cmd_cls):
+ self._bg_id = bg_id
+ self._cmd_cls = cmd_cls
+ self._pid = None
+ self._read_pipe = None
- def get_pipe(self, bg_id):
- return self._dict[bg_id]["pipe"]
+ def get_bg_id(self):
+ return self._bg_id
- def remove(self, bg_id):
- del self._dict[bg_id]
+ def run(self):
+ read_pipe, write_pipe = os.pipe()
+ self._pid = os.fork()
+ if self._pid:
+ os.close(write_pipe)
+ logging.debug("Running in background with"
+ " id \"%s\", pid \"%d\"" % (self._bg_id, self._pid))
+ self._read_pipe = read_pipe
+ return {"passed": True}
+ os.close(read_pipe)
+ os.setpgrp()
+ self._cmd_cls.set_handle_intr()
+ try:
+ self._cmd_cls.run()
+ result = self._cmd_cls.get_result()
+ except KeyboardInterrupt:
+ result = self._cmd_cls.get_result()
+ except:
+ type, value, tb = sys.exc_info()
+ result = {"Exception": ''.join(traceback.format_exception(type, value, tb))}
+ tmp = pickle.dumps(result)
+ os.write(write_pipe, tmp)
+ os.close(write_pipe)
+ os._exit(0)
+
+ def wait_for(self):
+ logging.debug("Waiting for background command with id \"%s\", pid \"%d\"" % (self._bg_id, self._pid))
+ os.waitpid(self._pid, 0)
+
+ def interrupt(self):
+ logging.debug("Interrupting background command with id \"%s\", pid \"%d\"" % (self._bg_id, self._pid))
+ os.killpg(os.getpgid(self._pid), signal.SIGINT)
+ os.waitpid(self._pid, 0)
+
+ def kill(self):
+ logging.debug("Killing background command with id \"%s\", pid \"%d\"" % (self._bg_id, self._pid))
+ os.killpg(os.getpgid(self._pid), signal.SIGKILL)
- def get_bg_process_result(self, bg_id):
- pipe = self.get_pipe(bg_id)
- tmp = os.read(pipe, 4096*10)
+ def get_result(self):
+ tmp = os.read(self._read_pipe, 4096*10)
result = pickle.loads(tmp)
if "Exception" in result:
- raise BgProcessException(result["Exception"])
- os.close(pipe)
+ raise BgCommandException(result["Exception"])
+ os.close(self._read_pipe)
return result
-bg_processes = BGProcesses()
+class NetTestCommandContext:
+ def __init__(self):
+ self._dict = {}
+
+ def add_bg_cmd(self, bg_cmd):
+ self._dict[bg_cmd.get_bg_id()] = bg_cmd
+
+ def del_bg_cmd(self, bg_cmd):
+ del self._dict[bg_cmd.get_bg_id()]
+
+ def get_bg_cmd(self, bg_id):
+ return self._dict[bg_id]
+
+ def _kill_all_bg_cmds(self):
+ for bg_id in self._dict:
+ self._dict[bg_id].kill()
+
+ def cleanup(self):
+ self._kill_all_bg_cmds()
+ self._dict = {}
def NetTestCommandTest(command):
test_name = command["value"]
@@ -174,48 +222,49 @@ class NetTestCommandSystemConfig(NetTestCommandGeneric):
res["res_data"] = res_data
self.set_result(res)
-class NetTestCommandWait(NetTestCommandGeneric):
+class NetTestCommandControl(NetTestCommandGeneric):
+ def __init__(self, command_context, command):
+ self._command_context = command_context
+ NetTestCommandGeneric.__init__(self, command)
+
+class NetTestCommandWait(NetTestCommandControl):
def run(self):
bg_id = self._command["value"]
- pid = bg_processes.get_pid(bg_id)
- logging.debug("Waiting for background id \"%s\", pid \"%d\"" % (bg_id, pid))
- os.waitpid(pid, 0)
- result = bg_processes.get_bg_process_result(bg_id)
- bg_processes.remove(bg_id)
+ bg_cmd = self._command_context.get_bg_cmd(bg_id)
+ bg_cmd.wait_for()
+ result = bg_cmd.get_result()
+ self._command_context.del_bg_cmd(bg_cmd)
self.set_result(result)
-class NetTestCommandIntr(NetTestCommandGeneric):
+class NetTestCommandIntr(NetTestCommandControl):
def run(self):
bg_id = self._command["value"]
- pid = bg_processes.get_pid(bg_id)
- logging.debug("Interrupting background id \"%s\", pid \"%d\"" % (bg_id, pid))
- os.killpg(os.getpgid(pid), signal.SIGINT)
- os.waitpid(pid, 0)
- result = bg_processes.get_bg_process_result(bg_id)
- bg_processes.remove(bg_id)
+ bg_cmd = self._command_context.get_bg_cmd(bg_id)
+ bg_cmd.interrupt()
+ result = bg_cmd.get_result()
+ self._command_context.del_bg_cmd(bg_cmd)
self.set_result(result)
-class NetTestCommandKill(NetTestCommandGeneric):
+class NetTestCommandKill(NetTestCommandControl):
def run(self):
bg_id = self._command["value"]
- pid = bg_processes.get_pid(bg_id)
- logging.debug("Killing background id \"%s\", pid \"%d\"" % (bg_id, pid))
- os.killpg(os.getpgid(pid), signal.SIGKILL)
- bg_processes.remove(bg_id)
+ bg_cmd = self._command_context.get_bg_cmd(bg_id)
+ bg_cmd.kill()
+ self._command_context.del_bg_cmd(bg_cmd)
self.set_result({"passed": True})
-def get_command_class(command):
+def get_command_class(command_context, command):
cmd_type = command["type"]
if cmd_type == "exec":
return NetTestCommandExec(command)
elif cmd_type == "test":
return NetTestCommandTest(command)
elif cmd_type == "wait":
- return NetTestCommandWait(command)
+ return NetTestCommandWait(command_context, command)
elif cmd_type == "intr":
- return NetTestCommandIntr(command)
+ return NetTestCommandIntr(command_context, command)
elif cmd_type == "kill":
- return NetTestCommandKill(command)
+ return NetTestCommandKill(command_context, command)
elif cmd_type == "system_config":
return NetTestCommandSystemConfig(command)
else:
@@ -223,37 +272,18 @@ def get_command_class(command):
raise Exception("Unknown command type \"%s\"" % cmd_type)
class NetTestCommand:
- def __init__(self, command):
- self._command_class = get_command_class(command)
+ def __init__(self, command_context, command):
+ self._command_class = get_command_class(command_context, command)
+ self._command_context = command_context
self._command = command
def run(self):
cmd_cls = self._command_class
if "bg_id" in self._command:
bg_id = self._command["bg_id"]
- read_pipe, write_pipe = os.pipe()
- pid = os.fork()
- if pid:
- os.close(write_pipe)
- logging.debug("Running in background with"
- " id \"%s\", pid \"%d\"" % (bg_id, pid))
- bg_processes.add(bg_id, pid, read_pipe)
- return {"passed": True}
- os.close(read_pipe)
- os.setpgrp()
- cmd_cls.set_handle_intr()
- try:
- cmd_cls.run()
- result = cmd_cls.get_result()
- except KeyboardInterrupt:
- result = cmd_cls.get_result()
- except:
- type, value, tb = sys.exc_info()
- result = {"Exception": ''.join(traceback.format_exception(type, value, tb))}
- tmp = pickle.dumps(result)
- os.write(write_pipe, tmp)
- os.close(write_pipe)
- os._exit(0)
+ bg_cmd = BgCommand(bg_id, cmd_cls)
+ self._command_context.add_bg_cmd(bg_cmd)
+ return bg_cmd.run()
else:
cmd_cls.run()
return cmd_cls.get_result()
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py
index 2a6bbd6..01a5f9b 100644
--- a/NetTest/NetTestController.py
+++ b/NetTest/NetTestController.py
@@ -22,7 +22,7 @@ from NetTest.NetTestParse import NetTestParse
from Common.SlaveUtils import prepare_client_session
from Common.NetUtils import get_corespond_local_ip, MacPool
from NetTest.NetTestSlave import DefaultRPCPort
-from NetTest.NetTestCommand import NetTestCommand, str_command
+from NetTest.NetTestCommand import NetTestCommandContext, NetTestCommand, str_command
from Common.LoggingServer import LoggingServer
from Common.VirtUtils import VirtNetCtl, VirtDomainCtl, BridgeCtl
from Common.Utils import wait_for
@@ -43,7 +43,7 @@ class NetTestController:
self._docleanup = cleanup
self._res_serializer = res_serializer
self._remote_capture_files = {}
-
+ self._command_context = NetTestCommandContext()
self._machine_pool = MachinePool([])
self._recipe = {}
@@ -314,7 +314,7 @@ class NetTestController:
pass
if machine_id == "0":
- cmd_res = NetTestCommand(command).run()
+ cmd_res = NetTestCommand(self._command_context, command).run()
else:
rpc = self._get_machinerpc(machine_id)
if "timeout" in command:
@@ -390,6 +390,7 @@ class NetTestController:
self._deconfigure_slaves()
self._disconnect_slaves()
+ self._command_context.cleanup()
if not err:
return res
diff --git a/NetTest/NetTestSlave.py b/NetTest/NetTestSlave.py
index 8065591..7c391f8 100644
--- a/NetTest/NetTestSlave.py
+++ b/NetTest/NetTestSlave.py
@@ -20,7 +20,7 @@ from Common.XmlRpc import Server
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
from NetConfig.NetConfig import NetConfig
from NetConfig.NetConfigDevice import NetConfigDeviceAllCleanup
-from NetTest.NetTestCommand import NetTestCommand, CommandException
+from NetTest.NetTestCommand import NetTestCommandContext, NetTestCommand, CommandException
from Common.Utils import die_when_parent_die
from Common.NetUtils import scan_netdevs
@@ -30,10 +30,11 @@ class NetTestSlaveXMLRPC:
'''
Exported xmlrpc methods
'''
- def __init__(self):
+ def __init__(self, command_context):
self._netconfig = None
self._packet_captures = {}
self._netconfig = NetConfig()
+ self._command_context = command_context
def hello(self):
return "hello"
@@ -112,7 +113,7 @@ class NetTestSlaveXMLRPC:
def run_command(self, command):
try:
- return NetTestCommand(command).run()
+ return NetTestCommand(self._command_context, command).run()
except:
log_exc_traceback()
raise CommandException(command)
@@ -120,11 +121,13 @@ class NetTestSlaveXMLRPC:
def machine_cleanup(self):
NetConfigDeviceAllCleanup()
self._netconfig.cleanup()
+ self._command_context.cleanup()
return True
class MySimpleXMLRPCServer(Server):
- def __init__(self, *args, **kwargs):
+ def __init__(self, command_context, *args, **kwargs):
self._finished = False
+ self._command_context = command_context
Server.__init__(self, *args, **kwargs)
def register_die_signal(self, signum):
@@ -138,6 +141,7 @@ class MySimpleXMLRPCServer(Server):
while True:
try:
if self._finished:
+ self._command_context.cleanup()
import sys
sys.exit()
return
@@ -149,12 +153,14 @@ class NetTestSlave:
def __init__(self, port = DefaultRPCPort):
die_when_parent_die()
- server = MySimpleXMLRPCServer(("", port), SimpleXMLRPCRequestHandler,
+ command_context = NetTestCommandContext()
+ server = MySimpleXMLRPCServer(command_context,
+ ("", port), SimpleXMLRPCRequestHandler,
logRequests = False)
server.register_die_signal(signal.SIGHUP)
server.register_die_signal(signal.SIGINT)
server.register_die_signal(signal.SIGTERM)
- server.register_instance(NetTestSlaveXMLRPC())
+ server.register_instance(NetTestSlaveXMLRPC(command_context))
self._server = server
def run(self):
11 years, 6 months
[lnst] normalize path and allow ".."
by Jiří Pírko
commit 3c6236ce368cb6a331704bfd368c98e674c155ce
Author: Jiri Pirko <jiri(a)resnulli.us>
Date: Mon Sep 10 13:22:08 2012 +0200
normalize path and allow ".."
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
Common/XmlProcessing.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/Common/XmlProcessing.py b/Common/XmlProcessing.py
index 8d92e83..5aa7ccd 100644
--- a/Common/XmlProcessing.py
+++ b/Common/XmlProcessing.py
@@ -363,4 +363,4 @@ class RecipeParser(XmlParser):
raise XmlProcessingError(str(err), node)
def _get_referenced_xml_path(self, filename):
- return os.path.join(self._include_root, os.path.expanduser(filename))
+ return os.path.normpath(os.path.join(self._include_root, os.path.expanduser(filename)))
11 years, 6 months
[PATCH 1/8] nettestctl: Integration of config module
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
nettestctl now reads the users configuration file ~/.lnst/lnst.conf
As we agreed, the loaded configs will be distributed as function
parameters, therefore I made the necessary changes to functions
process_recipe and get_recipe_result.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
Common/Config.py | 5 -----
nettestctl.py | 16 +++++++++++-----
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/Common/Config.py b/Common/Config.py
index 8a1ad56..8ef2452 100644
--- a/Common/Config.py
+++ b/Common/Config.py
@@ -24,12 +24,7 @@ class Config():
def __init__(self):
self._parser = ConfigParser(dict_type=dict)
-
- # defaults.conf should contain all possible sections and options
- # sections and options not listed there will be undefined which
- # can cause problems
self.options = dict()
- self.load_config("default.conf")
def get_config(self):
return self.options
diff --git a/nettestctl.py b/nettestctl.py
index de07911..2fab067 100755
--- a/nettestctl.py
+++ b/nettestctl.py
@@ -21,6 +21,7 @@ from NetTest.NetTestResultSerializer import NetTestResultSerializer
from Common.Logs import Logs
from Common.LoggingServer import LoggingServer
import Common.ProcessManager
+from Common.Config import Config
def usage():
"""
@@ -45,7 +46,7 @@ def usage():
sys.exit()
def process_recipe(action, file_path, remoteexec, cleanup,
- res_serializer, packet_capture):
+ res_serializer, packet_capture, config):
nettestctl = NetTestController(os.path.realpath(file_path),
remoteexec=remoteexec, cleanup=cleanup,
res_serializer=res_serializer)
@@ -70,14 +71,14 @@ def print_summary(summary):
logging.info("=====================================================")
def get_recipe_result(args, file_path, remoteexec, cleanup,
- res_serializer, packet_capture):
+ res_serializer, packet_capture, config):
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_serializer, packet_capture)
+ res_serializer, packet_capture, config)
loggingServer.stop()
return ((file_path, res))
@@ -97,6 +98,9 @@ def main():
usage()
sys.exit()
+ config = Config()
+ config.load_config('~/.lnst/lnst.conf')
+
debug = 0
recipe_path = None
remoteexec = False
@@ -144,12 +148,14 @@ def main():
summary.append(get_recipe_result(action, recipe_file,
remoteexec, cleanup,
res_serializer,
- packet_capture))
+ packet_capture,
+ config))
Logs.set_logging_root_path(clean=False)
else:
summary.append(get_recipe_result(action, recipe_path, remoteexec,
cleanup, res_serializer,
- packet_capture))
+ packet_capture,
+ config))
Logs.set_logging_root_path(clean=False)
--
1.7.11.4
11 years, 6 months
[lnst] Fix forgotten rename of target_bridge to libvirt_bridge
by Jiří Pírko
commit 49b77a1a0cf47436a00650f319f65f44f001acfa
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Fri Sep 7 17:27:10 2012 +0200
Fix forgotten rename of target_bridge to libvirt_bridge
It was suggested that option 'target_bridge' should be renamed to
'libvirt_bridge'[1]. In following two lines the change was not made
resulting in ignoring user supplied bridge device.
[1] https://lists.fedorahosted.org/pipermail/lnst-developers/2012-August/0002...
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
NetTest/NetTestController.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
---
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py
index b028e35..2a6bbd6 100644
--- a/NetTest/NetTestController.py
+++ b/NetTest/NetTestController.py
@@ -122,8 +122,8 @@ class NetTestController:
if not len(query_result):
break
- if "target_bridge" in dev:
- brctl = BridgeCtl(dev["target_bridge"])
+ if "libvirt_bridge" in dev:
+ brctl = BridgeCtl(dev["libvirt_bridge"])
else:
if "default_bridge" in dev_net:
brctl = dev_net["default_bridge"]
11 years, 6 months
[lnst] TestIperf: fix scope of the rate variable
by Jiří Pírko
commit 90dd466730bf2a1708eaa3b9680361ea5ec244cd
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Fri Sep 7 16:55:51 2012 +0200
TestIperf: fix scope of the rate variable
Made a mistake in my previous patch and forgot to check the scope of the
rate variable. Without the fix in case of test pass the rate variable is
not assigned resulting in test crash. With the fix all is working fine.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
Tests/TestIperf.py | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
---
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index e926acb..7cb6663 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -94,14 +94,14 @@ class TestIperf(TestGeneric):
logging.info("Iperf connection failed!")
return (False, "Iperf connection failed!")
+ m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\s*\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
+ if m is None:
+ logging.info("Could not get performance throughput!")
+ return (False, "Could not get performance throughput!")
+
+ rate = m.group(2)
if self.threshold is not None:
# check if expected threshold is reached
- m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\s*\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
- if m is None:
- logging.info("Could not get performance throughput!")
- return (False, "Could not get performance throughput!")
-
- rate = m.group(2)
result = self._rate_over_threshold(rate)
if result:
return (True, "Measured rate (%s) is over threshold (%s)." %
11 years, 6 months
[PATCH] TestIperf: fix scope of the rate variable
by Jan Tluka
Made a mistake in my previous patch and forgot to check the scope of the
rate variable. Without the fix in case of test pass the rate variable is
not assigned resulting in test crash. With the fix all is working fine.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
Tests/TestIperf.py | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index e926acb..7cb6663 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -94,14 +94,14 @@ class TestIperf(TestGeneric):
logging.info("Iperf connection failed!")
return (False, "Iperf connection failed!")
+ m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\s*\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
+ if m is None:
+ logging.info("Could not get performance throughput!")
+ return (False, "Could not get performance throughput!")
+
+ rate = m.group(2)
if self.threshold is not None:
# check if expected threshold is reached
- m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\s*\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
- if m is None:
- logging.info("Could not get performance throughput!")
- return (False, "Could not get performance throughput!")
-
- rate = m.group(2)
result = self._rate_over_threshold(rate)
if result:
return (True, "Measured rate (%s) is over threshold (%s)." %
--
1.7.7.6
11 years, 6 months
[lnst] Sanitizing Iperf test results.
by Jiří Pírko
commit f861c054f63a51a8b2565afc6e6fc2f5035ccb2f
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Wed Sep 5 15:06:43 2012 +0200
Sanitizing Iperf test results.
TestIperf will now report if it:
* passed (measured rate will be logged)
* passed and over defined threshold
* failed because threshold was not reached
* failed because of connection failed
All the information is written into info log so there's no need to check
sequence logs.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
Tests/TestIperf.py | 26 +++++++++++++++++++++-----
1 files changed, 21 insertions(+), 5 deletions(-)
---
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index f6ba232..e926acb 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -89,15 +89,28 @@ class TestIperf(TestGeneric):
client.kill()
output = client.read_nonblocking()
+
+ if re.search("connect failed:", output):
+ logging.info("Iperf connection failed!")
+ return (False, "Iperf connection failed!")
+
if self.threshold is not None:
# check if expected threshold is reached
m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\s*\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
if m is None:
logging.info("Could not get performance throughput!")
- return False
+ return (False, "Could not get performance throughput!")
rate = m.group(2)
- return self._rate_over_threshold(rate)
+ result = self._rate_over_threshold(rate)
+ if result:
+ return (True, "Measured rate (%s) is over threshold (%s)." %
+ (rate, self.threshold))
+ else:
+ return (False, "Measured rate (%s) is below threshold (%s)!" %
+ (rate, self.threshold))
+ else:
+ return True, "Measured rate: %s" % rate
def run_server(self, cmd):
server = ShellProcess(cmd)
@@ -144,10 +157,13 @@ class TestIperf(TestGeneric):
if role == "server":
logging.debug("running as server ...")
self.run_server(cmd)
+
+ return self.set_pass()
elif role == "client":
logging.debug("running as client ...")
- rv = self.run_client(cmd)
+ (rv, message) = self.run_client(cmd)
if rv == False:
- return self.set_fail("iperf test failed, measured rate is below expected threshold")
+ return self.set_fail(message)
+
+ return self.set_pass(message)
- return self.set_pass()
11 years, 6 months
[PATCH 1/7] nettestctl: Integration of config module
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
nettestctl now reads the default.conf file. I postponed adding other
config files for later when we have agreed on which ones we really want.
As we agreed, the loaded configs will be distributed as function
parameters, therefore I made the necessary changes to functions
process_recipe and get_recipe_result.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
Common/Config.py | 5 -----
nettestctl.py | 20 +++++++++++++++-----
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/Common/Config.py b/Common/Config.py
index 8a1ad56..8ef2452 100644
--- a/Common/Config.py
+++ b/Common/Config.py
@@ -24,12 +24,7 @@ class Config():
def __init__(self):
self._parser = ConfigParser(dict_type=dict)
-
- # defaults.conf should contain all possible sections and options
- # sections and options not listed there will be undefined which
- # can cause problems
self.options = dict()
- self.load_config("default.conf")
def get_config(self):
return self.options
diff --git a/nettestctl.py b/nettestctl.py
index de07911..21fdefc 100755
--- a/nettestctl.py
+++ b/nettestctl.py
@@ -21,6 +21,7 @@ from NetTest.NetTestResultSerializer import NetTestResultSerializer
from Common.Logs import Logs
from Common.LoggingServer import LoggingServer
import Common.ProcessManager
+from Common.Config import Config
def usage():
"""
@@ -45,7 +46,7 @@ def usage():
sys.exit()
def process_recipe(action, file_path, remoteexec, cleanup,
- res_serializer, packet_capture):
+ res_serializer, packet_capture, config):
nettestctl = NetTestController(os.path.realpath(file_path),
remoteexec=remoteexec, cleanup=cleanup,
res_serializer=res_serializer)
@@ -70,14 +71,14 @@ def print_summary(summary):
logging.info("=====================================================")
def get_recipe_result(args, file_path, remoteexec, cleanup,
- res_serializer, packet_capture):
+ res_serializer, packet_capture, config):
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_serializer, packet_capture)
+ res_serializer, packet_capture, config)
loggingServer.stop()
return ((file_path, res))
@@ -97,6 +98,13 @@ def main():
usage()
sys.exit()
+ # defaults.conf should contain all possible sections and options
+ # sections and options not listed there will be undefined which
+ # can cause problems
+ config = Config()
+ default_cfg = os.path.join(os.path.dirname(sys.argv[0]), 'default.conf')
+ config.load_config(default_cfg)
+
debug = 0
recipe_path = None
remoteexec = False
@@ -144,12 +152,14 @@ def main():
summary.append(get_recipe_result(action, recipe_file,
remoteexec, cleanup,
res_serializer,
- packet_capture))
+ packet_capture,
+ config))
Logs.set_logging_root_path(clean=False)
else:
summary.append(get_recipe_result(action, recipe_path, remoteexec,
cleanup, res_serializer,
- packet_capture))
+ packet_capture,
+ config))
Logs.set_logging_root_path(clean=False)
--
1.7.11.4
11 years, 6 months
[PATCH] Sanitizing Iperf test results.
by Jan Tluka
TestIperf will now report if it:
* passed (measured rate will be logged)
* passed and over defined threshold
* failed because threshold was not reached
* failed because of connection failed
All the information is written into info log so there's no need to check
sequence logs.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
Tests/TestIperf.py | 26 +++++++++++++++++++++-----
1 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index f6ba232..e926acb 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -89,15 +89,28 @@ class TestIperf(TestGeneric):
client.kill()
output = client.read_nonblocking()
+
+ if re.search("connect failed:", output):
+ logging.info("Iperf connection failed!")
+ return (False, "Iperf connection failed!")
+
if self.threshold is not None:
# check if expected threshold is reached
m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\s*\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
if m is None:
logging.info("Could not get performance throughput!")
- return False
+ return (False, "Could not get performance throughput!")
rate = m.group(2)
- return self._rate_over_threshold(rate)
+ result = self._rate_over_threshold(rate)
+ if result:
+ return (True, "Measured rate (%s) is over threshold (%s)." %
+ (rate, self.threshold))
+ else:
+ return (False, "Measured rate (%s) is below threshold (%s)!" %
+ (rate, self.threshold))
+ else:
+ return True, "Measured rate: %s" % rate
def run_server(self, cmd):
server = ShellProcess(cmd)
@@ -144,10 +157,13 @@ class TestIperf(TestGeneric):
if role == "server":
logging.debug("running as server ...")
self.run_server(cmd)
+
+ return self.set_pass()
elif role == "client":
logging.debug("running as client ...")
- rv = self.run_client(cmd)
+ (rv, message) = self.run_client(cmd)
if rv == False:
- return self.set_fail("iperf test failed, measured rate is below expected threshold")
+ return self.set_fail(message)
+
+ return self.set_pass(message)
- return self.set_pass()
--
1.7.6.5
11 years, 6 months
[lnst trac] #17: Net addresses verification
by fedora-badges
#17: Net addresses verification
-------------------------+-----------------------
Reporter: rpazdera | Owner: somebody
Type: enhancement | Status: new
Priority: minor | Milestone:
Component: component1 | Version:
Keywords: | Blocked By:
Blocking: |
-------------------------+-----------------------
We could use some functions for inet and hwaddr format validation. The
addresses are almost always user input and that should be checked.
We will also need it in the new Config parsing code.
It could be added to the NetUtils module in Common.
--
Ticket URL: <https://fedorahosted.org/lnst/ticket/17>
lnst <http://example.org/>
My example project
11 years, 6 months