initial changes to support cross_connection in two stages.
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Thu, 28 Apr 2011 17:10:07 +0000 (19:10 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Thu, 28 Apr 2011 17:10:07 +0000 (19:10 +0200)
13 files changed:
src/nepi/core/attributes.py
src/nepi/core/execute.py
src/nepi/core/metadata.py
src/nepi/core/testbed_impl.py
src/nepi/testbeds/netns/metadata_v01.py
src/nepi/testbeds/ns3/metadata_v3_9_RC3.py
src/nepi/testbeds/planetlab/metadata_v01.py
src/nepi/util/proxy.py
test/core/execute.py
test/core/integration.py
test/testbeds/netns/execute.py
test/testbeds/ns3/execute.py
test/testbeds/ns3/execute2.py

index 3dd3da4..b6bf913 100644 (file)
@@ -134,7 +134,7 @@ class AttributesMap(object):
         return self._attributes.values()
 
     @property
-    def attributes_name(self):
+    def attributes_list(self):
         return self._attributes.keys()
 
     def set_attribute_value(self, name, value):
index 2fa16c2..cbc8f18 100644 (file)
@@ -31,22 +31,24 @@ class ConnectorType(ConnectorTypeBase):
         self._from_connections = dict()
         self._to_connections = dict()
 
-    def add_from_connection(self, testbed_id, factory_id, name, can_cross, code):
+    def add_from_connection(self, testbed_id, factory_id, name, can_cross, 
+            init_code, compl_code):
         type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        self._from_connections[type_id] = (can_cross, code)
+        self._from_connections[type_id] = (can_cross, init_code, compl_code)
 
-    def add_to_connection(self, testbed_id, factory_id, name, can_cross, code):
+    def add_to_connection(self, testbed_id, factory_id, name, can_cross, 
+            init_code, compl_code):
         type_id = self.make_connector_type_id(testbed_id, factory_id, name)
-        self._to_connections[type_id] = (can_cross, code)
+        self._to_connections[type_id] = (can_cross, init_code, compl_code)
 
     def can_connect(self, testbed_id, factory_id, name, count, 
             must_cross = False):
         connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
         for lookup_type_id in self._type_resolution_order(connector_type_id):
             if lookup_type_id in self._from_connections:
-                (can_cross, code) = self._from_connections[lookup_type_id]
+                (can_cross, init_code, compl_code) = self._from_connections[lookup_type_id]
             elif lookup_type_id in self._to_connections:
-                (can_cross, code) = self._to_connections[lookup_type_id]
+                (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
             else:
                 # keey trying
                 continue
@@ -54,17 +56,21 @@ class ConnectorType(ConnectorTypeBase):
         else:
             return False
 
-    def code_to_connect(self, testbed_id, factory_id, name):
+    def _connect_to_code(self, testbed_id, factory_id, name):
         connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
         for lookup_type_id in self._type_resolution_order(connector_type_id):
             if lookup_type_id in self._to_connections:
-                (can_cross, code) = self._to_connections[lookup_type_id]
-                return code
+                (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
+                return (init_code, compl_code)
         else:
-            return False
+            return (False, False)
+    
+    def connect_to_init_code(self, testbed_id, factory_id, name):
+        return self._connect_to_code(testbed_id, factory_id, name)[0]
+
+    def connect_to_compl_code(self, testbed_id, factory_id, name):
+        return self._connect_to_code(testbed_id, factory_id, name)[1]
 
-# TODO: create_function, start_function, stop_function, status_function 
-# need a definition!
 class Factory(AttributesMap):
     def __init__(self, factory_id, create_function, start_function, 
             stop_function, status_function, 
@@ -214,10 +220,17 @@ class TestbedController(object):
         """
         raise NotImplementedError
 
-    def do_connect(self):
+    def do_connect_init(self):
+        """
+        After do_connect_init all internal connections between testbed elements
+        are initiated
+        """
+        raise NotImplementedError
+
+    def do_connect_compl(self):
         """
         After do_connect all internal connections between testbed elements
-        are done
+        are completed
         """
         raise NotImplementedError
 
@@ -225,10 +238,17 @@ class TestbedController(object):
         """After do_configure elements are configured"""
         raise NotImplementedError
 
-    def do_cross_connect(self):
+    def do_cross_connect_init(self, cross_data):
         """
-        After do_cross_connect all external connections between different testbed 
-        elements are done
+        After do_cross_connect_init initiation of all external connections 
+        between different testbed elements is performed
+        """
+        raise NotImplementedError
+
+    def do_cross_connect_compl(self, cross_data):
+        """
+        After do_cross_connect_compl completion of all external connections 
+        between different testbed elements is performed
         """
         raise NotImplementedError
 
@@ -264,6 +284,9 @@ class TestbedController(object):
         """
         raise NotImplementedError
 
+    def get_attribute_list(self, guid):
+        raise NotImplementedError
+
     def action(self, time, guid, action):
         raise NotImplementedError
 
@@ -282,7 +305,7 @@ class ExperimentController(object):
         self._testbeds = dict()
         self._access_config = dict()
         self._netrefs = dict()
-        self._crossdata = dict()
+        self._cross_data = dict()
         self._root_dir = root_dir
 
         self.persist_experiment_xml()
@@ -324,11 +347,18 @@ class ExperimentController(object):
         
         # perform create-connect in parallel, wait
         # (internal connections only)
-        self._parallel([lambda : (testbed.do_create(), 
-                                  testbed.do_connect(),
-                                  testbed.do_preconfigure())
+        self._parallel([lambda : testbed.do_create()
                         for testbed in self._testbeds.itervalues()])
-        
+
+        self._parallel([lambda : testbed.do_connect_init()
+                        for testbed in self._testbeds.itervalues()])
+
+        self._parallel([lambda : testbed.do_connect_compl()
+                        for testbed in self._testbeds.itervalues()])
+
+        self._parallel([lambda : testbed.do_preconfigure()
+                        for testbed in self._testbeds.itervalues()])
+
         # resolve netrefs
         self.do_netrefs(fail_if_undefined=True)
         
@@ -338,9 +368,13 @@ class ExperimentController(object):
                         for testbed in self._testbeds.itervalues()])
 
         # cross-connect (cannot be done in parallel)
-        for testbed in self._testbeds.values():
-            testbed.do_cross_connect()
-        
+        for guid, testbed in self._testbeds.iteritems():
+            cross_data = self._get_cross_data(guid)
+            testbed.do_cross_connect_init(cross_data)
+        for guid, testbed in self._testbeds.iteritems():
+            cross_data = self._get_cross_data(guid)
+            testbed.do_cross_connect_compl(cross_data)
+       
         # start experiment (parallel start on all testbeds)
         self._parallel([testbed.start
                         for testbed in self._testbeds.itervalues()])
@@ -354,7 +388,7 @@ class ExperimentController(object):
         for testbed_guid, testbed_config in self._access_config.iteritems():
             testbed_guid = str(testbed_guid)
             conf.add_section(testbed_guid)
-            for attr in testbed_config.attributes_name:
+            for attr in testbed_config.attributes_list:
                 if attr not in TRANSIENT:
                     conf.set(testbed_guid, attr, 
                         testbed_config.get_attribute_value(attr))
@@ -381,7 +415,7 @@ class ExperimentController(object):
                 
             testbed_guid = str(testbed_guid)
             conf.add_section(testbed_guid)
-            for attr in testbed_config.attributes_name:
+            for attr in testbed_config.attributes_list:
                 if attr not in TRANSIENT:
                     getter = getattr(conf, TYPEMAP.get(
                         testbed_config.get_attribute_type(attr),
@@ -562,23 +596,57 @@ class ExperimentController(object):
         for guid in element_guids: 
             (testbed_guid, factory_id) = data.get_box_data(guid)
             testbed = self._testbeds[testbed_guid]
-            for (connector_type_name, other_guid, other_connector_type_name) \
+            for (connector_type_name, cross_guid, cross_connector_type_name) \
                     in data.get_connection_data(guid):
                 (testbed_guid, factory_id) = data.get_box_data(guid)
-                (other_testbed_guid, other_factory_id) = data.get_box_data(
-                        other_guid)
-                if testbed_guid == other_testbed_guid:
-                    testbed.defer_connect(guid, connector_type_name, other_guid, 
-                        other_connector_type_name)
-                else:
-                    testbed.defer_cross_connect(guid, connector_type_name, other_guid, 
-                        other_testbed_id, other_factory_id, other_connector_type_name)
+                (cross_testbed_guid, cross_factory_id) = data.get_box_data(
+                        cross_guid)
+                if testbed_guid == cross_testbed_guid:
+                    testbed.defer_connect(guid, connector_type_name, 
+                            cross_guid, cross_connector_type_name)
+                else: 
+                    testbed.defer_cross_connect(guid, connector_type_name, cross_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,
+                            cross_guid)
             for trace_id in data.get_trace_data(guid):
                 testbed.defer_add_trace(guid, trace_id)
             for (autoconf, address, netprefix, broadcast) in \
                     data.get_address_data(guid):
                 if address != None:
-                    testbed.defer_add_address(guid, address, netprefix, broadcast)
+                    testbed.defer_add_address(guid, address, netprefix, 
+                            broadcast)
             for (destination, netprefix, nexthop) in data.get_route_data(guid):
                 testbed.defer_add_route(guid, destination, netprefix, nexthop)
-
+                
+    def _add_crossdata(self, testbed_guid, guid, cross_testbed_guid, cross_guid):
+        if testbed_guid not in self._crossdata:
+            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)
+
+    def _get_cross_data(self, testbed_guid):
+        cross_data = dict()
+        if not testbed_guid in self._cross_data:
+            return cross_data
+        for cross_testbed_guid, guid_list in self._cross_data[testbed_guid]:
+            cross_data[cross_testbed_guid] = dict()
+            cross_testbed = self._testbeds[cross_testbed_guid]
+            for cross_guid in guid_list:
+                cross_data_guid = dict()
+                cross_data[cross_testbed_guid][cross_guid] = cross_data_guid
+                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)
+                    cross_data_guid[attr_name] = attr_value
+        return cross_data
+    
index 93a31c7..7414b61 100644 (file)
@@ -24,7 +24,9 @@ class VersionedMetadataInfo(object):
         dict({
             "from": (testbed_id1, factory_id1, connector_type_name1),
             "to": (testbed_id2, factory_id2, connector_type_name2),
-            "code": connection function to invoke upon connection creation
+            "init_code": connection function to invoke for connection initiation
+            "compl_code": connection function to invoke for connection 
+                completion
             "can_cross": whether the connection can be done across testbed 
                             instances
          }),
@@ -344,13 +346,18 @@ class Metadata(object):
                 from_ = connection["from"]
                 to = connection["to"]
                 can_cross = connection["can_cross"]
-                code = connection["code"]
+                init_code = connection["init_code"] \
+                        if "init_code" in connection else None
+                compl_code = connection["compl_code"] \
+                        if "compl_code" in connection else None
                 if from_ not in from_connections:
                     from_connections[from_] = list()
                 if to not in to_connections:
                     to_connections[to] = list()
-                from_connections[from_].append((to, can_cross, code))
-                to_connections[to].append((from_, can_cross, code))
+                from_connections[from_].append((to, can_cross, init_code, 
+                    compl_code))
+                to_connections[to].append((from_, can_cross, init_code,
+                    compl_code))
             for connector_id in info["connector_types"]:
                 connector_type_info = self._metadata.connector_types[
                         connector_id]
@@ -363,15 +370,18 @@ class Metadata(object):
                         max, min)
                 connector_key = (testbed_id, factory_id, name)
                 if connector_key in to_connections:
-                    for (from_, can_cross, code) in to_connections[connector_key]:
+                    for (from_, can_cross, init_code, compl_code) in \
+                            to_connections[connector_key]:
                         (testbed_id_from, factory_id_from, name_from) = from_
                         connector_type.add_from_connection(testbed_id_from, 
-                                factory_id_from, name_from, can_cross, code)
+                                factory_id_from, name_from, can_cross, 
+                                init_code, compl_code)
                 if connector_key in from_connections:
-                    for (to, can_cross, code) in from_connections[(testbed_id, 
-                            factory_id, name)]:
+                    for (to, can_cross, init_code, compl_code) in \
+                            from_connections[(testbed_id, factory_id, name)]:
                         (testbed_id_to, factory_id_to, name_to) = to
                         connector_type.add_to_connection(testbed_id_to, 
-                                factory_id_to, name_to, can_cross, code)
+                                factory_id_to, name_to, can_cross, init_code,
+                                compl_code)
                 factory.add_connector_type(connector_type)
  
index 819fc14..78cbb1f 100644 (file)
@@ -192,7 +192,7 @@ class TestbedController(execute.TestbedController):
                 for name, value in parameters.iteritems():
                     self.set(TIME_NOW, guid, name, value)
 
-    def do_connect(self):
+    def _do_connect(self, init = True):
         for guid1, connections in self._connect.iteritems():
             element1 = self._elements[guid1]
             factory_id1 = self._create[guid1]
@@ -204,12 +204,23 @@ class TestbedController(execute.TestbedController):
                     factory_id2 = self._create[guid2]
                     # Connections are executed in a "From -> To" direction only
                     # This explicitly ignores the "To -> From" (mirror) 
-                    # connections of every connection pair. 
-                    code_to_connect = connector_type1.code_to_connect(
-                            self._testbed_id, factory_id2, 
-                            connector_type_name2)
-                    if code_to_connect:
-                        code_to_connect(self, element1, element2)
+                    # connections of every connection pair.
+                    if init:
+                        connect_code = connector_type1.connect_to_init_code(
+                                self._testbed_id, factory_id2, 
+                                connector_type_name2)
+                    else:
+                        connect_code = connector_type1.connect_to_compl_code(
+                                self._testbed_id, factory_id2, 
+                                connector_type_name2)
+                    if connect_code:
+                        connect_code(self, element1, element2)
+
+    def do_connect_init(self):
+        self._do_connect()
+
+    def do_connect_compl(self):
+        self._do_connect(init = False)
 
     def do_preconfigure(self):
         guids = dict()
@@ -247,7 +258,7 @@ class TestbedController(execute.TestbedController):
             for guid in guids[factory_id]:
                 factory.configure_function(self, guid)
 
-    def do_cross_connect(self):
+    def _do_cross_connect(self, cross_data, init = True):
         for guid, cross_connections in self._cross_connect.iteritems():
             element = self._elements[guid]
             factory_id = self._create[guid]
@@ -257,11 +268,23 @@ class TestbedController(execute.TestbedController):
                 connector_type = factory.connector_type(connector_type_name)
                 (cross_testbed_id, cross_factory_id, 
                         cross_connector_type_name) = cross_connection
-                code_to_connect = connector_type.code_to_connect(
-                    cross_guid, cross_testbed_id, cross_factory_id, 
-                    cross_conector_type_name)
-                if code_to_connect:
-                    code_to_connect(element, cross_guid)       
+                if init:
+                    connect_code = connector_type.connect_to_init_code(
+                        cross_testbed_id, cross_factory_id, 
+                        cross_conector_type_name)
+                else:
+                    connect_code = connector_type.connect_to_compl_code(
+                        cross_testbed_id, cross_factory_id, 
+                        cross_conector_type_name)
+                if connect_code:
+                    cross_data_guid = cross_data[cross_testbed_id][cross_guid]
+                    connect_code(element, cross_guid, cross_data_guid)       
+
+    def do_cross_connect_init(self, cross_data):
+        self._do_cross_connect(cross_data)
+
+    def do_cross_connect_compl(self, cross_data):
+        self._do_cross_connect(cross_data, init = False)
 
     def set(self, time, guid, name, value):
         if not guid in self._create:
@@ -355,6 +378,11 @@ class TestbedController(execute.TestbedController):
         
         return addresses[index][attribute_index]
 
+    def get_attribute_list(self, guid):
+        factory_id = self._create[guid]
+        factory = self._factories[factory_id]
+        attribute_list = list()
+        return factory.box_attributes.attributes_list
 
     def start(self, time = TIME_NOW):
         for guid, factory_id in self._create.iteritems():
index 7b9cecb..472935c 100644 (file)
@@ -200,43 +200,38 @@ connections = [
     dict({
         "from": (TESTBED_ID, NODE, "devs"),
         "to":   (TESTBED_ID, P2PIFACE, "node"),
-        "code": None,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODE, "devs"),
         "to":   (TESTBED_ID, TAPIFACE, "node"),
-        "code": None,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODE, "devs"),
         "to":   (TESTBED_ID, NODEIFACE, "node"),
-        "code": None,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, P2PIFACE, "p2p"),
         "to":   (TESTBED_ID, P2PIFACE, "p2p"),
-        "code": None,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, TAPIFACE, "fd"),
         "to":   (NS3_TESTBED_ID, FDNETDEV, "fd"),
