From 00f2c243566b08387658112d684c31371286ffcc Mon Sep 17 00:00:00 2001 From: Alina Quereilhac Date: Sun, 1 May 2011 22:36:44 +0200 Subject: [PATCH] mock cross_connect test added to test/core/integration.py --- src/nepi/core/execute.py | 36 ++-- src/nepi/core/testbed_impl.py | 33 ++-- src/nepi/testbeds/netns/execute.py | 10 +- src/nepi/testbeds/netns/metadata_v01.py | 7 +- src/nepi/testbeds/ns3/execute.py | 10 +- src/nepi/testbeds/ns3/metadata_v3_9_RC3.py | 57 ++++-- src/nepi/testbeds/planetlab/execute.py | 9 +- src/nepi/testbeds/planetlab/metadata_v01.py | 23 ++- src/nepi/util/proxy.py | 108 +++++++--- test/core/execute.py | 2 +- test/core/integration.py | 44 ++++- test/lib/mock/metadata_v01.py | 46 +++-- test/lib/mock2/__init__.py | 6 + test/lib/mock2/constants.py | 5 + test/lib/mock2/execute.py | 31 +++ test/lib/mock2/metadata_v01.py | 208 ++++++++++++++++++++ 16 files changed, 518 insertions(+), 117 deletions(-) create mode 100644 test/lib/mock2/__init__.py create mode 100644 test/lib/mock2/constants.py create mode 100644 test/lib/mock2/execute.py create mode 100644 test/lib/mock2/metadata_v01.py diff --git a/src/nepi/core/execute.py b/src/nepi/core/execute.py index f64368c1..ca3199b3 100644 --- a/src/nepi/core/execute.py +++ b/src/nepi/core/execute.py @@ -266,10 +266,10 @@ class TestbedController(object): def stop(self): raise NotImplementedError - def set(self, time, guid, name, value): + def set(self, guid, name, value, time = TIME_NOW): raise NotImplementedError - def get(self, time, guid, name): + def get(self, guid, name, time = TIME_NOW): raise NotImplementedError def get_route(self, guid, index, attribute): @@ -458,6 +458,14 @@ class ExperimentController(object): return testbed.status(guid) == STATUS_FINISHED raise RuntimeError("No element exists with guid %d" % guid) + def set(self, testbed_guid, guid, name, value, time = TIME_NOW): + testbed = self._testbeds[testbed_guid] + testbed.set(guid, name, value, time) + + def get(self, testbed_guid, guid, name, time = TIME_NOW): + testbed = self._testbeds[testbed_guid] + return testbed.get(guid, name, time) + def shutdown(self): for testbed in self._testbeds.values(): testbed.shutdown() @@ -483,13 +491,13 @@ class ExperimentController(object): testbed.trace(guid, index, name), '' : lambda testbed, guid, index, name: - testbed.get(TIME_NOW, guid, name), + testbed.get(guid, name), } for (testbed_guid, guid), attrs in self._netrefs.iteritems(): testbed = self._testbeds[testbed_guid] for name in attrs: - value = testbed.get(TIME_NOW, guid, name) + value = testbed.get(guid, name) if isinstance(value, basestring): match = ATTRIBUTE_PATTERN_BASE.search(value) if match: @@ -513,8 +521,8 @@ class ExperimentController(object): ref_value = COMPONENT_GETTERS[component]( ref_testbed, ref_guid, component_index, attribute) if ref_value: - testbed.set(TIME_NOW, guid, name, - value.replace(match.group(), ref_value)) + testbed.set(guid, name, + value.replace(match.group(), ref_value)) break else: # couldn't find value @@ -616,7 +624,7 @@ class ExperimentController(object): cross_testbed = self._testbeds[cross_testbed_guid] cross_testbed_id = cross_testbed.testbed_id testbed.defer_cross_connect(guid, connector_type_name, cross_guid, - cross_testbed_id, cross_factory_id, + cross_testbed_guid, cross_testbed_id, cross_factory_id, cross_connector_type_name) # save cross data for later self._add_crossdata(testbed_guid, guid, cross_testbed_guid, @@ -635,13 +643,8 @@ class ExperimentController(object): if testbed_guid not in self._cross_data: self._cross_data[testbed_guid] = dict() if cross_testbed_guid not in self._cross_data[testbed_guid]: - self._cross_data[testbed_guid][cross_testbed_guid] = list() - if cross_testbed_guid not in self._cross_data: - self._cross_data[cross_testbed_guid] = dict() - if testbed_guid not in self._cross_data[cross_testbed_guid]: - self._cross_data[cross_testbed_guid][testbed_guid] = list() - self._cross_data[testbed_guid][cross_testbed_guid].append(cross_guid) - self._cross_data[cross_testbed_guid][testbed_guid].append(guid) + self._cross_data[testbed_guid][cross_testbed_guid] = set() + self._cross_data[testbed_guid][cross_testbed_guid].add(cross_guid) def _get_cross_data(self, testbed_guid): cross_data = dict() @@ -656,8 +659,7 @@ class ExperimentController(object): cross_data[cross_testbed_guid][cross_guid] = elem_cross_data attributes_list = cross_testbed.get_attribute_list(cross_guid) for attr_name in attributes_list: - attr_value = cross_testbed.get(TIME_NOW, cross_guid, - attr_name) + attr_value = cross_testbed.get(cross_guid, attr_name) elem_cross_data[attr_name] = attr_value - return elem_cross_data + return cross_data diff --git a/src/nepi/core/testbed_impl.py b/src/nepi/core/testbed_impl.py index 37d53eb7..8966cced 100644 --- a/src/nepi/core/testbed_impl.py +++ b/src/nepi/core/testbed_impl.py @@ -125,7 +125,8 @@ class TestbedController(execute.TestbedController): connector_type_name1 def defer_cross_connect(self, guid, connector_type_name, cross_guid, - cross_testbed_id, cross_factory_id, cross_connector_type_name): + cross_testbed_guid, cross_testbed_id, cross_factory_id, + cross_connector_type_name): factory = self._get_factory(guid) count = self._get_connection_count(guid, connector_type_name) connector_type = factory.connector_type(connector_type_name) @@ -136,8 +137,8 @@ class TestbedController(execute.TestbedController): if not connector_type_name in self._cross_connect[guid]: self._cross_connect[guid][connector_type_name] = dict() self._cross_connect[guid][connector_type_name] = \ - (cross_guid, cross_testbed_id, cross_factory_id, - cross_connector_type_name) + (cross_guid, cross_testbed_guid, cross_testbed_id, + cross_factory_id, cross_connector_type_name) def defer_add_trace(self, guid, trace_id): if not guid in self._create: @@ -198,17 +199,15 @@ class TestbedController(execute.TestbedController): factory.create_function(self, guid) parameters = self._get_parameters(guid) for name, value in parameters.iteritems(): - self.set(TIME_NOW, guid, name, value) + self.set(guid, name, value) self._status = TESTBED_STATUS_CREATED def _do_connect(self, init = True): for guid1, connections in self._connect.iteritems(): - element1 = self._elements[guid1] factory1 = self._get_factory(guid1) for connector_type_name1, connections2 in connections.iteritems(): connector_type1 = factory1.connector_type(connector_type_name1) for guid2, connector_type_name2 in connections2.iteritems(): - element2 = self._elements[guid2] factory_id2 = self._create[guid2] # Connections are executed in a "From -> To" direction only # This explicitly ignores the "To -> From" (mirror) @@ -222,7 +221,7 @@ class TestbedController(execute.TestbedController): self._testbed_id, factory_id2, connector_type_name2) if connect_code: - connect_code(self, element1, element2) + connect_code(self, guid1, guid2) def do_connect_init(self): self._do_connect() @@ -270,24 +269,23 @@ class TestbedController(execute.TestbedController): def _do_cross_connect(self, cross_data, init = True): for guid, cross_connections in self._cross_connect.iteritems(): - element = self._elements[guid] factory = self._get_factory(guid) for connector_type_name, cross_connection in \ cross_connections.iteritems(): connector_type = factory.connector_type(connector_type_name) - (cross_testbed_id, cross_factory_id, - cross_connector_type_name) = cross_connection + (cross_guid, cross_testbed_guid, cross_testbed_id, + cross_factory_id, cross_connector_type_name) = cross_connection if init: connect_code = connector_type.connect_to_init_code( cross_testbed_id, cross_factory_id, - cross_conector_type_name) + cross_connector_type_name) else: connect_code = connector_type.connect_to_compl_code( cross_testbed_id, cross_factory_id, - cross_conector_type_name) + cross_connector_type_name) if connect_code: - elem_data_guid = cross_data[cross_testbed_id][cross_guid] - connect_code(self, element, elem_cross_data) + elem_cross_data = cross_data[cross_testbed_guid][cross_guid] + connect_code(self, guid, elem_cross_data) def do_cross_connect_init(self, cross_data): self._do_cross_connect(cross_data) @@ -296,7 +294,7 @@ class TestbedController(execute.TestbedController): self._do_cross_connect(cross_data, init = False) self._status = TESTBED_STATUS_CROSS_CONNECTED - def set(self, time, guid, name, value): + def set(self, guid, name, value, time = TIME_NOW): if not guid in self._create: raise RuntimeError("Element guid %d doesn't exist" % guid) factory = self._get_factory(guid) @@ -317,7 +315,7 @@ class TestbedController(execute.TestbedController): self._setlog[guid][time][name] = value self._set[guid][name] = value - def get(self, time, guid, name): + def get(self, guid, name, time = TIME_NOW): """ gets an attribute from box definitions if available. Throws KeyError if the GUID wasn't created @@ -330,9 +328,6 @@ class TestbedController(execute.TestbedController): if not factory.box_attributes.has_attribute(name): raise AttributeError, "Invalid attribute %s for element type %s" % \ (name, factory.factory_id) - if self._status > TESTBED_STATUS_CREATED and \ - factory.box_attributes.is_attribute_design_only(name): - raise AttributeError, "Attribute %s can only be queried during experiment design" % name if guid in self._set and name in self._set[guid]: return self._set[guid][name] if guid in self._create_set and name in self._create_set[guid]: diff --git a/src/nepi/testbeds/netns/execute.py b/src/nepi/testbeds/netns/execute.py index cba37f07..67dee91e 100644 --- a/src/nepi/testbeds/netns/execute.py +++ b/src/nepi/testbeds/netns/execute.py @@ -3,7 +3,7 @@ from constants import TESTBED_ID from nepi.core import testbed_impl -from nepi.util.constants import TESTBED_STATUS_CREATED +from nepi.util.constants import TIME_NOW import os class TestbedController(testbed_impl.TestbedController): @@ -27,15 +27,15 @@ class TestbedController(testbed_impl.TestbedController): self._netns = self._load_netns_module() super(TestbedController, self).do_setup() - def set(self, time, guid, name, value): - super(TestbedController, self).set(time, guid, name, value) + def set(self, guid, name, value, time = TIME_NOW): + super(TestbedController, self).set(guid, name, value, time) # TODO: take on account schedule time for the task element = self._elements.get(guid) if element: setattr(element, name, value) - def get(self, time, guid, name): - value = super(TestbedController, self).get(time, guid, name) + def get(self, guid, name, time = TIME_NOW): + value = super(TestbedController, self).get(guid, name, time) # TODO: take on account schedule time for the task factory_id = self._create[guid] factory = self._factories[factory_id] diff --git a/src/nepi/testbeds/netns/metadata_v01.py b/src/nepi/testbeds/netns/metadata_v01.py index 526158ae..2af898d5 100644 --- a/src/nepi/testbeds/netns/metadata_v01.py +++ b/src/nepi/testbeds/netns/metadata_v01.py @@ -20,12 +20,15 @@ FDNETDEV = "ns3::FileDescriptorNetDevice" ### Connection functions #### -def connect_switch(testbed_instance, switch, interface): +def connect_switch(testbed_instance, switch_guid, interface_guid): + switch = testbed_instance._elements[switch_guid] + interface = testbed_instance._elements[interface_guid] switch.connect(interface) -def connect_fd(testbed_instance, tap, cross_data): +def connect_fd(testbed_instance, tap_guid, cross_data): import passfd import socket + tap = testbed_instance._elements[tap_guid] fd = tap.file_descriptor address = cross_data["LinuxSocketAddress"] sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) diff --git a/src/nepi/testbeds/ns3/execute.py b/src/nepi/testbeds/ns3/execute.py index 04247939..84b8f0f2 100644 --- a/src/nepi/testbeds/ns3/execute.py +++ b/src/nepi/testbeds/ns3/execute.py @@ -4,7 +4,7 @@ from constants import TESTBED_ID from nepi.core import testbed_impl from nepi.core.attributes import Attribute -from nepi.util.constants import TESTBED_STATUS_CREATED +from nepi.util.constants import TIME_NOW import os import sys import threading @@ -39,8 +39,8 @@ class TestbedController(testbed_impl.TestbedController): args = [self._condition]) self._simulator_thread.start() - def set(self, time, guid, name, value): - super(TestbedController, self).set(time, guid, name, value) + def set(self, guid, name, value, time = TIME_NOW): + super(TestbedController, self).set(guid, name, value, time) # TODO: take on account schedule time for the task factory_id = self._create[guid] factory = self._factories[factory_id] @@ -50,8 +50,8 @@ class TestbedController(testbed_impl.TestbedController): ns3_value = self._to_ns3_value(guid, name, value) element.SetAttribute(name, ns3_value) - def get(self, time, guid, name): - value = super(TestbedController, self).get(time, guid, name) + def get(self, guid, name, time = TIME_NOW): + value = super(TestbedController, self).get(guid, name, time) # TODO: take on account schedule time for the task factory_id = self._create[guid] factory = self._factories[factory_id] diff --git a/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py b/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py index 59b74132..57cbf664 100644 --- a/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py +++ b/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py @@ -8,16 +8,24 @@ from nepi.util import validation ### Connection functions #### -def connect_node_device(testbed_instance, node, device): +def connect_node_device(testbed_instance, node_guid, device_guid): + node = testbed_instance._elements[node_guid] + device = testbed_instance._elements[device_guid] node.AddDevice(device) -def connect_queue_device(testbed_instance, queue, device): +def connect_queue_device(testbed_instance, queue_guid, device_guid): + queue = testbed_instance._elements[queue_guid] + device = testbed_instance._elements[device_guid] device.SetQueue(queue) -def connect_manager_device(testbed_instance, manager, device): +def connect_manager_device(testbed_instance, manager_guid, device_guid): + manager = testbed_instance._elements[manager_guid] + device = testbed_instance._elements[device_guid] device.SetRemoteStationManager(manager) -def connect_phy_device(testbed_instance, phy, device): +def connect_phy_device(testbed_instance, phy_guid, device_guid): + phy = testbed_instance._elements[phy_guid] + device = testbed_instance._elements[device_guid] device.SetPhy(phy) phy.SetDevice(device) # search for the node asociated with the device @@ -28,40 +36,61 @@ def connect_phy_device(testbed_instance, phy, device): node = testbed_instance.elements[node_guid[0]] phy.SetMobility(node) -def connect_mac_device(testbed_instance, mac, device): +def connect_mac_device(testbed_instance, mac_guid, device_guid): + mac = testbed_instance._elements[mac_guid] + device = testbed_instance._elements[device_guid] device.SetMac(mac) -def connect_errormodel_device(testbed_instance, model, device): +def connect_errormodel_device(testbed_instance, model_guid, device_guid): + model = testbed_instance._elements[model_guid] + device = testbed_instance._elements[device_guid] device.SetReceiveErrorModel(model) -def connect_errormodel_phy(testbed_instance, err, phy): +def connect_errormodel_phy(testbed_instance, err_guid, phy_guid): + err = testbed_instance._elements[err_guid] + phy = testbed_instance._elements[phy_guid] phy.SetErrorRateModel(err) -def connect_channel_device(testbed_instance, channel, device): +def connect_channel_device(testbed_instance, channel_guid, device_guid): + channel = testbed_instance._elements[channel_guid] + device = testbed_instance._elements[device_guid] device.Attach(channel) -def connect_simple_channel_device(testbed_instance, channel, device): +def connect_simple_channel_device(testbed_instance, channel_guid, device_guid): + channel = testbed_instance._elements[channel_guid] + device = testbed_instance._elements[device_guid] device.SetChannel(channel) def connect_loss_channel(testbed_instance, loss, channel): + loss = testbed_instance._elements[loss_guid] + channel = testbed_instance._elements[channel_guid] channel.SetPropagationLossModel(loss) -def connect_next_loss(testbed_instance, prev, next): +def connect_next_loss(testbed_instance, prev_guid, next_guid): + prev = testbed_instance._elements[prev_guid] + next = testbed_instance._elements[next_guid] prev.SetNext(next) -def connect_delay_channel(testbed_instance, delay, channel): +def connect_delay_channel(testbed_instance, delay_guid, channel_guid): + delay = testbed_instance._elements[delay_guid] + channel = testbed_instance._elements[channel_guid] channel.SetPropagationDelayModel(delay) -def connect_node_application(testbed_instance, node, application): +def connect_node_application(testbed_instance, node_guid, application_guid): + node = testbed_instance._elements[node_guid] + application = testbed_instance._elements[application_guid] node.AddApplication(application) # works for ArpL3Protocol, Ipv4L3Protocol, UdpL4Protocol, TcpL4Protocol, # NscTcpL4Protocol, MobilityModel (every subclass), # RoutingProtocol (every subclass) -def connect_node_other(tesbed_instance, node, other): +def connect_node_other(testbed_instance, node_guid, other_guid): + node = testbed_instance._elements[node_guid] + other = testbed_instance._elements[other_guid] node.AggregateObject(other) -def connect_fd(testbed_instance, fdnd, cross_data): +def connect_fd(testbed_instance, fdnd_guid, cross_data): + fdnd = testbed_instance._elements[fdnd_guid] address = fdnd.socket_address fdnd.set_attribute_value("LinuxSocketAddress", address) diff --git a/src/nepi/testbeds/planetlab/execute.py b/src/nepi/testbeds/planetlab/execute.py index 38bea7b6..32405f53 100644 --- a/src/nepi/testbeds/planetlab/execute.py +++ b/src/nepi/testbeds/planetlab/execute.py @@ -3,6 +3,7 @@ from constants import TESTBED_ID from nepi.core import testbed_impl +from nepi.util.constants import TIME_NOW import os import time @@ -108,8 +109,8 @@ class TestbedController(testbed_impl.TestbedController): # cleanup del self._to_provision - def set(self, time, guid, name, value): - super(TestbedController, self).set(time, guid, name, value) + def set(self, guid, name, value, time = TIME_NOW): + super(TestbedController, self).set(guid, name, value, time) # TODO: take on account schedule time for the task element = self._elements[guid] if element: @@ -119,8 +120,8 @@ class TestbedController(testbed_impl.TestbedController): # invoke attribute refresh hook element.refresh() - def get(self, time, guid, name): - value = super(TestbedController, self).get(time, guid, name) + def get(self, guid, name, time = TIME_NOW): + value = super(TestbedController, self).get(guid, name, time) # TODO: take on account schedule time for the task factory_id = self._create[guid] factory = self._factories[factory_id] diff --git a/src/nepi/testbeds/planetlab/metadata_v01.py b/src/nepi/testbeds/planetlab/metadata_v01.py index 34022bc0..396c920c 100644 --- a/src/nepi/testbeds/planetlab/metadata_v01.py +++ b/src/nepi/testbeds/planetlab/metadata_v01.py @@ -78,24 +78,33 @@ def is_portlist(attribute, value): ### Connection functions #### -def connect_node_iface_node(testbed_instance, node, iface): +def connect_node_iface_node(testbed_instance, node_guid, iface_guid): + node = testbed_instance._elements[node_guid] + iface = testbed_instance._elements[iface_guid] iface.node = node -def connect_node_iface_inet(testbed_instance, iface, inet): +def connect_node_iface_inet(testbed_instance, iface_guid, inet_guid): + iface = testbed_instance._elements[iface_guid] iface.has_internet = True -def connect_tun_iface_node(testbed_instance, node, iface): +def connect_tun_iface_node(testbed_instance, node_guid, iface_guid): + node = testbed_instance._elements[node_guid] + iface = testbed_instance._elements[iface_guid] if not node.emulation: raise RuntimeError, "Use of TUN interfaces requires emulation" iface.node = node node.required_vsys.update(('fd_tuntap', 'vif_up')) -def connect_tun_iface_peer(proto, testbed_instance, iface, peer_iface): +def connect_tun_iface_peer(proto, testbed_instance, iface_guid, peer_iface_guid): + iface = testbed_instance._elements[iface_guid] + peer_iface = testbed_instance._elements[peer_iface_guid] iface.peer_iface = peer_iface iface.peer_proto = \ iface.tun_proto = proto -def connect_dep(testbed_instance, node, app): +def connect_dep(testbed_instance, node_guid, app_guid): + node = testbed_instance._elements[node_guid] + app = testbed_instance._elements[app_guid] app.node = node if app.depends: @@ -106,7 +115,9 @@ def connect_dep(testbed_instance, node, app): if app.home_path and app.home_path not in node.pythonpath: node.pythonpath.append(app.home_path) -def connect_node_netpipe(testbed_instance, node, netpipe): +def connect_node_netpipe(testbed_instance, node_guid, netpipe_guid): + node = testbed_instance._elements[node_guid] + netpipe = testbed_instance._elements[netpipe_guid] if not node.emulation: raise RuntimeError, "Use of NetPipes requires emulation" netpipe.node = node diff --git a/src/nepi/util/proxy.py b/src/nepi/util/proxy.py index 9470ad5e..9b7b447f 100644 --- a/src/nepi/util/proxy.py +++ b/src/nepi/util/proxy.py @@ -52,6 +52,8 @@ DO_CONNECT_COMPL = 33 DO_CROSS_CONNECT_COMPL = 34 TESTBED_ID = 35 TESTBED_VERSION = 36 +EXPERIMENT_SET = 37 +EXPERIMENT_GET = 38 # PARAMETER TYPE STRING = 100 @@ -82,7 +84,7 @@ testbed_messages = dict({ CREATE_SET: "%d|%s" % (CREATE_SET, "%d|%s|%s|%d"), FACTORY_SET: "%d|%s" % (FACTORY_SET, "%d|%s|%s|%d"), CONNECT: "%d|%s" % (CONNECT, "%d|%s|%d|%s"), - CROSS_CONNECT: "%d|%s" % (CROSS_CONNECT, "%d|%s|%d|%d|%s|%s"), + CROSS_CONNECT: "%d|%s" % (CROSS_CONNECT, "%d|%s|%d|%d|%s|%s|%s"), ADD_TRACE: "%d|%s" % (ADD_TRACE, "%d|%s"), ADD_ADDRESS: "%d|%s" % (ADD_ADDRESS, "%d|%s|%d|%s"), ADD_ROUTE: "%d|%s" % (ADD_ROUTE, "%d|%s|%d|%s"), @@ -94,8 +96,10 @@ testbed_messages = dict({ DO_PRECONFIGURE: "%d" % DO_PRECONFIGURE, DO_CROSS_CONNECT_INIT: "%d|%s" % (DO_CROSS_CONNECT_INIT, "%s"), DO_CROSS_CONNECT_COMPL: "%d|%s" % (DO_CROSS_CONNECT_COMPL, "%s"), - GET: "%d|%s" % (GET, "%s|%d|%s"), - SET: "%d|%s" % (SET, "%s|%d|%s|%s|%d"), + GET: "%d|%s" % (GET, "%d|%s|%s"), + SET: "%d|%s" % (SET, "%d|%s|%s|%d|%s"), + EXPERIMENT_GET: "%d|%s" % (EXPERIMENT_GET, "%d|%d|%s|%s"), + EXPERIMENT_SET: "%d|%s" % (EXPERIMENT_SET, "%d|%d|%s|%s|%d|%s"), GET_ROUTE: "%d|%s" % (GET, "%d|%d|%s"), GET_ADDRESS: "%d|%s" % (GET, "%d|%d|%s"), ACTION: "%d|%s" % (ACTION, "%s|%d|%s"), @@ -148,6 +152,8 @@ instruction_text = dict({ FLOAT: "FLOAT", TESTBED_ID: "TESTBED_ID", TESTBED_VERSION: "TESTBED_VERSION", + EXPERIMENT_SET: "EXPERIMENT_SET", + EXPERIMENT_GET: "EXPERIMENT_GET", }) def get_type(value): @@ -506,11 +512,13 @@ class TestbedControllerServer(server.Server): cross_guid = int(params[3]) connector_type_name = params[4] cross_guid = int(params[5]) - cross_testbed_id = params[6] - cross_factory_id = params[7] - cross_connector_type_name = params[8] + cross_testbed_guid = int(params[6]) + cross_testbed_id = params[7] + cross_factory_id = params[8] + cross_connector_type_name = params[9] self._testbed.defer_cross_connect(guid, connector_type_name, cross_guid, - cross_testbed_id, cross_factory_id, cross_connector_type_name) + cross_testbed_guid, cross_testbed_id, cross_factory_id, + cross_connector_type_name) return "%d|%s" % (OK, "") def defer_add_trace(self, params): @@ -573,21 +581,21 @@ class TestbedControllerServer(server.Server): return "%d|%s" % (OK, "") def get(self, params): - time = params[1] - guid = int(param[2]) - name = base64.b64decode(params[3]) - value = self._testbed.get(time, guid, name) + guid = int(param[1]) + name = base64.b64decode(params[2]) + value = self._testbed.get(guid, name, time) + time = params[3] result = base64.b64encode(str(value)) return "%d|%s" % (OK, result) def set(self, params): - time = params[1] - guid = int(params[2]) - name = base64.b64decode(params[3]) - value = base64.b64decode(params[4]) - type = int(params[3]) + guid = int(params[1]) + name = base64.b64decode(params[2]) + value = base64.b64decode(params[3]) + type = int(params[2]) + time = params[4] value = set_type(type, value) - self._testbed.set(time, guid, name, value) + self._testbed.set(guid, name, value, time) return "%d|%s" % (OK, "") def get_address(self, params): @@ -656,6 +664,10 @@ class ExperimentControllerServer(server.Server): reply = self.trace(params) elif instruction == FINISHED: reply = self.is_finished(params) + elif instruction == EXPERIMENT_GET: + reply = self.get(params) + elif instruction == EXPERIMENT_SET: + reply = self.set(params) elif instruction == START: reply = self.start(params) elif instruction == STOP: @@ -719,6 +731,26 @@ class ExperimentControllerServer(server.Server): result = base64.b64encode(str(status)) return "%d|%s" % (OK, result) + def get(self, params): + testbed_guid = int(param[1]) + guid = int(params[2]) + name = base64.b64decode(params[3]) + value = self._controller.get(testbed_guid, guid, name, time) + time = params[4] + result = base64.b64encode(str(value)) + return "%d|%s" % (OK, result) + + def set(self, params): + testbed_guid = int(params[1]) + guid = int(params[2]) + name = base64.b64decode(params[3]) + value = base64.b64decode(params[4]) + type = int(params[3]) + time = params[5] + value = set_type(type, value) + self._controller.set(testbed_guid, guid, name, value, time) + return "%d|%s" % (OK, "") + def start(self, params): self._controller.start() return "%d|%s" % (OK, "") @@ -873,9 +905,10 @@ class TestbedControllerProxy(object): raise RuntimeError(text) def defer_cross_connect(self, guid, connector_type_name, cross_guid, - cross_testbed_id, cross_factory_id, cross_connector_type_name): + cross_testbed_guid, cross_testbed_id, cross_factory_id, + cross_connector_type_name): msg = testbed_messages[CROSS_CONNECT] - msg = msg % (guid, connector_type_name, cross_guid, + msg = msg % (guid, connector_type_name, cross_guid, cross_testbed_guid, cross_testbed_id, cross_factory_id, cross_connector_type_name) self._client.send_msg(msg) reply = self._client.read_reply() @@ -1024,13 +1057,13 @@ class TestbedControllerProxy(object): if code == ERROR: raise RuntimeError(text) - def set(self, time, guid, name, value): + def set(self, guid, name, value, time = TIME_NOW): msg = testbed_messages[SET] type = get_type(value) # avoid having "|" in this parameters name = base64.b64encode(name) value = base64.b64encode(str(value)) - msg = msg % (time, guid, name, value, type) + msg = msg % (guid, name, value, type, time) self._client.send_msg(msg) reply = self._client.read_reply() result = reply.split("|") @@ -1039,11 +1072,11 @@ class TestbedControllerProxy(object): if code == ERROR: raise RuntimeError(text) - def get(self, time, guid, name): + def get(self, guid, name, time = TIME_NOW): msg = testbed_messages[GET] # avoid having "|" in this parameters name = base64.b64encode(name) - msg = msg % (time, guid, name) + msg = msg % (guid, name, time) self._client.send_msg(msg) reply = self._client.read_reply() result = reply.split("|") @@ -1259,6 +1292,35 @@ class ExperimentControllerProxy(object): raise RuntimeError(text) return text == "True" + def set(self, testbed_guid, guid, name, value, time = TIME_NOW): + msg = testbed_messages[EXPERIMENT_SET] + type = get_type(value) + # avoid having "|" in this parameters + name = base64.b64encode(name) + value = base64.b64encode(str(value)) + msg = msg % (testbed_guid, guid, name, value, type, time) + self._client.send_msg(msg) + reply = self._client.read_reply() + result = reply.split("|") + code = int(result[0]) + text = base64.b64decode(result[1]) + if code == ERROR: + raise RuntimeError(text) + + def get(self, testbed_guid, guid, name, time = TIME_NOW): + msg = testbed_messages[EXPERIMENT_GET] + # avoid having "|" in this parameters + name = base64.b64encode(name) + msg = msg % (testbed_guid, guid, name, time) + self._client.send_msg(msg) + reply = self._client.read_reply() + result = reply.split("|") + code = int(result[0]) + text = base64.b64decode(result[1]) + if code == ERROR: + raise RuntimeError(text) + return text + def shutdown(self): msg = controller_messages[SHUTDOWN] self._client.send_msg(msg) diff --git a/test/core/execute.py b/test/core/execute.py index 2bb15b47..e5c609ff 100755 --- a/test/core/execute.py +++ b/test/core/execute.py @@ -38,7 +38,7 @@ class ExecuteTestCase(unittest.TestCase): instance.do_configure() instance.start() attr_list = instance.get_attribute_list(5) - self.assertEquals(attr_list, ["test", "fake", "label"]) + self.assertEquals(attr_list, ["test", "fake", "cross", "label"]) while instance.status(7) != STATUS_FINISHED: time.sleep(0.5) app_result = instance.trace(7, "fake") diff --git a/test/core/integration.py b/test/core/integration.py index 220d7e94..326275b3 100755 --- a/test/core/integration.py +++ b/test/core/integration.py @@ -6,6 +6,8 @@ from nepi.util.constants import STATUS_FINISHED from nepi.util import proxy import mock import mock.metadata_v01 +import mock2 +import mock2.metadata_v01 import os import shutil import sys @@ -18,15 +20,14 @@ class ExecuteTestCase(unittest.TestCase): def setUp(self): sys.modules["nepi.testbeds.mock.metadata_v01"] = mock.metadata_v01 sys.modules["nepi.testbeds.mock"] = mock + sys.modules["nepi.testbeds.mock2.metadata_v01"] = mock2.metadata_v01 + sys.modules["nepi.testbeds.mock2"] = mock2 self.root_dir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.root_dir) - - def make_test_experiment(self): - exp_desc = ExperimentDescription() - testbed_version = "01" - testbed_id = "mock" + + def make_testbed(self, exp_desc, testbed_id, testbed_version): provider = FactoriesProvider(testbed_id, testbed_version) desc = exp_desc.add_testbed_description(provider) desc.set_attribute_value("fake", True) @@ -45,6 +46,39 @@ class ExecuteTestCase(unittest.TestCase): return exp_desc, desc, app, node1, node2, iface1, iface2 + def make_test_experiment(self): + exp_desc = ExperimentDescription() + testbed_version = "01" + testbed_id = "mock" + return self.make_testbed(exp_desc, testbed_id, testbed_version) + + def make_cross_test_experiment(self): + exp_desc = ExperimentDescription() + testbed_version = "01" + testbed_id1 = "mock" + testbed_id2 = "mock2" + exp_desc, desc1, app1, node11, node12, iface11, iface12 = \ + self.make_testbed(exp_desc, testbed_id1, testbed_version) + exp_desc, desc2, app2, node21, node22, iface21, iface22 = \ + self.make_testbed(exp_desc, testbed_id2, testbed_version) + iface12.connector("cross").connect(iface21.connector("cross")) + + return exp_desc, desc1, desc2, iface12, iface21 + + def test_single_process_cross_integration(self): + exp_desc, desc1, desc2, iface12, iface21 = \ + self.make_cross_test_experiment() + xml = exp_desc.to_xml() + access_config = None + controller = proxy.create_controller(xml, access_config) + + controller.start() + cross1 = controller.get(desc1.guid, iface12.guid, "cross") + cross2 = controller.get(desc2.guid, iface21.guid, "cross") + self.assertTrue(cross1 == cross2 == True) + controller.stop() + controller.shutdown() + def test_single_process_integration(self): exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment() xml = exp_desc.to_xml() diff --git a/test/lib/mock/metadata_v01.py b/test/lib/mock/metadata_v01.py index 67a0eac9..d12e9ae9 100644 --- a/test/lib/mock/metadata_v01.py +++ b/test/lib/mock/metadata_v01.py @@ -13,19 +13,20 @@ APP = "Application" ### Connection functions #### +def connect_cross(testbed_instance, guid, cross_data): + connected = True + testbed_instance.set(guid, "cross", True) + ### Creation functions ### def create_node(testbed_instance, guid): - element = NODE - testbed_instance.elements[guid] = element + testbed_instance.elements[guid] = NODE def create_iface(testbed_instance, guid): - element = IFACE - testbed_instance.elements[guid] = element + testbed_instance.elements[guid] = IFACE def create_application(testbed_instance, guid): - element = APP - testbed_instance.elements[guid] = element + testbed_instance.elements[guid] = APP ### Start/Stop functions ### @@ -61,28 +62,36 @@ connector_types = dict({ "max": 1, "min": 0 }), + "cross": dict({ + "help": "Connector to an Interface in other testbed", + "name": "cross", + "max": 1, + "min": 0 + }), }) connections = [ dict({ "from": (TESTBED_ID, NODE, "devs"), "to": (TESTBED_ID, IFACE, "node"), - "code": None, "can_cross": False }), dict({ "from": (TESTBED_ID, IFACE, "iface"), "to": (TESTBED_ID, IFACE, "iface"), - "code": None, "can_cross": False }), dict({ "from": (TESTBED_ID, NODE, "apps"), "to": (TESTBED_ID, APP, "node"), - "code": None, "can_cross": False - }) -] + }), + dict({ + "from": (TESTBED_ID, IFACE, "cross"), + "to": ("mock2", IFACE, "cross"), + "init_code": connect_cross, + "can_cross": True, + })] attributes = dict({ "fake": dict({ @@ -90,8 +99,6 @@ attributes = dict({ "help": "fake attribute", "type": Attribute.BOOL, "value": False, - "range": None, - "allowed": None, "validation_function": validation.is_bool }), "test": dict({ @@ -100,6 +107,13 @@ attributes = dict({ "type": Attribute.STRING, "validation_function": validation.is_string }), + "cross": dict({ + "name": "cross", + "help": "Attribute that indicates if cross connection was performed", + "type": Attribute.BOOL, + "value": False, + "validation_function": validation.is_bool + }) }) traces = dict({ @@ -131,8 +145,8 @@ factories_info = dict({ "status_function": None, "allow_addresses": True, "factory_attributes": ["fake"], - "box_attributes": ["fake","test"], - "connector_types": ["node", "iface"] + "box_attributes": ["fake", "test", "cross"], + "connector_types": ["node", "iface", "cross"] }), APP: dict({ "help": "Fake application", @@ -141,7 +155,7 @@ factories_info = dict({ "start_function": None, "stop_function": None, "status_function": status_application, - "box_attributes": ["fake","test"], + "box_attributes": ["fake", "test"], "connector_types": ["node"], "traces": ["fake"] }), diff --git a/test/lib/mock2/__init__.py b/test/lib/mock2/__init__.py new file mode 100644 index 00000000..cf042520 --- /dev/null +++ b/test/lib/mock2/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from constants import TESTBED_ID +from execute import TestbedController + diff --git a/test/lib/mock2/constants.py b/test/lib/mock2/constants.py new file mode 100644 index 00000000..4a1547bf --- /dev/null +++ b/test/lib/mock2/constants.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +TESTBED_ID = "mock2" + diff --git a/test/lib/mock2/execute.py b/test/lib/mock2/execute.py new file mode 100644 index 00000000..762b110f --- /dev/null +++ b/test/lib/mock2/execute.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from constants import TESTBED_ID +from nepi.core import testbed_impl + +class TestbedController(testbed_impl.TestbedController): + def __init__(self, testbed_version): + super(TestbedController, self).__init__(TESTBED_ID, testbed_version) + + def do_configure(self): + pass + + def action(self, time, guid, action): + raise NotImplementedError + + def trace(self, guid, trace_id, attribute='value'): + if attribute == 'value': + return """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data. + +--- 10.0.0.2 ping statistics --- +1 packets transmitted, 1 received, 0% packet loss, time 0ms +""" + elif attribute == 'path': + return '' + else: + return None + + def shutdown(self): + pass + diff --git a/test/lib/mock2/metadata_v01.py b/test/lib/mock2/metadata_v01.py new file mode 100644 index 00000000..672f9ec1 --- /dev/null +++ b/test/lib/mock2/metadata_v01.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from constants import TESTBED_ID +from nepi.core import metadata +from nepi.core.attributes import Attribute +from nepi.util import validation +from nepi.util.constants import STATUS_FINISHED + +NODE = "Node" +IFACE = "Interface" +APP = "Application" + +### Connection functions #### + +def connect_cross(testbed_instance, guid, cross_data): + connected = cross_data["cross"] + testbed_instance.set(guid, "cross", connected) + +### Creation functions ### + +def create_node(testbed_instance, guid): + testbed_instance.elements[guid] = NODE + +def create_iface(testbed_instance, guid): + testbed_instance.elements[guid] = IFACE + +def create_application(testbed_instance, guid): + testbed_instance.elements[guid] = APP + +### Start/Stop functions ### + +### Status functions ### + +def status_application(testbed_instance, guid): + return STATUS_FINISHED + +### Factory information ### + +connector_types = dict({ + "apps": dict({ + "help": "Connector from node to applications", + "name": "apps", + "max": -1, + "min": 0 + }), + "devs": dict({ + "help": "Connector from node to network interfaces", + "name": "devs", + "max": -1, + "min": 0 + }), + "node": dict({ + "help": "Connector to a Node", + "name": "node", + "max": 1, + "min": 1 + }), + "iface": dict({ + "help": "Connector to a Interface", + "name": "iface", + "max": 1, + "min": 0 + }), + "cross": dict({ + "help": "Connector to an Interface in other testbed", + "name": "cross", + "max": 1, + "min": 0 + }), + }) + +connections = [ + dict({ + "from": (TESTBED_ID, NODE, "devs"), + "to": (TESTBED_ID, IFACE, "node"), + "can_cross": False + }), + dict({ + "from": (TESTBED_ID, IFACE, "iface"), + "to": (TESTBED_ID, IFACE, "iface"), + "can_cross": False + }), + dict({ + "from": (TESTBED_ID, NODE, "apps"), + "to": (TESTBED_ID, APP, "node"), + "can_cross": False + }), + dict({ + "from": (TESTBED_ID, IFACE, "cross"), + "to": ("mock", IFACE, "cross"), + "compl_code": connect_cross, + "can_cross": True, + })] + +attributes = dict({ + "fake": dict({ + "name": "fake", + "help": "fake attribute", + "type": Attribute.BOOL, + "value": False, + "validation_function": validation.is_bool + }), + "test": dict({ + "name": "test", + "help": "test attribute", + "type": Attribute.STRING, + "validation_function": validation.is_string + }), + "cross": dict({ + "name": "cross", + "help": "Attribute that indicates if cross connection was performed", + "type": Attribute.BOOL, + "value": False, + "validation_function": validation.is_bool + }) + }) + +traces = dict({ + "fake": dict({ + "name": "fake", + "help": "fake trace" + }), + }) + +factories_order = [ NODE, IFACE, APP ] + +factories_info = dict({ + NODE: dict({ + "help": "Fake node", + "category": "topology", + "create_function": create_node, + "start_function": None, + "stop_function": None, + "status_function": None, + "box_attributes": ["fake","test"], + "connector_types": ["devs", "apps"] + }), + IFACE: dict({ + "help": "Fake iface", + "category": "devices", + "create_function": create_iface, + "start_function": None, + "stop_function": None, + "status_function": None, + "allow_addresses": True, + "factory_attributes": ["fake"], + "box_attributes": ["fake", "test", "cross"], + "connector_types": ["node", "iface", "cross"] + }), + APP: dict({ + "help": "Fake application", + "category": "applications", + "create_function": create_application, + "start_function": None, + "stop_function": None, + "status_function": status_application, + "box_attributes": ["fake", "test"], + "connector_types": ["node"], + "traces": ["fake"] + }), +}) + +testbed_attributes = dict({ + "fake": dict({ + "name": "fake", + "help": "fake attribute", + "type": Attribute.BOOL, + "value": False, + "range": None, + "allowed": None, + "validation_function": validation.is_bool + }), + }) + +class VersionedMetadataInfo(metadata.VersionedMetadataInfo): + @property + def connector_types(self): + return connector_types + + @property + def connections(self): + return connections + + @property + def attributes(self): + return attributes + + @property + def traces(self): + return traces + + @property + def create_order(self): + return factories_order + + @property + def configure_order(self): + return factories_order + + @property + def factories_info(self): + return factories_info + + @property + def testbed_attributes(self): + return testbed_attributes + -- 2.47.0