mock cross_connect test added to test/core/integration.py
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Sun, 1 May 2011 20:36:44 +0000 (22:36 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Sun, 1 May 2011 20:36:44 +0000 (22:36 +0200)
16 files changed:
src/nepi/core/execute.py
src/nepi/core/testbed_impl.py
src/nepi/testbeds/netns/execute.py
src/nepi/testbeds/netns/metadata_v01.py
src/nepi/testbeds/ns3/execute.py
src/nepi/testbeds/ns3/metadata_v3_9_RC3.py
src/nepi/testbeds/planetlab/execute.py
src/nepi/testbeds/planetlab/metadata_v01.py
src/nepi/util/proxy.py
test/core/execute.py
test/core/integration.py
test/lib/mock/metadata_v01.py
test/lib/mock2/__init__.py [new file with mode: 0644]
test/lib/mock2/constants.py [new file with mode: 0644]
test/lib/mock2/execute.py [new file with mode: 0644]
test/lib/mock2/metadata_v01.py [new file with mode: 0644]

index f64368c..ca3199b 100644 (file)
@@ -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
     
index 37d53eb..8966cce 100644 (file)
@@ -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]:
index cba37f0..67dee91 100644 (file)
@@ -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]
index 526158a..2af898d 100644 (file)
@@ -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)
index 0424793..84b8f0f 100644 (file)
@@ -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]
index 59b7413..57cbf66 100644 (file)
@@ -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)
 
index 38bea7b..32405f5 100644 (file)
@@ -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]
index 34022bc..396c920 100644 (file)
@@ -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
index 9470ad5..9b7b447 100644 (file)
@@ -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)
index 2bb15b4..e5c609f 100755 (executable)
@@ -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")
index 220d7e9..326275b 100755 (executable)
@@ -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()
index 67a0eac..d12e9ae 100644 (file)
@@ -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 (file)
index 0000000..cf04252
--- /dev/null
@@ -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 (file)
index 0000000..4a1547b
--- /dev/null
@@ -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 (file)
index 0000000..762b110
--- /dev/null
@@ -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 '<test>'
+        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 (file)
index 0000000..672f9ec
--- /dev/null
@@ -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
+