From: Alina Quereilhac Date: Tue, 9 Oct 2012 15:10:45 +0000 (+0200) Subject: Added routes to OMF nodes X-Git-Tag: nepi-3.0.0~143 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=1cf85539204432589217de408cd2eb37e3d68e6a;p=nepi.git Added routes to OMF nodes --- diff --git a/examples/omf-plexuslab-vlc.py b/examples/omf-plexuslab-vlc.py new file mode 100644 index 00000000..3ffabe47 --- /dev/null +++ b/examples/omf-plexuslab-vlc.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Experiment Topology: +# +# n1 --- n2 +# 0.1 0.2 +# + +from nepi.core.design import ExperimentDescription, FactoriesProvider +from nepi.core.execute import ExperimentController +import getpass +import logging +import tempfile +import time + +logging.basicConfig(level=logging.DEBUG) + +root_dir = tempfile.mkdtemp() + +exp_desc = ExperimentDescription() + +testbed_id = "omf" +omf_provider = FactoriesProvider(testbed_id) +omf_desc = exp_desc.add_testbed_description(omf_provider) +omf_desc.set_attribute_value("homeDirectory", root_dir) +omf_desc.set_attribute_value("enableDebug", True) +omf_desc.set_attribute_value("xmppSlice", "default_slice") +omf_desc.set_attribute_value("xmppHost", "xmpp-plexus.onelab.eu") +omf_desc.set_attribute_value("xmppPort", 5222) +omf_desc.set_attribute_value("xmppPassword", "1234") + +# Add node1 +node1 = omf_desc.create("Node") +node1.set_attribute_value("hostname", "omf.plexus.wlab17") + +# Add configuration for interface 1 +iface1 = omf_desc.create("WifiInterface") +iface1.set_attribute_value("alias", "w0") +iface1.set_attribute_value("mode", "adhoc") +iface1.set_attribute_value("channel", "6") +iface1.set_attribute_value("type", "g") +iface1.set_attribute_value("essid", "cvlcmode") +iface1.set_attribute_value("ip", "192.168.0.17") +node1.connector("devs").connect(iface1.connector("node")) + +# Add multicast route to node 1 +route1 = node1.add_route() +route1.set_attribute_value("Destination", "224.0.0.0") +route1.set_attribute_value("NetPrefix", 4) +route1.set_attribute_value("Device", "wlan0") + +# Add node2 +node2 = omf_desc.create("Node") +node2.set_attribute_value("hostname", "omf.plexus.wlab37") + +# Add configuration for interface 2 +iface2 = omf_desc.create("WifiInterface") +iface2.set_attribute_value("alias", "w0") +iface2.set_attribute_value("mode", "adhoc") +iface2.set_attribute_value("channel", "6") +iface2.set_attribute_value("type", "g") +iface2.set_attribute_value("essid", "cvlcmode") +iface2.set_attribute_value("ip", "192.168.0.37") +node2.connector("devs").connect(iface2.connector("node")) + +# Add multicast route to node 2 +route2 = node2.add_route() +route2.set_attribute_value("Destination", "224.0.0.0") +route2.set_attribute_value("NetPrefix", 4) +route2.set_attribute_value("Device", "wlan0") + +# Add a channel... this could be ommited +channel = omf_desc.create("Channel") +channel.set_attribute_value("mode", "adhoc") +channel.set_attribute_value("channel", "6") +channel.set_attribute_value("type", "g") +channel.set_attribute_value("essid", "cvlcmode") +channel.connector("devs").connect(iface1.connector("chan")) +channel.connector("devs").connect(iface2.connector("chan")) + +# Add a vlc server to stream a video using multicast +app1 = omf_desc.create("OmfApplication") +app1.set_attribute_value("appId", "Vlc#1") +app1.set_attribute_value("arguments", "/opt/bbb_240p_mpeg4_lq.ts --sout '#rtp{dst=239.255.0.1,port=1234,mux=ts}' vlc://quit") +app1.set_attribute_value("path", "/opt/vlc-1.1.13/cvlc") +app1.set_attribute_value("env", "DISPLAY=localhost:10.0 XAUTHORITY=/root/.Xauthority") +app1.connector("node").connect(node1.connector("apps")) + +# Add a vlc client to receive the video stream +app2 = omf_desc.create("OmfApplication") +app2.set_attribute_value("appId", "Vlc#2") +app2.set_attribute_value("arguments", "rtp://239.255.0.1:1234") +app2.set_attribute_value("path", "/opt/vlc-1.1.13/cvlc") +# To see the stream to a ssh -X connection, the DISPLAY variable must be set to the value of the node. +# Also don't forget to execute in 'xhost + localhost' in the node +app2.set_attribute_value("env", "DISPLAY=localhost:10.0 XAUTHORITY=/root/.Xauthority") +app2.connector("node").connect(node2.connector("apps")) + +xml = exp_desc.to_xml() + +controller = ExperimentController(xml, root_dir) +controller.start() +#while not (controller.is_finished(app1.guid) and \ +# controller.is_finished(app2.guid)): +# time.sleep(0.5) + +time.sleep(30) + +controller.set(iface2.guid, "channel", "1") + +time.sleep(15) + +controller.stop() +controller.shutdown() + diff --git a/examples/omf-plexuslab-xeyes.py b/examples/omf-plexuslab-xeyes.py new file mode 100644 index 00000000..7e83943d --- /dev/null +++ b/examples/omf-plexuslab-xeyes.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# Experiment Topology: +# +# n1 --- n2 +# 0.1 0.2 +# + +from nepi.core.design import ExperimentDescription, FactoriesProvider +from nepi.core.execute import ExperimentController +import getpass +import logging +import tempfile +import time + +logging.basicConfig(level=logging.DEBUG) + +root_dir = tempfile.mkdtemp() + +exp_desc = ExperimentDescription() + +testbed_id = "omf" +omf_provider = FactoriesProvider(testbed_id) +omf_desc = exp_desc.add_testbed_description(omf_provider) +omf_desc.set_attribute_value("homeDirectory", root_dir) +omf_desc.set_attribute_value("enableDebug", True) +omf_desc.set_attribute_value("xmppSlice", "default_slice") +omf_desc.set_attribute_value("xmppHost", "xmpp-plexus.onelab.eu") +omf_desc.set_attribute_value("xmppPort", 5222) +omf_desc.set_attribute_value("xmppPassword", "1234") + +node1 = omf_desc.create("Node") +node1.set_attribute_value("hostname", "omf.plexus.wlab17") + +app1 = omf_desc.create("OmfApplication") +app1.set_attribute_value("appId", "xeyes#1") +app1.set_attribute_value("path", "/usr/bin/xeyes") +app1.set_attribute_value("env", "DISPLAY=localhost:10.0 XAUTHORITY=/root/.Xauthority") +app1.connector("node").connect(node1.connector("apps")) + +xml = exp_desc.to_xml() + +controller = ExperimentController(xml, root_dir) +controller.start() + +time.sleep(30) + +controller.stop() +controller.shutdown() + diff --git a/examples/omf_vlc.py b/examples/omf_vlc.py deleted file mode 100644 index 1f923196..00000000 --- a/examples/omf_vlc.py +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# -# Experiment Topology: -# -# n1 --- n2 -# 0.1 0.2 -# - -from nepi.core.design import ExperimentDescription, FactoriesProvider -from nepi.core.execute import ExperimentController -import getpass -import tempfile -import time - -root_dir = tempfile.mkdtemp() - -exp_desc = ExperimentDescription() - -testbed_id = "omf" -omf_provider = FactoriesProvider(testbed_id) -omf_desc = exp_desc.add_testbed_description(omf_provider) -omf_desc.set_attribute_value("homeDirectory", root_dir) -omf_desc.set_attribute_value("enableDebug", True) -omf_desc.set_attribute_value("xmppSlice", "default_slice") -omf_desc.set_attribute_value("xmppHost", "xmpp-omf.onelab.eu") -omf_desc.set_attribute_value("xmppPort", 5222) -omf_desc.set_attribute_value("xmppPassword", "1234") - -node1 = omf_desc.create("Node") -node1.set_attribute_value("hostname", "omf.my.wlab18") -node2 = omf_desc.create("Node") -node2.set_attribute_value("hostname", "omf.my.wlab49") - -iface12 = omf_desc.create("WifiInterface") -iface12.set_attribute_value("mode", "adhoc") -iface12.set_attribute_value("channel", "6") -iface12.set_attribute_value("type", "g") -iface12.set_attribute_value("essid", "cvlcmode") -iface12.set_attribute_value("ip", "192.168.0.18") -node1.connector("devs").connect(iface12.connector("node")) - -iface21 = omf_desc.create("WifiInterface") -iface21.set_attribute_value("mode", "adhoc") -iface21.set_attribute_value("channel", "6") -iface21.set_attribute_value("type", "g") -iface21.set_attribute_value("essid", "cvlcmode") -iface21.set_attribute_value("ip", "192.168.0.49") -node2.connector("devs").connect(iface21.connector("node")) - -channel = omf_desc.create("Channel") -channel.set_attribute_value("mode", "adhoc") -channel.set_attribute_value("channel", "6") -channel.set_attribute_value("type", "g") -channel.set_attribute_value("essid", "cvlcmode") -channel.connector("devs").connect(iface12.connector("chan")) -channel.connector("devs").connect(iface21.connector("chan")) - -app2 = omf_desc.create("OmfApplication") -app2.set_attribute_value("appId", "Vlc#2") -app2.set_attribute_value("arguments", "rtp://239.255.0.1:1234") -app2.set_attribute_value("path", "/opt/vlc-1.1.13/vlc") -app2.connector("node").connect(node2.connector("apps")) - -app1 = omf_desc.create("OmfApplication") -app1.set_attribute_value("appId", "Vlc#1") -app1.set_attribute_value("arguments", "/opt/10-by-p0d.avi --sout '#duplicate{dst=display,dst=rtp{mux=ts,dst=239.255.0.1,port=1234}}'") -app1.set_attribute_value("path", "/opt/vlc-1.1.13/vlc") -app1.connector("node").connect(node1.connector("apps")) - -xml = exp_desc.to_xml() - -controller = ExperimentController(xml, root_dir) -controller.start() -#while not (controller.is_finished(app1.guid) and \ -# controller.is_finished(app2.guid)): -# time.sleep(0.5) - -time.sleep(20) - -controller.set(iface21.guid, "channel", "1") - -time.sleep(15) - -controller.stop() -controller.shutdown() - diff --git a/src/nepi/core/design.py b/src/nepi/core/design.py index e6300126..7ad55092 100644 --- a/src/nepi/core/design.py +++ b/src/nepi/core/design.py @@ -157,6 +157,12 @@ class Route(AttributesMap): value = 0, flags = Attribute.NoDefaultValue, validation_function = validation.is_integer) + self.add_attribute(name = "Device", + help = "Device name", + type = Attribute.STRING, + value = None, + flags = Attribute.NoDefaultValue, + validation_function = validation.is_string) class Box(AttributesMap, Taggable): def __init__(self, guid, factory, testbed_guid, container = None): diff --git a/src/nepi/core/execute.py b/src/nepi/core/execute.py index 9f034cbb..5e0c5ea6 100644 --- a/src/nepi/core/execute.py +++ b/src/nepi/core/execute.py @@ -83,7 +83,8 @@ class TestbedController(object): """Instructs the addition of an address""" raise NotImplementedError - def defer_add_route(self, guid, destination, netprefix, nexthop, metric = 0): + def defer_add_route(self, guid, destination, netprefix, nexthop, + metric = 0, device = None): """Instructs the addition of a route""" raise NotImplementedError @@ -1017,8 +1018,10 @@ class ExperimentController(object): testbed.defer_add_address(guid, address, netprefix, broadcast) # routes - for (destination, netprefix, nexthop, metric) in data.get_route_data(guid): - testbed.defer_add_route(guid, destination, netprefix, nexthop, metric) + for (destination, netprefix, nexthop, metric, device) in \ + data.get_route_data(guid): + testbed.defer_add_route(guid, destination, netprefix, nexthop, + metric, device) # store connections data for (connector_type_name, other_guid, other_connector_type_name) \ in data.get_connection_data(guid): diff --git a/src/nepi/core/testbed_impl.py b/src/nepi/core/testbed_impl.py index ade1cccd..d27588dc 100644 --- a/src/nepi/core/testbed_impl.py +++ b/src/nepi/core/testbed_impl.py @@ -150,12 +150,14 @@ class TestbedController(execute.TestbedController): self._add_address[guid] = list() self._add_address[guid].append((address, netprefix, broadcast)) - def defer_add_route(self, guid, destination, netprefix, nexthop, metric = 0): + def defer_add_route(self, guid, destination, netprefix, nexthop, + metric = 0, device = None): self._validate_guid(guid) self._validate_allow_routes(guid) if not guid in self._add_route: self._add_route[guid] = list() - self._add_route[guid].append((destination, netprefix, nexthop, metric)) + self._add_route[guid].append((destination, netprefix, nexthop, + metric, device)) def do_setup(self): self._root_directory = self._attributes.\ diff --git a/src/nepi/testbeds/netns/metadata.py b/src/nepi/testbeds/netns/metadata.py index 472062c9..36e914a5 100644 --- a/src/nepi/testbeds/netns/metadata.py +++ b/src/nepi/testbeds/netns/metadata.py @@ -245,7 +245,7 @@ def configure_node(testbed_instance, guid): return routes = testbed_instance._add_route[guid] for route in routes: - (destination, netprefix, nexthop, metric) = route + (destination, netprefix, nexthop, metric, device) = route element.add_route(prefix = destination, prefix_len = netprefix, nexthop = nexthop, metric = metric) diff --git a/src/nepi/testbeds/ns3/factories_metadata.py b/src/nepi/testbeds/ns3/factories_metadata.py index 201c9323..a7921a81 100644 --- a/src/nepi/testbeds/ns3/factories_metadata.py +++ b/src/nepi/testbeds/ns3/factories_metadata.py @@ -477,7 +477,7 @@ def configure_node(testbed_instance, guid): ns3 = testbed_instance.ns3 routes = testbed_instance._add_route[guid] for route in routes: - (destination, netprefix, nexthop, metric) = route + (destination, netprefix, nexthop, metric, device) = route address = ns3.Ipv4Address(destination) if nexthop: nexthop_address = ns3.Ipv4Address(nexthop) @@ -497,7 +497,7 @@ def configure_node(testbed_instance, guid): break if ifindex < 0: # Check previous ptp routes - for chaindest, chainprefix, chainhop, metric in routes: + for chaindest, chainprefix, chainhop, metric, device in routes: if chaindest == nexthop and chainprefix == 32: chainhop_address = ns3.Ipv4Address(chainhop) for ifidx in xrange(nifaces): diff --git a/src/nepi/testbeds/omf/execute.py b/src/nepi/testbeds/omf/execute.py index db2e8107..97369557 100644 --- a/src/nepi/testbeds/omf/execute.py +++ b/src/nepi/testbeds/omf/execute.py @@ -34,7 +34,8 @@ class TestbedController(testbed_impl.TestbedController): port = self._attributes.get_attribute_value("xmppPort") password = self._attributes.get_attribute_value("xmppPassword") - self._api = OmfAPI(slice, host, port, password) + xmpp_root = self._attributes.get_attribute_value("xmppRoot") + self._api = OmfAPI(slice, host, port, password, xmpp_root) super(TestbedController, self).do_setup() diff --git a/src/nepi/testbeds/omf/metadata.py b/src/nepi/testbeds/omf/metadata.py index 4b1734fa..faca73f1 100644 --- a/src/nepi/testbeds/omf/metadata.py +++ b/src/nepi/testbeds/omf/metadata.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- import functools +import random import weakref from constants import TESTBED_ID, TESTBED_VERSION from nepi.core import metadata from nepi.core.attributes import Attribute -from nepi.util import tags, validation +from nepi.util import tags, validation, ipaddr2 from nepi.util.constants import ApplicationStatus as AS, \ FactoryCategories as FC, DeploymentConfiguration as DC @@ -22,6 +23,10 @@ class OmfResource(object): def tc(self): return self._tc and self._tc() + @property + def guid(self): + return self._guid + def configure(self): pass @@ -45,6 +50,26 @@ class OmfNode(OmfResource): self.hostname = self.tc._get_parameters(guid)['hostname'] self.tc.api.enroll_host(self.hostname) + def configure(self): + routes = self.tc._add_route.get(self.guid, []) + iface_guids = self.tc.get_connected(self.guid, "devs", "node") + + for route in routes: + (destination, netprefix, nexthop, metric, device) = route + netmask = ipaddr2.ipv4_mask2dot(netprefix) + + # Validate that the interface is associated to the node + for iface_guid in iface_guids: + iface = self.tc.elements.get(iface_guid) + if iface.devname == device: + self.tc.api.execute(self.hostname, + "Id#%s" % str(random.getrandbits(128)), + "add -net %s netmask %s dev %s" % (destination, netmask, iface.devname), + "/sbin/route", # path + None, # env + ) + break + ## APPLICATION ################################################################ class OmfApplication(OmfResource): @@ -84,6 +109,8 @@ class OmfApplication(OmfResource): ## WIFIIFACE ######################################################## class OmfWifiInterface(OmfResource): + alias2name = dict({'w0':'wlan0', 'w1':'wlan1'}) + def __init__(self, guid, tc): super(OmfWifiInterface, self).__init__(guid, tc) node_guids = tc.get_connected(guid, "node", "devs") @@ -91,19 +118,24 @@ class OmfWifiInterface(OmfResource): raise RuntimeError("Can't instantiate interface %d outside node" % guid) self._node_guid = node_guids[0] + self.alias = None self.mode = None self.type = None self.essid = None self.channel = None self.ip = None + self.devname = None def __setattr__(self, name, value): + if name == "alias": + self.devname = self.alias2name.get(value) + if name in ["ip", "mode", "type", "essid", "channel"]: node = self.tc.elements.get(self._node_guid) - attribute = "net/w0/%s" % name + attribute = "net/%s/%s" % (self.alias, name) self._tc().api.configure(node.hostname, attribute, value) - else: - super(OmfWifiInterface, self).__setattr__(name, value) + + super(OmfWifiInterface, self).__setattr__(name, value) # Factories NODE = "Node" @@ -138,7 +170,7 @@ def status(testbed_instance, guid): def configure(testbed_instance, guid): element = testbed_instance.elements.get(guid) - return element.status() + return element.configure() ### Factory information ### @@ -258,9 +290,14 @@ attributes = dict({ "flags": Attribute.NoDefaultValue, "validation_function": validation.is_ip4_address }), - - - + "alias": dict({ + "name": "alias", + "help": "Alias for device (e.g. w0, w1, etc)", + "type": Attribute.STRING, + "value": "w0", + "flags": Attribute.NoDefaultValue, + "validation_function": validation.is_string + }), }) traces = dict() @@ -273,6 +310,7 @@ factories_info = dict({ "help": "OMF Node", "category": FC.CATEGORY_NODES, "create_function": functools.partial(create, NODE), + "configure_function": configure, "box_attributes": ["hostname"], "connector_types": ["devs", "apps"], "tags": [tags.NODE, tags.ALLOW_ROUTES], @@ -282,7 +320,7 @@ factories_info = dict({ "category": FC.CATEGORY_DEVICES, "create_function": functools.partial(create, WIFIIFACE), "configure_function": configure, - "box_attributes": ["mode", "type", "channel", "essid", "ip"], + "box_attributes": ["mode", "type", "channel", "essid", "ip", "alias"], "connector_types": ["node", "chan"], "tags": [tags.INTERFACE, tags.HAS_ADDRESSES], }), @@ -343,6 +381,14 @@ testbed_attributes = dict({ "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable, "validation_function": validation.is_string }), + "xmppRoot": dict({ + "name": "xmppRoot", + "help": "Root node of the xmpp server pubsub tree", + "type": Attribute.STRING, + "value": "OMF", + "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable, + "validation_function": validation.is_string + }), }) supported_recovery_policies = [ diff --git a/src/nepi/testbeds/omf/omf_api.py b/src/nepi/testbeds/omf/omf_api.py index d76fba34..7b54b4c3 100644 --- a/src/nepi/testbeds/omf/omf_api.py +++ b/src/nepi/testbeds/omf/omf_api.py @@ -8,7 +8,7 @@ from nepi.testbeds.omf.omf_client import OMFClient from nepi.testbeds.omf.omf_messages import MessageHandler class OmfAPI(object): - def __init__(self, slice, host, port, password): + def __init__(self, slice, host, port, password, xmpp_root = None): date = datetime.datetime.now().strftime("%Y-%m-%dt%H.%M.%S") tz = -time.altzone if time.daylight != 0 else -time.timezone date += "%+06.2f" % (tz / 3600) # timezone difference is in seconds @@ -18,6 +18,7 @@ class OmfAPI(object): self._port = port self._password = password self._hostnames = [] + self._xmpp_root = xmpp_root or "OMF" self._logger = logging.getLogger("nepi.testbeds.omf") @@ -61,9 +62,9 @@ class OmfAPI(object): self._client.create(xmpp_node) self._client.subscribe(xmpp_node) - address = "/%s/OMF/%s/%s" % (self._host, self._slice, self._user) + address = "/%s/%s/%s/%s" % (self._host, self._xmpp_root, self._slice, self._user) payload = self._message.newexpfunction(self._user, address) - slice_sid = "/OMF/%s" % (self._slice) + slice_sid = "/%s/%s" % (self._xmpp_root, self._slice) self._client.publish(payload, slice_sid) def _enroll_logger(self): @@ -78,18 +79,18 @@ class OmfAPI(object): self._client.publish(payload, xmpp_node) def _host_session_id(self, hostname): - return "/OMF/%s/%s/%s" % (self._slice, self._user, hostname) + return "/%s/%s/%s/%s" % (self._xmpp_root, self._slice, self._user, hostname) def _host_resource_id(self, hostname): - return "/OMF/%s/resources/%s" % (self._slice, hostname) + return "/%s/%s/resources/%s" % (self._xmpp_root, self._slice, hostname) @property def _exp_session_id(self): - return "/OMF/%s/%s" % (self._slice, self._user) + return "/%s/%s/%s" % (self._xmpp_root, self._slice, self._user) @property def _logger_session_id(self): - return "/OMF/%s/%s/LOGGER" % (self._slice, self._user) + return "/%s/%s/%s/LOGGER" % (self._xmpp_root, self._slice, self._user) def delete(self, hostname): if not hostname in self._hostnames: diff --git a/src/nepi/testbeds/planetlab/interfaces.py b/src/nepi/testbeds/planetlab/interfaces.py index 24937db2..f4df82f6 100644 --- a/src/nepi/testbeds/planetlab/interfaces.py +++ b/src/nepi/testbeds/planetlab/interfaces.py @@ -221,7 +221,7 @@ class TunIface(object): if pointopoint: prefix = 32 - dest, destprefix, nexthop, metric = route + dest, destprefix, nexthop, metric, device = route myNet = ipaddr.IPv4Network("%s/%d" % (addr, prefix)) gwIp = ipaddr.IPv4Network(nexthop) diff --git a/src/nepi/testbeds/planetlab/node.py b/src/nepi/testbeds/planetlab/node.py index e863f4ac..34f6f797 100644 --- a/src/nepi/testbeds/planetlab/node.py +++ b/src/nepi/testbeds/planetlab/node.py @@ -672,7 +672,7 @@ class Node(object): vsys_vnet = ipaddr.IPv4Network(vsys_vnet) for route in routes: - dest, prefix, nexthop, metric = route + dest, prefix, nexthop, metric, device = route dest = ipaddr.IPv4Network("%s/%d" % (dest,prefix)) nexthop = ipaddr.IPAddress(nexthop) if dest not in vsys_vnet or nexthop not in vsys_vnet: @@ -681,7 +681,7 @@ class Node(object): return 'vroute' def format_route(self, route, dev, method, action): - dest, prefix, nexthop, metric = route + dest, prefix, nexthop, metric, device = route if method == 'vroute': return ( "%s %s%s gw %s %s" % ( diff --git a/src/nepi/util/parser/_xml.py b/src/nepi/util/parser/_xml.py index a1a8a592..683e4f53 100644 --- a/src/nepi/util/parser/_xml.py +++ b/src/nepi/util/parser/_xml.py @@ -131,7 +131,7 @@ class XmlExperimentParser(ExperimentParser): def routes_data_to_xml(self, doc, parent_tag, guid, data): routes_tag = doc.createElement("routes") - for (destination, netprefix, nexthop, metric) \ + for (destination, netprefix, nexthop, metric, device) \ in data.get_route_data(guid): route_tag = doc.createElement("route") routes_tag.appendChild(route_tag) @@ -139,6 +139,7 @@ class XmlExperimentParser(ExperimentParser): route_tag.setAttribute("NetPrefix", xmlencode(netprefix)) route_tag.setAttribute("NextHop", xmlencode(nexthop)) route_tag.setAttribute("Metric", xmlencode(metric)) + route_tag.setAttribute("Device", xmlencode(device)) if routes_tag.hasChildNodes(): parent_tag.appendChild(routes_tag) @@ -283,8 +284,9 @@ class XmlExperimentParser(ExperimentParser): nexthop = xmldecode(route_tag.getAttribute("NextHop")) metric = int(route_tag.getAttribute("Metric")) \ if route_tag.hasAttribute("Metric") else 0 + device = xmldecode(route_tag.getAttribute("Device")) data.add_route_data(guid, destination, netprefix, - nexthop, metric) + nexthop, metric, device) def connections_data_from_xml(self, tag, guid, data): connections_tag_list = tag.getElementsByTagName("connections") diff --git a/src/nepi/util/parser/base.py b/src/nepi/util/parser/base.py index 6da07db7..eeaf5949 100644 --- a/src/nepi/util/parser/base.py +++ b/src/nepi/util/parser/base.py @@ -85,7 +85,7 @@ class ExperimentData(object): address_data["Broadcast"] = broadcast addresses_data.append(address_data) - def add_route_data(self, guid, destination, netprefix, nexthop, metric): + def add_route_data(self, guid, destination, netprefix, nexthop, metric, device): data = self.data[guid] if not "routes" in data: data["routes"] = list() @@ -94,7 +94,8 @@ class ExperimentData(object): "Destination": destination, "NetPrefix": netprefix, "NextHop": nexthop, - "Metric": metric + "Metric": metric, + "Device": device }) routes_data.append(route_data) @@ -183,7 +184,8 @@ class ExperimentData(object): return [(data["Destination"], data["NetPrefix"], data["NextHop"], - data["Metric"]) \ + data["Metric"], + data["Device"]) \ for data in routes_data] class ExperimentParser(object): @@ -254,7 +256,9 @@ class ExperimentParser(object): netprefix = route.get_attribute_value("NetPrefix") nexthop = route.get_attribute_value("NextHop") metric = route.get_attribute_value("Metric") - data.add_route_data(guid, destination, netprefix, nexthop, metric) + device = route.get_attribute_value("Device") + data.add_route_data(guid, destination, netprefix, nexthop, + metric, device) def from_data(self, experiment_description, data): box_guids = list() @@ -325,13 +329,14 @@ class ExperimentParser(object): addr.set_attribute_value("Broadcast", broadcast) def routes_from_data(self, box, data): - for (destination, netprefix, nexthop, metric) \ + for (destination, netprefix, nexthop, metric, device) \ in data.get_route_data(box.guid): addr = box.add_route() addr.set_attribute_value("Destination", destination) addr.set_attribute_value("NetPrefix", netprefix) addr.set_attribute_value("NextHop", nexthop) addr.set_attribute_value("Metric", metric) + addr.set_attribute_value("Device", device) def connections_from_data(self, experiment_description, guids, data): for guid in guids: diff --git a/src/nepi/util/proxy.py b/src/nepi/util/proxy.py index 9545a5ca..04f3655a 100644 --- a/src/nepi/util/proxy.py +++ b/src/nepi/util/proxy.py @@ -761,8 +761,10 @@ class TestbedControllerServer(BaseServer): @Marshalling.handles(ADD_ROUTE) @Marshalling.args(int, str, int, str, int) @Marshalling.retvoid - def defer_add_route(self, guid, destination, netprefix, nexthop, metric): - self._testbed.defer_add_route(guid, destination, netprefix, nexthop, metric) + def defer_add_route(self, guid, destination, netprefix, nexthop, + metric, device): + self._testbed.defer_add_route(guid, destination, netprefix, nexthop, + metric, device) @Marshalling.handles(DO_SETUP) @Marshalling.args()