-        "code": connect_fd_local,
+        "compl_code": connect_fd_local,
         "can_cross": True
     }),
      dict({
         "from": (TESTBED_ID, SWITCH, "devs"),
         "to":   (TESTBED_ID, NODEIFACE, "switch"),
-        "code": connect_switch,
+        "init_code": connect_switch,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODE, "apps"),
         "to":   (TESTBED_ID, APPLICATION, "node"),
-        "code": None,
         "can_cross": False
     })
 ]
index 9d5cfab..3a3891c 100644 (file)
@@ -61,10 +61,6 @@ def connect_node_application(testbed_instance, node, application):
 def connect_node_other(tesbed_instance, node, other):
     node.AggregateObject(other)
 
-def connect_fd_tap(tesbed_instance, fd, tap):
-    print "CONNNECT TAP!!!"
-    # TODO!
-
 ### Connector information ###
 
 connector_types = dict({
@@ -188,271 +184,270 @@ connections = [
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::BridgeNetDevice", "node" ),
-            "code": connect_node_device,
+            "init_code": connect_node_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::CsmaNetDevice", "node" ),
-            "code": connect_node_device,
+            "init_code": connect_node_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::EmuNetDevice", "node" ),
-            "code": connect_node_device,
+            "init_code": connect_node_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::PointToPointNetDevice", "node" ),
-            "code": connect_node_device,
+            "init_code": connect_node_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::SimpleNetDevice", "node" ),
-            "code": connect_node_device,
+            "init_code": connect_node_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::FileDescriptorNetDevice", "node" ),
-            "code": connect_node_device,
+            "init_code": connect_node_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::Node", "devs" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "node" ),
-            "code": connect_node_device,   
+            "init_code": connect_node_device,   
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::DropTailQueue", "dev" ),
             "to":   ( "ns3", "ns3::CsmaNetDevice", "queue" ),
-            "code": connect_queue_device,
+            "init_code": connect_queue_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::DropTailQueue", "dev" ),
             "to":   ( "ns3", "ns3::EmuNetDevice", "queue" ),
-            "code": connect_queue_device,
+            "init_code": connect_queue_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::DropTailQueue", "dev" ),
             "to":   ( "ns3", "ns3::PointToPointNetDevice", "queue" ),
-            "code": connect_queue_device,
+            "init_code": connect_queue_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::ArfWifiManager", "dev" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
-            "code": connect_manager_device,
+            "init_code": connect_manager_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::ConstantRateWifiManager", "dev" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
-            "code": connect_manager_device,
+            "init_code": connect_manager_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::YansWifiPhy", "dev" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "phy" ),  
-            "code": connect_phy_device,
+            "init_code": connect_phy_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::QapWifiMac", "dev" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "mac" ),
-            "code": connect_mac_device,
+            "init_code": connect_mac_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::QstaWifiMac", "dev" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "mac" ),
-            "code": connect_mac_device,
+            "init_code": connect_mac_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::RateErrorModel", "dev" ),
             "to":   ( "ns3", "ns3::CsmaNetDevice", "err" ),
-            "code": connect_errormodel_device,
+            "init_code": connect_errormodel_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::RateErrorModel", "dev" ),
             "to":   ( "ns3", "ns3::PointToPointNetDevice", "err" ),
-            "code": connect_errormodel_device,
+            "init_code": connect_errormodel_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::ListErrorModel", "dev" ),
             "to":   ( "ns3", "ns3::CsmaNetDevice", "err" ),
-            "code": connect_errormodel_device,
+            "init_code": connect_errormodel_device,
             "can_cross": False
     }),
     dict({
             "from": ( "ns3", "ns3::ListErrorModel", "dev" ),
             "to":   ( "ns3", "ns3::PointToPointNetDevice", "err" ),
-            "code": connect_errormodel_device,
+            "init_code": connect_errormodel_device,
             "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::NistErrorRateModel", "phy" ),        
         "to":   ( "ns3", "ns3::YansWifiPhy", "err" ),
-        "code": connect_errormodel_phy,
+        "init_code": connect_errormodel_phy,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::CsmaChannel", "devs" ),
         "to":   ( "ns3", "ns3::CsmaNetDevice", "chan" ),
-        "code": connect_channel_device,
+        "init_code": connect_channel_device,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::PointToPointChannel", "dev2" ),
         "to":   ( "ns3", "ns3::PointToPointNetDevice", "chan" ),
-        "code": connect_channel_device,
+        "init_code": connect_channel_device,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::SimpleChannel", "devs" ),
         "to":   ( "ns3", "ns3::SimpleNetDevice", "chan" ),
-        "code": connect_simple_channel_device,
+        "init_code": connect_simple_channel_device,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::YansWifiChannel", "phys" ),
         "to":   ( "ns3", "ns3::YansWifiPhy", "chan" ),  
-        "code": connect_simple_channel_device,
+        "init_code": connect_simple_channel_device,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::LogDistancePropagationLossModel", "prev" ),
         "to":   ( "ns3", "ns3::YansWifiChannel", "loss" ),  
-        "code": connect_loss_channel,
+        "init_code": connect_loss_channel,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::LogDistancePropagationLossModel", "prev" ),
         "to":   ( "ns3", "ns3::LogDistancePropagationLossModel", "next" ),  
-        "code": connect_next_loss,
+        "init_code": connect_next_loss,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::ConstantSpeedPropagationDelayModel", "chan" ),
         "to":   ( "ns3", "ns3::YansWifiChannel", "delay" ),  
-        "code": connect_delay_channel,
+        "init_code": connect_delay_channel,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "apps" ),
         "to":   ( "ns3", "ns3::OnOffApplication", "node" ),
-        "code": connect_node_application,
+        "init_code": connect_node_application,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "apps" ),
         "to":   ( "ns3", "ns3::PacketSink", "node" ),
