From: Ondrej Lichtner <olichtne(a)redhat.com>
This parameter class accepts a Device or DeviceRef objects as possible
values. Since RemoteDevice is also recognized as a Device instance this
will work on the Controller where the parameter value is set.
DeviceRef is then used by the Controller-Slave communication methods to
transfer the information. For this to work properly the TestModule is
deepcopied and modified (only DeviceParam) before transmission. Since
DeviceParam can refer to a VirtualDevice object it cannot be deepcopied
so we override it's deepcopy operation to only do a shallowcopy.
It's important to note that at the moment this works in just one
direction: Controller -> Slave and not the other way around. However
this shouldn't be a problem since passing Parameters the other way
around doesn't really make sense.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Common/Parameters.py | 19 +++++++++++++++++++
lnst/Controller/MessageDispatcher.py | 15 +++++++++++++++
lnst/Slave/NetTestSlave.py | 12 ++++++++++++
3 files changed, 46 insertions(+)
diff --git a/lnst/Common/Parameters.py b/lnst/Common/Parameters.py
index 16385b4..e21c8d6 100644
--- a/lnst/Common/Parameters.py
+++ b/lnst/Common/Parameters.py
@@ -14,6 +14,7 @@ __author__ = """
olichtne(a)redhat.com (Ondrej Lichtner)
"""
+from lnst.Common.DeviceRef import DeviceRef
from lnst.Common.IpAddress import BaseIpAddress, IpAddress
from lnst.Common.LnstError import LnstError
@@ -91,6 +92,24 @@ class IpParam(Param):
"Not {}".format(type(value)))
self.set = True
+class DeviceParam(Param):
+ @Param.val.setter
+ def val(self, value):
+ #runtime import this because the Device class arrives on the Slave
+ #during recipe execution, not during Slave init
+ from lnst.Devices.Device import Device
+ if isinstance(value, Device) or isinstance(value, DeviceRef):
+ self._val = value
+ else:
+ raise ParamError("Value must be a Device or DeviceRef object."
+ "Not {}".format(type(value)))
+ self.set = True
+
+ def __deepcopy__(self, memo):
+ newone = type(self)()
+ newone.__dict__.update(self.__dict__)
+ return newone
+
class Parameters(object):
def __getattribute__(self, name):
"""
diff --git a/lnst/Controller/MessageDispatcher.py b/lnst/Controller/MessageDispatcher.py
index 0f3d23d..1609dd5 100644
--- a/lnst/Controller/MessageDispatcher.py
+++ b/lnst/Controller/MessageDispatcher.py
@@ -15,8 +15,11 @@ olichtne(a)redhat.com (Ondrej Lichtner)
"""
import logging
+import copy
from lnst.Common.ConnectionHandler import send_data
from lnst.Common.ConnectionHandler import ConnectionHandler
+from lnst.Common.TestModule import BaseTestModule
+from lnst.Common.Parameters import Parameters, DeviceParam
from lnst.Common.DeviceRef import DeviceRef
from lnst.Controller.Common import ControllerError
from lnst.Devices.RemoteDevice import RemoteDevice
@@ -64,6 +67,18 @@ def remote_device_to_deviceref(obj):
for value in obj:
new_list.append(remote_device_to_deviceref(value))
return tuple(new_list)
+ elif isinstance(obj, DeviceParam):
+ new_param = DeviceParam()
+ new_param.val = remote_device_to_deviceref(obj.val)
+ return new_param
+ elif isinstance(obj, Parameters):
+ for param_name, param in obj:
+ setattr(obj, param_name, remote_device_to_deviceref(param))
+ return obj
+ elif isinstance(obj, BaseTestModule):
+ new_test = copy.deepcopy(obj)
+ new_test.params = remote_device_to_deviceref(new_test.params)
+ return new_test
else:
return obj
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index 99914df..9a29808 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -41,6 +41,8 @@ from lnst.Common.DeviceRef import DeviceRef
from lnst.Common.LnstError import LnstError
from lnst.Common.DeviceError import DeviceDeleted
from lnst.Common.IpAddress import IpAddress
+from lnst.Common.TestModule import BaseTestModule
+from lnst.Common.Parameters import Parameters, DeviceParam
from lnst.Slave.Job import Job, JobContext
from lnst.Slave.InterfaceManager import InterfaceManager
from lnst.Slave.BridgeTool import BridgeTool
@@ -1002,6 +1004,16 @@ def deviceref_to_device(if_manager, obj):
for value in obj:
new_list.append(deviceref_to_device(if_manager, value))
return tuple(new_list)
+ elif isinstance(obj, DeviceParam):
+ obj.val = deviceref_to_device(if_manager, obj.val)
+ return obj
+ elif isinstance(obj, Parameters):
+ for param_name, param in obj:
+ deviceref_to_device(if_manager, param)
+ return obj
+ elif isinstance(obj, BaseTestModule):
+ deviceref_to_device(if_manager, obj.params)
+ return obj
else:
return obj
--
2.13.0