[lnst] Do not stop command sequence execution if command failed
by Jiří Pírko
commit 980e11b2bf8f82b60a8f5e9bd371ffff46f54bd4
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Wed Jun 6 15:02:59 2012 +0200
Do not stop command sequence execution if command failed
In case of a failed sequence command (even test that did not pass) the
whole rest of the command sequence was skipped. This could result in
hanging background process that would not be optionally killed at the
end of command sequence using type="kill" command. The fix is to let
the whole command sequence continue and save any failed command for
the overall command sequence result.
NetTest/NetTestController.py | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
---
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py
index 51a401f..8f46bcb 100644
--- a/NetTest/NetTestController.py
+++ b/NetTest/NetTestController.py
@@ -176,6 +176,7 @@ class NetTestController:
return cmd_res
def _run_command_sequence(self, sequence):
+ seq_passed = True
for command in sequence:
logging.info("Executing command: [%s]" % str_command(command))
cmd_res = self._run_command(command)
@@ -189,8 +190,8 @@ class NetTestController:
logging.error("Command failed - command: [%s], "
"Error message: \"%s\""
% (str_command(command), cmd_res["err_msg"]))
- return False
- return True
+ seq_passed = False
+ return seq_passed
def dump_recipe(self):
pprint(self._recipe)
11 years, 9 months
[lnst] Fix system_config bug for non-remote_exec case
by Jiří Pírko
commit a1a3ed238f26ad6179fed81f47a9d0065fcf9986
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Wed Jun 6 14:57:43 2012 +0200
Fix system_config bug for non-remote_exec case
The system_config implementation worked only for remote_exec runs. In
case of non-remote test execution the system_config key was missing and
lead to unhandled exception. The fix is to move the system_config
initialization to netconfig initialization code.
NetConfig/NetConfigParse.py | 1 +
NetTest/NetTestController.py | 1 -
2 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/NetConfig/NetConfigParse.py b/NetConfig/NetConfigParse.py
index f94a73d..dbd7a6d 100644
--- a/NetConfig/NetConfigParse.py
+++ b/NetConfig/NetConfigParse.py
@@ -42,6 +42,7 @@ class NetConfigParse:
info["rootpass"] = rootpass
if rpcport:
info["rpcport"] = int(rpcport)
+ info["system_config"] = {}
dom_netdevs = dom_netmachine.getElementsByTagName("netdevice")
netdevs = {}
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py
index 12a871d..51a401f 100644
--- a/NetTest/NetTestController.py
+++ b/NetTest/NetTestController.py
@@ -58,7 +58,6 @@ class NetTestController:
"nettestslave.py")
session.add_kill_handler(self._session_die)
info["session"] = session
- info["system_config"] = {}
def _cleanup_slaves(self):
for machine_id in self._recipe["machines"]:
11 years, 9 months
[lnst] Iperf test option threshold added
by Jiří Pírko
commit fdaec39c2980cfdef593e87ac38ac291c9eae94d
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Wed Jun 6 14:53:40 2012 +0200
Iperf test option threshold added
The new 'threshold' option for TestIperf lets user configure an expected
transfer rate that has to be met to make the test pass. Works for single
threaded unidirectional test only.
The format of the option value string is anything similar to the following:
<option name="threshold" value="1000 bits/sec" />
<option name="threshold" value="5.5 kbits/sec" />
<option name="threshold" value="600 Mbits/sec" />
<option name="threshold" value="6.5 Gbits/sec" />
Tests/TestIperf.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 65 insertions(+), 2 deletions(-)
---
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index 07aaa98..cfea973 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -12,6 +12,7 @@ from Common.ExecCmd import exec_cmd
from Common.ShellProcess import ShellProcess
import time
import errno
+import re
class TestIperf(TestGeneric):
def _install_iperf(self):
@@ -36,6 +37,54 @@ class TestIperf(TestGeneric):
return cmd
+ def _rate_over_threshold(self, rate):
+ # convert rate to the same unit as threshold unit
+ pattern = "(\d*(\.\d*){0,1})\s*([ kMGT])bits\/sec"
+
+ # parse threshold value
+ r1 = re.match(pattern, self.threshold)
+ thr_units = r1.group(3)
+
+ # parse measured rate value
+ r2 = re.match(pattern, rate)
+ rate_units = r2.group(3)
+
+ if r1.group(2) != None:
+ thr_val = float(r1.group(1) + r1.group(2))
+ else:
+ thr_val = float(r1.group(1))
+
+ if r2.group(2) != None:
+ rate_val = float(r2.group(1) + r2.group(2))
+ else:
+ rate_val = float(r2.group(1))
+
+ # do the conversion of rate units
+ if thr_units != rate_units:
+ # remove any k,M,G,T from measured rate
+ if rate_units == 'k':
+ rate_val *= 1000
+ elif rate_units == 'M':
+ rate_val *= 1000*1000
+ elif rate_val == 'G':
+ rate_val *= 1000*1000*1000
+
+ # divide by k or M or G if present
+ if thr_units == 'k':
+ rate_val /= 1000
+ elif thr_units == 'M':
+ rate_val /= 1000*1000
+ elif thr_units == 'G':
+ rate_val /= 1000*1000*1000
+
+ if rate_val < thr_val:
+ logging.info("measured rate is below threshold! " \
+ "(measured: %s < threshold: %s)" % \
+ (rate, self.threshold))
+ return False
+
+ return True
+
def run_client(self, cmd):
client = ShellProcess(cmd)
try:
@@ -44,7 +93,17 @@ class TestIperf(TestGeneric):
# we got interrupted, let's gather data
if e.errno == errno.EINTR:
client.kill()
- client.read_nonblocking()
+
+ output = client.read_nonblocking()
+ if self.threshold is not None:
+ # check if expected threshold is reached
+ m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\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
+
+ rate = m.group(2)
+ return self._rate_over_threshold(rate)
def run_server(self, cmd):
server = ShellProcess(cmd)
@@ -82,6 +141,8 @@ class TestIperf(TestGeneric):
else:
self._temp_dir = installed
+ self.threshold = self.get_opt("threshold")
+
role = self.get_mopt("role")
cmd = self._compose_iperf_cmd(role)
logging.debug("compiled command: %s" % cmd)
@@ -91,6 +152,8 @@ class TestIperf(TestGeneric):
self.run_server(cmd)
elif role == "client":
logging.debug("running as client ...")
- self.run_client(cmd)
+ rv = self.run_client(cmd)
+ if rv == False:
+ return self.set_fail("iperf test failed, measured rate is below expected threshold")
return self.set_pass()
11 years, 9 months
[lnst] Interrupt exception handler in Iperf test
by Jiří Pírko
commit efcfd32f0be5fd6ad84b2ddfcec1f789021c5eec
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Fri Jun 1 16:29:32 2012 +0200
Interrupt exception handler in Iperf test
If TestIperf is interrupted with kill/intr signal it does not collect
the ShellProcess data. I added signal handler for both client and server
part so that in case of receiving interrupt exception the iperf process'
statistics output will be collected and available for inspection at end
of testing.
Tests/TestIperf.py | 16 ++++++++++++++--
1 files changed, 14 insertions(+), 2 deletions(-)
---
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index c65ed2d..07aaa98 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -11,6 +11,7 @@ from Common.TestsCommon import TestGeneric
from Common.ExecCmd import exec_cmd
from Common.ShellProcess import ShellProcess
import time
+import errno
class TestIperf(TestGeneric):
def _install_iperf(self):
@@ -37,7 +38,12 @@ class TestIperf(TestGeneric):
def run_client(self, cmd):
client = ShellProcess(cmd)
- client.wait()
+ try:
+ client.wait()
+ except OSError as e:
+ # we got interrupted, let's gather data
+ if e.errno == errno.EINTR:
+ client.kill()
client.read_nonblocking()
def run_server(self, cmd):
@@ -48,7 +54,13 @@ class TestIperf(TestGeneric):
server.read_nonblocking()
server.kill()
else:
- server.wait()
+ try:
+ server.wait()
+ except OSError as e:
+ if e.errno == errno.EINTR:
+ server.kill()
+
+ server.read_nonblocking()
def run(self):
self._keep_server_running = True
11 years, 9 months
[lnst] Let count of packets in PktgenTx test be configurable
by Jiří Pírko
commit b29daa4b577667bd1dd8e1e6fd6f225c975114a5
Author: Jan Tluka <jtluka(a)redhat.com>
Date: Fri Jun 1 16:10:21 2012 +0200
Let count of packets in PktgenTx test be configurable
This patch lets user configure the count of packets to sent by pktgen
facility. The default behaviour has not been changed.
Tests/TestPktgenTx.py | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
---
diff --git a/Tests/TestPktgenTx.py b/Tests/TestPktgenTx.py
index 5ec500f..792a991 100644
--- a/Tests/TestPktgenTx.py
+++ b/Tests/TestPktgenTx.py
@@ -58,6 +58,7 @@ class TestPktgenTx(TestGeneric):
hwaddr = self.get_mopt("hwaddr")
vlan_tci = self.get_opt("vlan_tci", default=0)
skb_clone = self.get_opt("skb_clone", default=100000)
+ count = self.get_opt("count", default=10000000)
exec_cmd("modprobe pktgen")
@@ -74,7 +75,7 @@ class TestPktgenTx(TestGeneric):
pg.set("dst_mac %s" % hwaddr)
if vlan_tci:
pg.set("vlan_id %d" % vlan_tci)
- pg.set("count 10000000")
+ pg.set("count %d" % count)
pgctl.set("start")
except ExecCmdFail:
return self.set_fail("pktgen failed")
11 years, 9 months
[PATCH] Interrupt exception handler in Iperf test
by Jan Tluka
If TestIperf is interrupted with kill/intr signal it does not collect
the ShellProcess data. I added signal handler for both client and server
part so that in case of receiving interrupt exception the iperf process'
statistics output will be collected and available for inspection at end
of testing.
---
Tests/TestIperf.py | 17 +++++++++++++++--
1 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index c65ed2d..e4fabbb 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -11,6 +11,7 @@ from Common.TestsCommon import TestGeneric
from Common.ExecCmd import exec_cmd
from Common.ShellProcess import ShellProcess
import time
+import errno
class TestIperf(TestGeneric):
def _install_iperf(self):
@@ -37,7 +38,13 @@ class TestIperf(TestGeneric):
def run_client(self, cmd):
client = ShellProcess(cmd)
- client.wait()
+ try:
+ client.wait()
+ except OSError as e:
+ # we got interrupted, let's gather data
+ if e.errno == errno.EINTR:
+ client.kill()
+
client.read_nonblocking()
def run_server(self, cmd):
@@ -48,7 +55,13 @@ class TestIperf(TestGeneric):
server.read_nonblocking()
server.kill()
else:
- server.wait()
+ try:
+ server.wait()
+ except OSError as e:
+ if e.errno == errno.EINTR:
+ server.kill()
+
+ server.read_nonblocking()
def run(self):
self._keep_server_running = True
--
1.7.6.5
11 years, 9 months
[PATCH] Parsing error fix for short test times
by Jan Tluka
Minor fix for the iperf output parsing.
Case 1:
[ 5] 0.0-10.0 sec 5.21 GBytes 4.47 Gbits/sec
Case 2:
[ 5] 0.0- 5.0 sec 3.52 GBytes 6.04 Gbits/sec
In case #2 the space after dash was not expected and resulted in
parsing error. The fix corrects this and handles both cases.
---
Tests/TestIperf.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index 9b67d40..f6ba232 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -91,7 +91,7 @@ class TestIperf(TestGeneric):
output = client.read_nonblocking()
if self.threshold is not None:
# check if expected threshold is reached
- m = re.search("\[[^0-9]*[0-9]*\]\s*0.0-\d*\.\d sec\s*\d*(\.\d*){0,1}\s*[ kGMT]Bytes\s*(\d*(\.\d*){0,1}\s*[ kGMT]bits\/sec)", output)
+ 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
--
1.7.6.5
11 years, 9 months
[PATCH] Fix the wrong parsing of throughput value
by Jan Tluka
---
Tests/TestIperf.py | 10 ++--------
1 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/Tests/TestIperf.py b/Tests/TestIperf.py
index cfea973..9b67d40 100644
--- a/Tests/TestIperf.py
+++ b/Tests/TestIperf.py
@@ -49,15 +49,9 @@ class TestIperf(TestGeneric):
r2 = re.match(pattern, rate)
rate_units = r2.group(3)
- if r1.group(2) != None:
- thr_val = float(r1.group(1) + r1.group(2))
- else:
- thr_val = float(r1.group(1))
+ thr_val = float(r1.group(1))
- if r2.group(2) != None:
- rate_val = float(r2.group(1) + r2.group(2))
- else:
- rate_val = float(r2.group(1))
+ rate_val = float(r2.group(1))
# do the conversion of rate units
if thr_units != rate_units:
--
1.7.6.5
11 years, 9 months
[PATCH] XmlPreprocessor: Modify template detection
by Radek Pazdera
From: Radek Pazdera <rpazdera(a)redhat.com>
The previous solution considered curly braces to be reserved
characters, exclusively for marking templates. But according
to recent development, it will be necessary to deal with
those characters also in non-template context.
This commit enhances template detection code so it will ignore
any occurencies of curly braces unless they form a valid template.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
Common/XmlPreprocessor.py | 37 ++++++++++++++-----------------------
1 files changed, 14 insertions(+), 23 deletions(-)
diff --git a/Common/XmlPreprocessor.py b/Common/XmlPreprocessor.py
index 88ae758..21ce86e 100644
--- a/Common/XmlPreprocessor.py
+++ b/Common/XmlPreprocessor.py
@@ -31,9 +31,8 @@ class XmlPreprocessor:
This class serves as template processor within a XML DOM tree object.
"""
- _template_re = "\{([^\{\}]+)\}"
- _alias_re = "^\$([a-zA-Z0-9_]+)(\[.+\])*$"
- _func_re = "^([a-zA-Z0-9_]+)\(([^\(\)]*)\)$"
+ _alias_re = "\{\$([a-zA-Z0-9_]+)(\[.+\])*\}"
+ _func_re = "\{([a-zA-Z0-9_]+)\(([^\(\)]*)\)\}"
def __init__(self):
self._definitions = {}
@@ -82,31 +81,23 @@ class XmlPreprocessor:
def _expand_string(self, string):
while True:
- template_match = re.search(self._template_re, string)
- if template_match:
- template_string = template_match.group(0)
- template = template_match.group(1)
- template_result = self._process_template(template)
+ alias_match = re.search(self._alias_re, string)
+ func_match = re.search(self._func_re, string)
- string = string.replace(template_string, template_result)
+ result = None
+
+ if alias_match:
+ template = alias_match.group(0)
+ result = self._process_alias_template(template)
+ elif func_match:
+ template = func_match.group(0)
+ result = self._process_func_template(template)
else:
break
- return string
-
- def _process_template(self, string):
- string = string.strip()
- result = None
+ string = string.replace(template, result)
- if re.match(self._alias_re, string):
- result = self._process_alias_template(string)
- return result
-
- if re.match(self._func_re, string):
- result = self._process_func_template(string)
- return result
-
- raise XmlTemplateError("Unknown template type '%s'" % string)
+ return string
def _process_alias_template(self, string):
result = None
--
1.7.7.6
11 years, 9 months
[PATCH 1/4] NetConfigParse: Extending options parsing
by Radek Pazdera
From: Radek Pazdera <rpazdera(a)redhat.com>
This commit makes NetConfigParser accept <netdevice> options in a
slightly different format. Previous format of options accepted values
only as an 'value' attribute to the <option> tag. With this modification
it is possible to define options also with values as a text elements of
the option tag. There are now two possibilities:
<!-- The usual way -->
<option name="opt" value="5" />
<!-- Longer values can be specified like this -->
<option name="teamd_config">
{
"device": "team1",
"runner": {"name": "roundrobin"},
"ports": {"eth3": {}, "eth4": {}}
}
</option>
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
---
NetConfig/NetConfigParse.py | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/NetConfig/NetConfigParse.py b/NetConfig/NetConfigParse.py
index f94a73d..6538737 100644
--- a/NetConfig/NetConfigParse.py
+++ b/NetConfig/NetConfigParse.py
@@ -96,7 +96,17 @@ class NetConfigParse:
def _parse_options_handler(self, lst, dom_element, config):
name = str(dom_element.getAttribute("name"))
- value = str(dom_element.getAttribute("value"))
+
+ value = ""
+ if dom_element.hasAttribute("value"):
+ value = str(dom_element.getAttribute("value"))
+ elif dom_element.hasChildNodes():
+ node = dom_element.firstChild
+ try:
+ value = str(dom_element.firstChild.data)
+ except:
+ raise Exception("Invalid option value")
+
lst.append((name, value))
def _parse_options(self, netdev, dom_netdev, config):
--
1.7.7.6
11 years, 9 months