-        "code": connect_node_application,
+        "init_code": connect_node_application,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "apps" ),
         "to":   ( "ns3", "ns3::UdpEchoClient", "node" ),
-        "code": connect_node_application,
+        "init_code": connect_node_application,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "apps" ),
         "to":   ( "ns3", "ns3::UdpEchoServer", "node" ),
-        "code": connect_node_application,
+        "init_code": connect_node_application,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "apps" ),
         "to":   ( "ns3", "ns3::V4Ping", "node" ),
-        "code": connect_node_application,
+        "init_code": connect_node_application,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "protos" ),
         "to":   ( "ns3", "ns3::ArpL3Protocol", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "protos" ),
         "to":   ( "ns3", "ns3::Icmpv4L4Protocol", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "protos" ),
         "to":   ( "ns3", "ns3::Ipv4L3Protocol", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "protos" ),
         "to":   ( "ns3", "ns3::UdpL4Protocol", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "protos" ),
         "to":   ( "ns3", "ns3::TcpL4Protocol", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::ConstantAccelerationMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::ConstantPositionMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::ConstantVelocityMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::HierarchicalMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::RandomDirection2dMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::RandomWalk2dMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::Node", "mobility" ),
         "to":   ( "ns3", "ns3::RandomWaypointMobilityModel", "node" ),
-        "code": connect_node_other,
+        "init_code": connect_node_other,
         "can_cross": False
     }),
     dict({
         "from": ( "ns3", "ns3::FileDescriptorNetDevice", "fd" ),
         "to":   ( "netns", "TapNodeInterface", "fd" ),
-        "code": connect_fd_tap,
         "can_cross": False
     }),
 ]
