From: Alina Quereilhac Date: Thu, 28 Apr 2011 17:10:07 +0000 (+0200) Subject: initial changes to support cross_connection in two stages. X-Git-Tag: nepi_v2~107 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=0b31108e8d6240949592c9e344d0c5cee19f8f35;p=nepi.git initial changes to support cross_connection in two stages. --- diff --git a/src/nepi/core/attributes.py b/src/nepi/core/attributes.py index 3dd3da4d..b6bf9139 100644 --- a/src/nepi/core/attributes.py +++ b/src/nepi/core/attributes.py @@ -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): diff --git a/src/nepi/core/execute.py b/src/nepi/core/execute.py index 2fa16c28..cbc8f186 100644 --- a/src/nepi/core/execute.py +++ b/src/nepi/core/execute.py @@ -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 + diff --git a/src/nepi/core/metadata.py b/src/nepi/core/metadata.py index 93a31c71..7414b619 100644 --- a/src/nepi/core/metadata.py +++ b/src/nepi/core/metadata.py @@ -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) diff --git a/src/nepi/core/testbed_impl.py b/src/nepi/core/testbed_impl.py index 819fc143..78cbb1f9 100644 --- a/src/nepi/core/testbed_impl.py +++ b/src/nepi/core/testbed_impl.py @@ -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(): diff --git a/src/nepi/testbeds/netns/metadata_v01.py b/src/nepi/testbeds/netns/metadata_v01.py index 7b9cecbc..472935c5 100644 --- a/src/nepi/testbeds/netns/metadata_v01.py +++ b/src/nepi/testbeds/netns/metadata_v01.py @@ -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 }) ] diff --git a/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py b/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py index 9d5cfabe..3a3891c0 100644 --- a/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py +++ b/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py @@ -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 }), ] diff --git a/src/nepi/testbeds/planetlab/metadata_v01.py b/src/nepi/testbeds/planetlab/metadata_v01.py index 7866741a..b1d51c6e 100644 --- a/src/nepi/testbeds/planetlab/metadata_v01.py +++ b/src/nepi/testbeds/planetlab/metadata_v01.py @@ -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 }), ] diff --git a/src/nepi/util/proxy.py b/src/nepi/util/proxy.py index b0c045d2..0fdc47af 100644 --- a/src/nepi/util/proxy.py +++ b/src/nepi/util/proxy.py @@ -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) diff --git a/test/core/execute.py b/test/core/execute.py index 7718eaf2..2bb15b47 100755 --- a/test/core/execute.py +++ b/test/core/execute.py @@ -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") diff --git a/test/core/integration.py b/test/core/integration.py index d8d92eb8..220d7e94 100755 --- a/test/core/integration.py +++ b/test/core/integration.py @@ -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) diff --git a/test/testbeds/netns/execute.py b/test/testbeds/netns/execute.py index f8bce350..319de37f 100755 --- a/test/testbeds/netns/execute.py +++ b/test/testbeds/netns/execute.py @@ -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() diff --git a/test/testbeds/ns3/execute.py b/test/testbeds/ns3/execute.py index 3722bc7c..ffefbfcf 100755 --- a/test/testbeds/ns3/execute.py +++ b/test/testbeds/ns3/execute.py @@ -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() diff --git a/test/testbeds/ns3/execute2.py b/test/testbeds/ns3/execute2.py index 31d8481f..1a24e709 100755 --- a/test/testbeds/ns3/execute2.py +++ b/test/testbeds/ns3/execute2.py @@ -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()