[PATCH] Fix forgotten rename of target_bridge to libvirt_bridge
by Jan Tluka
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"]
--
1.7.7.6
11 years, 7 months
[lnst trac] #21: result summary improvement
by fedora-badges
#21: result summary improvement
-------------------------+-----------------------
Reporter: olichtne | Owner: somebody
Type: enhancement | Status: new
Priority: major | Milestone:
Component: component1 | Version:
Keywords: | Blocked By:
Blocking: |
-------------------------+-----------------------
Currently the summary of running a recipe consists of only a *PASS* or
*FAIL* message for every recipe. When running more recipes with more
complex command sequences this isn't ideal when you need to see which part
of a test failed.
Summaries should contain more information about the command results.
--
Ticket URL: <https://fedorahosted.org/lnst/ticket/21>
lnst <http://example.org/>
My example project
11 years, 7 months
[lnst trac] #20: suggestion: add suppport for dynamic template functions
by fedora-badges
#20: suggestion: add suppport for dynamic template functions
-------------------------+-----------------------
Reporter: olichtne | Owner: somebody
Type: enhancement | Status: new
Priority: major | Milestone:
Component: component1 | Version:
Keywords: | Blocked By:
Blocking: |
-------------------------+-----------------------
Template functions could be dynamically loaded in a similar way to how
Tests are loaded. We could create a new directory e.g. Functions/ where
they would be located. I discussed this with Jirka when we talked on the
topic of directly using python commands in the recipes. It would also make
template functions more universal and flexible.
Implementation of this shouldn't be too complicated. But the more
important question is how could this be used. The problem I see here is
that currently template functions are used to access internal data of the
controller. However the dynamically loaded functions shouldn't be able to
do this because they either wouldn't see the internal data structures or
it would be too confusing if they somehow did.
If you have any suggestions/ideas of use cases or on the other hand you
think this is a bad idea please add a comment.
--
Ticket URL: <https://fedorahosted.org/lnst/ticket/20>
lnst <http://example.org/>
My example project
11 years, 7 months
[PATCH] Logs: warn user if slave can't connect to logging server
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
Currently logging doesn't work correctly if the connection between a
slave and the controller isn't properly set up. This can be for example
caused by a firewall. In these cases it can be confusing to users
because there is no indication of it other than missing logs.
This patch changes that. It adds a new function test_tcp_connection() to
the NetUtils module. Slaves use it to check if they are able to connect to
the logging server and inform the controller of the results. The
controller can then log an error message in case of a failure.
I tried making the error message more visible so that it's harder to
overlook.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
Common/NetUtils.py | 9 +++++++++
NetTest/NetTestController.py | 6 +++++-
NetTest/NetTestSlave.py | 6 ++++--
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/Common/NetUtils.py b/Common/NetUtils.py
index d7db077..fb39a41 100644
--- a/Common/NetUtils.py
+++ b/Common/NetUtils.py
@@ -37,6 +37,15 @@ def scan_netdevs():
scan.append({"name": d, "hwaddr": addr})
return scan
+def test_tcp_connection(host, port):
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((host, port))
+ s.shutdown(socket.SHUT_RDWR)
+ return True
+ except:
+ return False
+
def verify_ip_address(addr):
if len(addr.split('.')) != 4:
return False
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py
index 95326e3..526a3e7 100644
--- a/NetTest/NetTestController.py
+++ b/NetTest/NetTestController.py
@@ -261,7 +261,11 @@ class NetTestController:
logging.info("Setting logging server on machine %s", hostname)
rpc = self._get_machinerpc(machine_id)
ip_addr = get_corespond_local_ip(hostname)
- rpc.set_logging(ip_addr, self._config.get_option('log', 'port'))
+ if not rpc.set_logging(ip_addr, self._config.get_option('log', 'port')):
+ logging.error("==================================================")
+ logging.error("Machine %s is unable to connect to the logging "\
+ "server! Check your firewall settings." % hostname)
+ logging.error("==================================================")
def _deconfigure_slaves(self):
if 'machines' not in self._recipe:
diff --git a/NetTest/NetTestSlave.py b/NetTest/NetTestSlave.py
index 7c391f8..a375f12 100644
--- a/NetTest/NetTestSlave.py
+++ b/NetTest/NetTestSlave.py
@@ -22,7 +22,7 @@ from NetConfig.NetConfig import NetConfig
from NetConfig.NetConfigDevice import NetConfigDeviceAllCleanup
from NetTest.NetTestCommand import NetTestCommandContext, NetTestCommand, CommandException
from Common.Utils import die_when_parent_die
-from Common.NetUtils import scan_netdevs
+from Common.NetUtils import scan_netdevs, test_tcp_connection
DefaultRPCPort = 9999
@@ -45,8 +45,10 @@ class NetTestSlaveXMLRPC:
@param logger_address: Address of running logger.
"""
+ connectable = test_tcp_connection(logger_address, port)
+
Logs.append_network_hadler(logger_address, port)
- return True
+ return connectable
def get_devices_by_hwaddr(self, hwaddr):
name_scan = scan_netdevs()
--
1.7.11.4
11 years, 7 months
[PATCH] Fixed interrupt handling in TCPConnect and TCPListen
by Jan Tluka
Fixed interrupt signal handling in the tests. All socket operations were
changed to non-blocking so that workers can stop their execution almost
immediately. Tested on RHEL5.9/RHEL6.3 instances.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
Tests/TestTCPConnect.py | 88 +++++++++++++++++++++++++++++------------
Tests/TestTCPListen.py | 101 ++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 148 insertions(+), 41 deletions(-)
diff --git a/Tests/TestTCPConnect.py b/Tests/TestTCPConnect.py
index 0a6c655..f4020f0 100644
--- a/Tests/TestTCPConnect.py
+++ b/Tests/TestTCPConnect.py
@@ -9,13 +9,14 @@ jtluka(a)redhat.com (Jan Tluka)
import sys
import socket
import errno
-from multiprocessing import Process, Lock
+from multiprocessing import Process, Value
from signal import signal, SIGINT
from time import sleep
from random import randrange, sample
import logging
import re
from Common.TestsCommon import TestGeneric
+import ctypes
"""
Test description:
@@ -35,52 +36,81 @@ Parameters:
class ConnectionWorker():
def __init__(self, host, port, sleep_time = None, continuous = None):
- self._tlock = Lock()
- self._terminate = 0
self._host = host
self._port = port
self._sleep_time = sleep_time
self._cont = continuous
self._ascii = [chr(i) for i in range(0,255)]
- def terminate(self):
- self._tlock.acquire()
- self._terminate=1
- self._tlock.release()
-
- def run(self):
+ def run(self, closecon):
loop = True
- while loop:
+ while loop and not closecon.value:
loop = (self._cont is not None)
logging.debug("Starting connection to (%s) port %s " % (self._host,
self._port))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ except socket.error, msg:
+ logging.debug(msg)
+ return
+
+ s.settimeout(5)
+
+ try:
s.connect((self._host, self._port))
+ except socket.timeout, msg:
+ logging.debug("Could not connect to %s port %s" %
+ (self._host, self._port))
+ s.close()
+ continue
except socket.error, msg:
+ logging.debug(msg)
s.close()
- s = None
- logging.error(msg)
- return
+ break
+
+ s.settimeout(1)
for txs in range(10, randrange(20,100)):
- self._tlock.acquire()
- if self._terminate:
- self._tlock.release()
+ if closecon.value:
logging.debug("Terminating connection on port %s" %
self._port)
loop = False
- break
- else:
- self._tlock.release()
+ s.settimeout(0)
+ try:
+ s.shutdown(socket.SHUT_WR)
+ except:
+ pass
+ s.close()
+ return
rnd_str = "".join(sample(self._ascii, len(self._ascii)))
- data = s.sendall(rnd_str)
+ while True and not closecon.value:
+ try:
+ data = s.sendall(rnd_str)
+ except socket.timeout:
+ continue
+ except socket.error, msg:
+ logging.debug(msg)
+ s.settimeout(0)
+ try:
+ s.shutdown(socket.SHUT_WR)
+ except:
+ pass
+ s.close()
+ return
+
+ break
+
if (self._sleep_time):
sleep(self._sleep_time)
+ s.settimeout(0)
+ try:
+ s.shutdown(socket.SHUT_WR)
+ except:
+ pass
s.close()
@@ -129,18 +159,17 @@ class TestTCPConnect(TestGeneric):
def _close_connections(self, signum, frame):
logging.debug("Termination signal delivered ...")
- for cw in self._cw_instances:
- cw.terminate()
+ self._closecon.value = True
def _set_interrupt_handler(self):
signal(SIGINT, self._close_connections)
def run(self):
- self._terminate = 0
self._host = None
self._port = None
self._cont = None
self._cw_instances = []
+ self._closecon = Value(ctypes.c_bool, False, lock=True)
self._set_interrupt_handler()
@@ -158,10 +187,17 @@ class TestTCPConnect(TestGeneric):
cw = ConnectionWorker(self._host, p, self._sleep_time, self._cont)
self._cw_instances.append(cw)
- w = Process(target=cw.run)
+ w = Process(target=cw.run, args=(self._closecon,))
w.start()
workers.append(w)
logging.debug("Waiting for workers ...")
- for w in workers:
- w.join()
+ while len(workers) > 0:
+ for w in workers:
+ try:
+ w.join()
+ except OSError, e:
+ continue
+ workers.remove(w)
+
+ logging.info("Connect: Finished ...")
diff --git a/Tests/TestTCPListen.py b/Tests/TestTCPListen.py
index c214a3d..3cf0798 100644
--- a/Tests/TestTCPListen.py
+++ b/Tests/TestTCPListen.py
@@ -11,8 +11,10 @@ import socket
import errno
import logging
import re
-from multiprocessing import Process
+from multiprocessing import Process, Value
from Common.TestsCommon import TestGeneric
+from signal import signal, SIGINT
+import ctypes
"""
Test description:
@@ -34,6 +36,8 @@ class TestTCPListen(TestGeneric):
self._addr = None
self._port = None
self._cont = None
+ self._closecon = Value(ctypes.c_bool, False, lock=True)
+
TestGeneric.__init__(self, command)
def _parse_options(self):
@@ -57,36 +61,83 @@ class TestTCPListen(TestGeneric):
if cont:
self._cont = cont
- def _worker(self, host, port):
+ def _worker(self, host, port, connections, closecon):
logging.debug("Starting listener (%s) on port %s " % (host, port))
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.settimeout(1)
+ except socket.error, msg:
+ logging.debug(msg)
+ return
+
+ try:
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
except socket.error, msg:
+ logging.debug(msg)
s.close()
- s = None
- logging.error(msg)
return
loop = 1
- while loop or self._cont:
- conn, addr = s.accept()
+ while (loop or self._cont) and not closecon.value:
+ conn = None
+ while conn == None and not closecon.value:
+ try:
+ conn, addr = s.accept()
+ except socket.timeout, e:
+ continue
+ except socket.error, e:
+ logging.debug(e)
+ s.close()
+ return
+ except:
+ logging.warning("Unknown exception.")
+ s.close()
+ return
+
+ if conn:
+ connections.value += 1
+ conn.settimeout(1)
+ else:
+ continue
+
logging.debug('Connected from ' + addr[0] + ' port:' +
str(addr[1]))
- while 1:
- data = conn.recv(1024)
+ while not closecon.value:
+ try:
+ data = conn.recv(1024)
+ except socket.timeout, e:
+ continue
+ except socket.error, e:
+ logging.debug(e)
+ if conn:
+ conn.shutdown(socket.SHUT_RDWR)
+ conn.close()
+ s.close()
+ return
+
if not data:
logging.debug('Client disconnected: ' + addr[0] +
' port:' + str(addr[1]))
break
- conn.close()
+ if conn:
+ try:
+ conn.shutdown(socket.SHUT_RDWR)
+ conn.close()
+ except socket.error, msg:
+ logging.debug(msg)
+ s.close()
+ return
+
loop = 0
+ s.close()
+
def _parse_port_range(self):
if self._port_range == None:
return []
@@ -104,7 +155,16 @@ class TestTCPListen(TestGeneric):
return range(low, high)
+ def _terminate(self, signum, frame):
+ self._closecon.value = True
+ logging.debug("Listen: terminate called")
+
+ def _set_interrupt_handler(self):
+ signal(SIGINT, self._terminate)
+
def run(self):
+ self._set_interrupt_handler()
+
self._parse_options()
ports = []
@@ -114,14 +174,25 @@ class TestTCPListen(TestGeneric):
r = self._parse_port_range()
ports.extend(r)
- workers = []
+ self.workers = []
+
+ connections = Value('L', 0, lock=True)
for p in ports:
- w = Process(target=self._worker, args=(self._addr, p))
+ w = Process(target=self._worker, args=(self._addr, p, connections, self._closecon))
w.start()
- workers.append(w)
+ self.workers.append(w)
logging.debug("Waiting for workers ...")
- for w in workers:
- w.join()
+ while len(self.workers) > 0:
+ for w in self.workers:
+ try:
+ w.join()
+ except:
+ continue
+ self.workers.remove(w)
+
+ logging.info("Handled %s TCP connections." % connections.value)
+
+ return self.set_pass("Handled %s TCP connections." % connections.value)
--
1.7.7.6
11 years, 7 months
[lnst] do not log ethtool errors
by Jiří Pírko
commit c6b735881493064f7eba6a8418a6d766a3b531f1
Author: Jiri Pirko <jiri(a)resnulli.us>
Date: Thu Sep 13 14:50:26 2012 +0200
do not log ethtool errors
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
NetConfig/NetConfigDevice.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/NetConfig/NetConfigDevice.py b/NetConfig/NetConfigDevice.py
index f991db7..1da5afa 100644
--- a/NetConfig/NetConfigDevice.py
+++ b/NetConfig/NetConfigDevice.py
@@ -75,7 +75,7 @@ class NetConfigDeviceEth(NetConfigDeviceGeneric):
def configure(self):
netdev = self._netdev
exec_cmd("ip addr flush %s" % netdev["name"])
- exec_cmd("ethtool -A %s rx off tx off" % netdev["name"], die_on_err=False)
+ exec_cmd("ethtool -A %s rx off tx off" % netdev["name"], die_on_err=False, log_outputs=False)
class NetConfigDeviceBond(NetConfigDeviceGeneric):
_modulename = "bonding"
11 years, 7 months
intr command enhancement
by Jan Tluka
Hi, I'm currently reworking TCPListen and TCPConnect tests and came over
following.
If intr command is executed the whole process group would get signalled. In
my scenario this is a bit complicated since I want to collect some data
when the test is interrupted. With the current intr implementation I am
receiving signals during socket operation system calls in spawned worker
threads. I'm handling termination of child threads inside the test
implementation via shared variable.
I'm thinking about changing the current intr command implementation or adding
an additional intr_parent command. I think that second would be better
to preserve compatibility. The name is matter of discussion.
I'm open to your suggestions and comments.
-Jan
11 years, 7 months
[lnst] NetTestController: bugfix for machine cleanup
by Jiří Pírko
commit 7a6044a136773c267bf95988f1567039169f3070
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Wed Sep 12 09:59:12 2012 +0200
NetTestController: bugfix for machine cleanup
Machine cleanup would sometimes end with a KeyError. This would happen
when recipe parsing failed too soon and no machines were parsed yet.
This commit fixes that.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
NetTest/NetTestController.py | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
---
diff --git a/NetTest/NetTestController.py b/NetTest/NetTestController.py
index 548fc17..95326e3 100644
--- a/NetTest/NetTestController.py
+++ b/NetTest/NetTestController.py
@@ -264,6 +264,8 @@ class NetTestController:
rpc.set_logging(ip_addr, self._config.get_option('log', 'port'))
def _deconfigure_slaves(self):
+ if 'machines' not in self._recipe:
+ return
for machine_id in self._recipe["machines"]:
info = self._get_machineinfo(machine_id)
if "rpc" not in info:
@@ -288,6 +290,8 @@ class NetTestController:
net["default_bridge"].cleanup()
def _disconnect_slaves(self):
+ if 'machines' not in self._recipe:
+ return
for machine_id in self._recipe["machines"]:
info = self._get_machineinfo(machine_id)
if self._remoteexec and "session" in info:
11 years, 7 months
[lnst] disable pausing on eth devices
by Jiří Pírko
commit 17c8272d03f31fde8ae526b4fa1f21494be4b1fc
Author: Jiri Pirko <jiri(a)resnulli.us>
Date: Wed Sep 12 21:35:07 2012 +0200
disable pausing on eth devices
That was killing pktgen performance
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
NetConfig/NetConfigDevice.py | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
---
diff --git a/NetConfig/NetConfigDevice.py b/NetConfig/NetConfigDevice.py
index 2dd8d1a..f991db7 100644
--- a/NetConfig/NetConfigDevice.py
+++ b/NetConfig/NetConfigDevice.py
@@ -75,6 +75,7 @@ class NetConfigDeviceEth(NetConfigDeviceGeneric):
def configure(self):
netdev = self._netdev
exec_cmd("ip addr flush %s" % netdev["name"])
+ exec_cmd("ethtool -A %s rx off tx off" % netdev["name"], die_on_err=False)
class NetConfigDeviceBond(NetConfigDeviceGeneric):
_modulename = "bonding"
11 years, 7 months
[lnst] use pktgen options directly
by Jiří Pírko
commit fd3fb5c497042ca259f2f4f26bbda1c76afb2e91
Author: Jiri Pirko <jiri(a)resnulli.us>
Date: Wed Sep 12 21:08:07 2012 +0200
use pktgen options directly
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
Tests/TestPktgenTx.py | 23 +++++++++++------------
1 files changed, 11 insertions(+), 12 deletions(-)
---
diff --git a/Tests/TestPktgenTx.py b/Tests/TestPktgenTx.py
index 792a991..46660c9 100644
--- a/Tests/TestPktgenTx.py
+++ b/Tests/TestPktgenTx.py
@@ -54,11 +54,13 @@ class PktgenWorkers:
class TestPktgenTx(TestGeneric):
def run(self):
dev_names = self.get_multi_mopt("netdev_name")
- addr = self.get_mopt("addr", opt_type="addr")
- 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)
+ pktgen_options = self.get_multi_mopt("pktgen_option")
+
+ default_pktgen_options = [
+ "count 10000000",
+ "clone_skb 100000",
+ "pkt_size 60",
+ ]
exec_cmd("modprobe pktgen")
@@ -69,13 +71,10 @@ class TestPktgenTx(TestGeneric):
for dev_name in dev_names:
pgwrkr.add_device(dev_name)
pg = Pktgen("/proc/net/pktgen/%s" % dev_name)
- pg.set("clone_skb %s" % skb_clone)
- pg.set("pkt_size 60")
- pg.set("dst %s" % addr)
- pg.set("dst_mac %s" % hwaddr)
- if vlan_tci:
- pg.set("vlan_id %d" % vlan_tci)
- pg.set("count %d" % count)
+ for pktgen_option in default_pktgen_options:
+ pg.set(pktgen_option)
+ for pktgen_option in pktgen_options:
+ pg.set(pktgen_option)
pgctl.set("start")
except ExecCmdFail:
return self.set_fail("pktgen failed")
11 years, 7 months