From: Ondrej Lichtner <olichtne(a)redhat.com>
After creating all the soft interfaces specified in the recipe, the
Controller will now wait until the associated Device object on the Slave
is initialized - this means waiting until there are no more devices left
in the _tmp_mapping dictionary of InterfaceManager.
To do this we introduced a new NetTestSlave method - wait_interface_init
that only returns after the InterfaceManager is ready.
This method is also called every time you create a device from inside a
python task.
This should avoid potential race conditions that we've experienced.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Tested-by: Jiri Pirko <jiri(a)mellanox.com>
---
lnst/Controller/Machine.py | 3 +++
lnst/Controller/NetTestController.py | 2 ++
lnst/Controller/Task.py | 3 +++
lnst/Slave/InterfaceManager.py | 12 ++++++++++++
lnst/Slave/NetTestSlave.py | 4 ++++
5 files changed, 24 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index d0e5b1b..755a2dd 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -500,6 +500,9 @@ class Machine(object):
self._namespaces = []
return True
+ def wait_interface_init(self):
+ return self._rpc_call("wait_interface_init")
+
class Interface(object):
""" Abstraction of a test network interface on a slave machine
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 04aa473..1e90688 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -223,6 +223,8 @@ class NetTestController:
for iface in ifaces:
iface.up()
+ m.wait_interface_init()
+
def provision_machines(self):
sp = self._slave_pool
machines = self._machines
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index e354180..9aac8c4 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -404,6 +404,9 @@ class HostAPI(object):
interface.configure()
interface.up()
+
+ self._m.wait_interface_init()
+
return iface
def _remove_iface(self, iface):
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index dfc2d10..144f5a7 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -13,11 +13,13 @@ olichtne(a)redhat.com (Ondrej Lichtner)
"""
import re
+import select
from lnst.Slave.NetConfigDevice import NetConfigDevice
from lnst.Slave.NetConfigCommon import get_option
from lnst.Common.NetUtils import normalize_hwaddr
from lnst.Common.NetUtils import scan_netdevs
from lnst.Common.ExecCmd import exec_cmd
+from lnst.Common.ConnectionHandler import recv_data
from pyroute2 import IPRSocket
try:
from pyroute2.netlink.iproute import RTM_NEWLINK
@@ -210,6 +212,16 @@ class InterfaceManager(object):
self._tmp_mapping[if_id2] = device2
return name1, name2
+ def wait_interface_init(self):
+ while len(self._tmp_mapping) > 0:
+ rl, wl, xl = select.select([self._nl_socket], [], [], 1)
+
+ if len(rl) == 0:
+ continue
+
+ msgs = recv_data(self._nl_socket)["data"]
+ self.handle_netlink_msgs(msgs)
+
def _is_name_used(self, name):
for device in self._devices.itervalues():
if name == device.get_name():
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index 12b3381..5569f07 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -763,6 +763,10 @@ class SlaveMethods:
return False
return True
+ def wait_interface_init(self):
+ self._if_manager.wait_interface_init()
+ return True
+
class ServerHandler(ConnectionHandler):
def __init__(self, addr):
super(ServerHandler, self).__init__()
--
2.7.0