index 7866741..b1d51c6 100644 (file)
@@ -338,43 +338,43 @@ connections = [
     dict({
         "from": (TESTBED_ID, NODE, "devs"),
         "to":   (TESTBED_ID, NODEIFACE, "node"),
-        "code": connect_node_iface_node,
+        "init_code": connect_node_iface_node,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODE, "devs"),
         "to":   (TESTBED_ID, TUNIFACE, "node"),
-        "code": connect_tun_iface_node,
+        "init_code": connect_tun_iface_node,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODEIFACE, "inet"),
         "to":   (TESTBED_ID, INTERNET, "devs"),
-        "code": connect_node_iface_inet,
+        "init_code": connect_node_iface_inet,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODE, "apps"),
         "to":   (TESTBED_ID, APPLICATION, "node"),
-        "code": connect_app,
+        "init_code": connect_app,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, NODE, "pipes"),
         "to":   (TESTBED_ID, NETPIPE, "node"),
-        "code": connect_node_netpipe,
+        "init_code": connect_node_netpipe,
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, TUNIFACE, "tcp"),
         "to":   (TESTBED_ID, TUNIFACE, "tcp"),
-        "code": functools.partial(connect_tun_iface_peer,"tcp"),
+        "init_code": functools.partial(connect_tun_iface_peer,"tcp"),
         "can_cross": False
     }),
     dict({
         "from": (TESTBED_ID, TUNIFACE, "udp"),
         "to":   (TESTBED_ID, TUNIFACE, "udp"),
-        "code": functools.partial(connect_tun_iface_peer,"udp"),
+        "init_code": functools.partial(connect_tun_iface_peer,"udp"),
         "can_cross": False
     }),
 ]
index b0c045d..0fdc47a 100644 (file)
@@ -6,6 +6,7 @@ from nepi.core.attributes import AttributesMap, Attribute
 from nepi.util import server, validation
 from nepi.util.constants import TIME_NOW
 import getpass
+import cPickle
 import sys
 import time
 import tempfile
@@ -34,9 +35,9 @@ ADD_ADDRESS = 16
 ADD_ROUTE   = 17
 DO_SETUP    = 18
 DO_CREATE   = 19
-DO_CONNECT  = 20
+DO_CONNECT_INIT = 20
 DO_CONFIGURE    = 21
-DO_CROSS_CONNECT    = 22
+DO_CROSS_CONNECT_INIT   = 22
 GET = 23
 SET = 24
 ACTION  = 25
@@ -46,6 +47,9 @@ GET_ROUTE = 28
 GET_ADDRESS = 29
 RECOVER = 30
 DO_PRECONFIGURE    = 31
+GET_ATTRIBUTE_LIST = 32
+DO_CONNECT_COMPL   = 33
+DO_CROSS_CONNECT_COMPL  = 34
 
 # PARAMETER TYPE
 STRING  =  100
@@ -82,10 +86,12 @@ testbed_messages = dict({
     ADD_ROUTE: "%d|%s" % (ADD_ROUTE, "%d|%s|%d|%s"),
     DO_SETUP:   "%d" % DO_SETUP,
     DO_CREATE:  "%d" % DO_CREATE,
-    DO_CONNECT: "%d" % DO_CONNECT,
-    DO_CONFIGURE:   "%d" % DO_CONFIGURE,
-    DO_PRECONFIGURE:   "%d" % DO_PRECONFIGURE,
-    DO_CROSS_CONNECT:   "%d" % DO_CROSS_CONNECT,
+    DO_CONNECT_INIT:    "%d" % DO_CONNECT_INIT,
+    DO_CONNECT_COMPL:   "%d" % DO_CONNECT_COMPL,
+    DO_CONFIGURE:       "%d" % DO_CONFIGURE,
+    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_ROUTE: "%d|%s" % (GET, "%d|%d|%s"),
@@ -93,6 +99,7 @@ testbed_messages = dict({
     ACTION: "%d|%s" % (ACTION, "%s|%d|%s"),
     STATUS: "%d|%s" % (STATUS, "%d"),
     GUIDS:  "%d" % GUIDS,
+    GET_ATTRIBUTE_LIST:  "%d" % GET_ATTRIBUTE_LIST,
     })
 
 instruction_text = dict({
@@ -117,14 +124,17 @@ instruction_text = dict({
     ADD_ROUTE:  "ADD_ROUTE",
     DO_SETUP:   "DO_SETUP",
     DO_CREATE:  "DO_CREATE",
-    DO_CONNECT: "DO_CONNECT",
+    DO_CONNECT_INIT: "DO_CONNECT_INIT",
+    DO_CONNECT_COMPL: "DO_CONNECT_COMPL",
     DO_CONFIGURE:   "DO_CONFIGURE",
     DO_PRECONFIGURE:   "DO_PRECONFIGURE",
-    DO_CROSS_CONNECT:   "DO_CROSS_CONNECT",
+    DO_CROSS_CONNECT_INIT:  "DO_CROSS_CONNECT_INIT",
+    DO_CROSS_CONNECT_COMPL: "DO_CROSS_CONNECT_COMPL",
     GET:    "GET",
     SET:    "SET",
     GET_ROUTE: "GET_ROUTE",
     GET_ADDRESS: "GET_ADDRESS",
+    GET_ATTRIBUTE_LIST: "GET_ATTRIBUTE_LIST",
     ACTION: "ACTION",
     STATUS: "STATUS",
     GUIDS:  "GUIDS",
@@ -364,14 +374,18 @@ class TestbedControllerServer(server.Server):
                     reply = self.do_setup(params)
                 elif instruction == DO_CREATE:
                     reply = self.do_create(params)
-                elif instruction == DO_CONNECT:
-                    reply = self.do_connect(params)
+                elif instruction == DO_CONNECT_INIT:
+                    reply = self.do_connect_init(params)
+                elif instruction == DO_CONNECT_COMPL:
+                    reply = self.do_connect_compl(params)
                 elif instruction == DO_CONFIGURE:
                     reply = self.do_configure(params)
                 elif instruction == DO_PRECONFIGURE:
                     reply = self.do_preconfigure(params)
-                elif instruction == DO_CROSS_CONNECT:
-                    reply = self.do_cross_connect(params)
+                elif instruction == DO_CROSS_CONNECT_INIT:
+                    reply = self.do_cross_connect_init(params)
+                elif instruction == DO_CROSS_CONNECT_COMPL:
+                    reply = self.do_cross_connect_compl(params)
                 elif instruction == GET:
                     reply = self.get(params)
                 elif instruction == SET:
@@ -386,6 +400,8 @@ class TestbedControllerServer(server.Server):
                     reply = self.status(params)
                 elif instruction == GUIDS:
                     reply = self.guids(params)
+                elif instruction == GET_ATTRIBUTE_LIST:
+                    reply = self.get_attribute_list(params)
                 else:
                     error = "Invalid instruction %s" % instruction
                     self.log_error(error)
@@ -508,8 +524,12 @@ class TestbedControllerServer(server.Server):
         self._testbed.do_create()
         return "%d|%s" % (OK, "")
 
-    def do_connect(self, params):
-        self._testbed.do_connect()
+    def do_connect_init(self, params):
+        self._testbed.do_connect_init()
+        return "%d|%s" % (OK, "")
+
+    def do_connect_compl(self, params):
+        self._testbed.do_connect_compl()
         return "%d|%s" % (OK, "")
 
     def do_configure(self, params):
@@ -520,13 +540,21 @@ class TestbedControllerServer(server.Server):
         self._testbed.do_preconfigure()
         return "%d|%s" % (OK, "")
 
-    def do_cross_connect(self, params):
-        self._testbed.do_cross_connect()
+    def do_cross_connect_init(self, params):
+        pcross_data = base64.b64decode(params[1])
+        cross_data = cPickle.loads(pcross_data)
+        self._testbed.do_cross_connect_init(cross_data)
+        return "%d|%s" % (OK, "")
+
+    def do_cross_connect_compl(self, params):
+        pcross_data = base64.b64decode(params[1])
+        cross_data = cPickle.loads(pcross_data)
+        self._testbed.do_cross_connect_compl(cross_data)
         return "%d|%s" % (OK, "")
 
     def get(self, params):
         time = params[1]
-        guid = int(param[2] )
+        guid = int(param[2])
         name = base64.b64decode(params[3])
         value = self._testbed.get(time, guid, name)
         result = base64.b64encode(str(value))
@@ -570,7 +598,14 @@ class TestbedControllerServer(server.Server):
         status = self._testbed.status(guid)
         result = base64.b64encode(str(status))
         return "%d|%s" % (OK, result)
+
+    def get_attribute_list(self, params):
+        guid = int(param[1])
+        attr_list = self._testbed.get_attribute_list(guid)
+        value = cPickle.dumps(attr_list)
+        result = base64.b64encode(value)
+        return "%d|%s" % (OK, result)
+
 class ExperimentControllerServer(server.Server):
     def __init__(self, root_dir, log_level, experiment_xml):
         super(ExperimentControllerServer, self).__init__(root_dir, log_level)
@@ -856,8 +891,18 @@ class TestbedControllerProxy(object):
         if code == ERROR:
             raise RuntimeError(text)
 
-    def do_connect(self):
-        msg = testbed_messages[DO_CONNECT]
+    def do_connect_init(self):
+        msg = testbed_messages[DO_CONNECT_INIT]
+        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 do_connect_compl(self):
+        msg = testbed_messages[DO_CONNECT_COMPL]
         self._client.send_msg(msg)
         reply = self._client.read_reply()
         result = reply.split("|")
@@ -886,8 +931,24 @@ class TestbedControllerProxy(object):
         if code == ERROR:
             raise RuntimeError(text)
 
-    def do_cross_connect(self):
-        msg = testbed_messages[DO_CROSS_CONNECT]
+    def do_cross_connect_init(self, cross_data):
+        msg = testbed_messages[DO_CROSS_CONNECT_INIT]
+        pcross_data = cPickle.dumps(cross_data)
+        cross_data = base64.b64encode(pcross_data)
+        msg = msg % (cross_data)
+        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 do_cross_connect_compl(self, cross_data):
+        msg = testbed_messages[DO_CROSS_CONNECT_COMPL]
+        pcross_data = cPickle.dumps(cross_data)
+        cross_data = base64.b64encode(pcross_data)
+        msg = msg % (cross_data)
         self._client.send_msg(msg)
         reply = self._client.read_reply()
         result = reply.split("|")
@@ -1009,6 +1070,19 @@ class TestbedControllerProxy(object):
             raise RuntimeError(text)
         return text
 
+    def get_attribute_list(self, guid):
+        msg = testbed_messages[GET_ATTRIBUTE_LIST]
+        msg = msg % (guid)
+        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)
+        attr_list = cPickle.loads(text)
+        return attr_list
+
     def shutdown(self):
         msg = testbed_messages[SHUTDOWN]
         self._client.send_msg(msg)
index 7718eaf..2bb15b4 100755 (executable)
@@ -33,9 +33,12 @@ class ExecuteTestCase(unittest.TestCase):
 
         instance.do_setup()
         instance.do_create()
-        instance.do_connect()
+        instance.do_connect_init()
+        instance.do_connect_compl()
         instance.do_configure()
         instance.start()
+        attr_list = instance.get_attribute_list(5)
+        self.assertEquals(attr_list, ["test", "fake", "label"])
         while instance.status(7) != STATUS_FINISHED:
             time.sleep(0.5)
         app_result = instance.trace(7, "fake")
index d8d92eb..220d7e9 100755 (executable)
@@ -50,6 +50,7 @@ class ExecuteTestCase(unittest.TestCase):
         xml = exp_desc.to_xml()
         access_config = None
         controller = proxy.create_controller(xml, access_config)
+
         controller.start()
         while not controller.is_finished(app.guid):
             time.sleep(0.5)
index f8bce35..319de37 100755 (executable)
@@ -43,7 +43,8 @@ class NetnsExecuteTestCase(unittest.TestCase):
 
         instance.do_setup()
         instance.do_create()
-        instance.do_connect()
+        instance.do_connect_init()
+        instance.do_connect_compl()
         instance.do_preconfigure()
         instance.do_configure()
         instance.start()
@@ -84,7 +85,8 @@ class NetnsExecuteTestCase(unittest.TestCase):
 
         instance.do_setup()
         instance.do_create()
-        instance.do_connect()
+        instance.do_connect_init()
+        instance.do_connect_compl()
         instance.do_preconfigure()
         instance.do_configure()
         instance.start()
@@ -144,7 +146,8 @@ class NetnsExecuteTestCase(unittest.TestCase):
 
         instance.do_setup()
         instance.do_create()
-        instance.do_connect()
+        instance.do_connect_init()
+        instance.do_connect_compl()
         instance.do_preconfigure()
         instance.do_configure()
         instance.start()
index 3722bc7..ffefbfc 100755 (executable)
@@ -64,7 +64,8 @@ class Ns3ExecuteTestCase(unittest.TestCase):
 
         instance.do_setup()
         instance.do_create()
-        instance.do_connect()
+        instance.do_connect_init()
+        instance.do_connect_compl()
         instance.do_preconfigure()
         instance.do_configure()
         instance.start()
index 31d8481..1a24e70 100755 (executable)
@@ -100,7 +100,8 @@ class Ns3ExecuteTestCase(unittest.TestCase):
 
         instance.do_setup()
         instance.do_create()
-        instance.do_connect()
+        instance.do_connect_init()
+        instance.do_connect_compl()
         instance.do_preconfigure()
         instance.do_configure()
         instance.start()