From: Alina Quereilhac Date: Thu, 10 May 2012 17:07:30 +0000 (+0200) Subject: Fixing CCNx on PlanetLab to accept a user defined bind port. X-Git-Tag: nepi-3.0.0~163^2~5 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=a1c0cc97b3fc6c5aba2e519cc846426a3d56cbfb;p=nepi.git Fixing CCNx on PlanetLab to accept a user defined bind port. --- diff --git a/examples/ccnx/planetlab_ccnx_multicast.py b/examples/ccnx/planetlab_ccnx_multicast.py index cb8bf6be..cecb78f5 100644 --- a/examples/ccnx/planetlab_ccnx_multicast.py +++ b/examples/ccnx/planetlab_ccnx_multicast.py @@ -89,32 +89,45 @@ def create_tunnel(node, peer, pl_nodes, slice_desc, subnet): peerip.set_attribute_value("Address", peeraddr.exploded) peerip.set_attribute_value("NetPrefix", subnet.prefixlen) -def create_ccnd(pl_node, hostname, routes, slice_desc): +def create_ccnd(pl_node, port, hostname, routes, slice_desc): pl_app = slice_desc.create("CCNxDaemon") # We use a wildcard to replace the TUN IP address of the node during runtime routes = "|".join(map(lambda route: "udp 224.0.23.170 %d 3 1 {#[tun_%s%s].addr[0].[Address]#}" \ % (route[1], hostname, route[0]), routes)) # Add multicast ccn routes - pl_app.set_attribute_value("ccnroutes", routes) + pl_app.set_attribute_value("ccnRoutes", routes) + # Use a specific port to bind the CCNx daemon + if port: + pl_app.set_attribute_value("ccnLocalPort", port) pl_app.enable_trace("stdout") pl_app.enable_trace("stderr") pl_app.connector("node").connect(pl_node.connector("apps")) -def create_ccnsendchunks(pl_node, slice_desc): +def create_ccnsendchunks(pl_node, port, slice_desc): pl_app = slice_desc.create("Application") path_to_video = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../big_buck_bunny_240p_mpeg4_lq.ts") pl_app.set_attribute_value("stdin", path_to_video) - pl_app.set_attribute_value("command", "ccnsendchunks ccnx:/VIDEO") + + command = "ccnsendchunks ccnx:/VIDEO" + if port: + command = "CCN_LOCAL_PORT=%d %s " % (port, command) + pl_app.set_attribute_value("command", command) + pl_app.enable_trace("stdout") pl_app.enable_trace("stderr") pl_app.connector("node").connect(pl_node.connector("apps")) return pl_app -def exec_ccncatchunks(slicename, hostname): +def exec_ccncatchunks(slicename, port, hostname): print "Starting Vlc streamming ..." + + command = 'PATH=$PATH:$(ls | egrep nepi-ccnd- | head -1)/bin;' + if port: + command += "CCN_LOCAL_PORT=%d " % port + command += ' ccncatchunks2 ccnx:/VIDEO' + login = "%s@%s" % (slicename, hostname) - command = 'PATH=$PATH:$(ls | egrep nepi-ccnd- | head -1)/bin; ccncatchunks2 ccnx:/VIDEO' proc1 = subprocess.Popen(['ssh', login, command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = False) proc2 = subprocess.Popen(['vlc', '--sub-filter', 'marq', @@ -126,7 +139,7 @@ def exec_ccncatchunks(slicename, hostname): return proc2 def create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, - port_base, root_dir): + port_base, root_dir, port): # Create the experiment description object exp_desc = ExperimentDescription() @@ -142,16 +155,16 @@ def create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh pl_nodes = dict() ccn_routes = dict() prev_hostname = None - port = 49695 + mport = port for hostname in hostnames: pl_node = create_node(hostname, pl_inet, slice_desc) pl_nodes[hostname] = pl_node ccn_routes[hostname] = list() if prev_hostname: - ccn_routes[hostname].append((prev_hostname, port)) - ccn_routes[prev_hostname].append((hostname, port)) - port +=1 + ccn_routes[hostname].append((prev_hostname, mport)) + ccn_routes[prev_hostname].append((hostname, mport)) + mport +=1 prev_hostname = hostname # Get the base network segment (slice vsys_vnet) to assign all the IP addresses @@ -180,21 +193,21 @@ def create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh # Create ccnd daemons in all nodes for hostname, pl_node in pl_nodes.iteritems(): routes = ccn_routes[hostname] - create_ccnd(pl_node, hostname, routes, slice_desc) + create_ccnd(pl_node, port, hostname, routes, slice_desc) # Create a ccnsendchunks application box in the first node hostname = hostnames[0] pl_node = pl_nodes[hostname] - pl_app = create_ccnsendchunks(pl_node, slice_desc) + pl_app = create_ccnsendchunks(pl_node, port, slice_desc) return exp_desc, pl_nodes, hostname, pl_app def run(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, - port_base, root_dir): + port_base, root_dir, port): exp_desc, pl_nodes, hostname, pl_app = create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, port_base, - root_dir) + root_dir, port) xml = exp_desc.to_xml() controller = ExperimentController(xml, root_dir) @@ -206,7 +219,7 @@ def run(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, proc = None if not TERMINATE: hostname = hostnames[-1] - proc = exec_ccncatchunks(slicename, hostname) + proc = exec_ccncatchunks(slicename, port, hostname) while not TERMINATE and proc and proc.poll() is None: time.sleep(0.5) @@ -249,8 +262,9 @@ if __name__ == '__main__': 'planetlabpc2.upf.edu', 'planet2.elte.hu', 'planetlab2.esprit-tn.com' ] + ccn_local_port = os.environ.get('CCN_LOCAL_PORT', 49695) - usage = "usage: %prog -s -H -k -u -p -v -N -c " + usage = "usage: %prog -s -H -k -u -p -v -N -c -P " parser = OptionParser(usage=usage) parser.add_option("-s", "--slicename", dest="slicename", @@ -275,6 +289,10 @@ if __name__ == '__main__': parser.add_option("-c", "--node-count", dest="node_count", help="Number of nodes to use", default=5, type="str") + parser.add_option("-P", "--ccn-local-port", dest="port", + help="Port to bind the CCNx daemon", + default=ccn_local_port, type="int") + (options, args) = parser.parse_args() hostnames = map(string.strip, options.hostnames.split(",")) if options.hostnames else default_hostnames @@ -286,7 +304,8 @@ if __name__ == '__main__': pl_user= options.pl_user pl_pwd = options.pl_pwd pl_ssh_key = options.pl_ssh_key + port = options.port run(hostnames, vsys_vnet, slicename, pl_host, pl_user, pl_pwd, pl_ssh_key, - port_base, root_dir) + port_base, root_dir, port) diff --git a/examples/ccnx/planetlab_ccnx_unicast.py b/examples/ccnx/planetlab_ccnx_unicast.py index 1d1e28d6..78080815 100644 --- a/examples/ccnx/planetlab_ccnx_unicast.py +++ b/examples/ccnx/planetlab_ccnx_unicast.py @@ -65,12 +65,11 @@ def create_node(hostname, pl_inet, slice_desc): pl_node.connector("devs").connect(pl_iface.connector("node")) return pl_node -def create_ccnd(pl_node, routes, slice_desc): +def create_ccnd(pl_node, port, routes, slice_desc): pl_app = slice_desc.create("CCNxDaemon") # We can specify a default ccnx version to be either ccnx-0.5.1 or ccnx-0.6.0 - #pl_app.set_attribute_value("ccnxversion", "ccnx-0.5.1") - + #pl_app.set_attribute_value("ccnxVersion", "ccnx-0.5.1") # We can also specify a custom local source and build and install directives path_to_source = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ccnx-0.6.0rc3.tar.gz") @@ -80,42 +79,60 @@ def create_ccnd(pl_node, routes, slice_desc): "cd ./ccnx-0.6.0rc3 && " "./configure && make ") pl_app.set_attribute_value("install", "cp -r ./ccnx-0.6.0rc3/bin ${SOURCES}") - # We use a wildcard to replace the public IP address of the node during runtime + + # We use a wildcard to replace the public IP address of the node during runtime, + # once this IP is known routes = "|".join(map(lambda route: "udp {#[iface_%s].addr[0].[Address]#}" % route, routes)) - # Add multicast ccn routes - pl_app.set_attribute_value("ccnroutes", routes) + # Add unicast ccn routes + pl_app.set_attribute_value("ccnRoutes", routes) + + # Use a specific port to bind the CCNx daemon + if port: + pl_app.set_attribute_value("ccnLocalPort", port) + pl_app.enable_trace("stdout") pl_app.enable_trace("stderr") pl_app.connector("node").connect(pl_node.connector("apps")) -def create_ccnsendchunks(pl_node, slice_desc): +def create_ccnsendchunks(pl_node, port, slice_desc): pl_app = slice_desc.create("Application") path_to_video = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../big_buck_bunny_240p_mpeg4_lq.ts") pl_app.set_attribute_value("stdin", path_to_video) - pl_app.set_attribute_value("command", "ccnsendchunks ccnx:/VIDEO") + + command = "ccnsendchunks ccnx:/VIDEO" + if port: + command = "CCN_LOCAL_PORT=%d %s " % (port, command) + pl_app.set_attribute_value("command", command) + pl_app.enable_trace("stdout") pl_app.enable_trace("stderr") pl_app.connector("node").connect(pl_node.connector("apps")) return pl_app -def exec_ccncatchunks(slicename, hostname): +def exec_ccncatchunks(slicename, port, hostname): print "Getting video chunks from %s ..." % hostname + + command = 'PATH=$PATH:$(ls | egrep nepi-ccnd- | head -1)/bin;' + if port: + command += "CCN_LOCAL_PORT=%d " % port + command += ' ccncatchunks2 ccnx:/VIDEO' + login = "%s@%s" % (slicename, hostname) - command = 'PATH=$PATH:$(ls | egrep nepi-ccnd- | head -1)/bin; ccncatchunks2 ccnx:/VIDEO' proc1 = subprocess.Popen(['ssh', login, command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = False) + proc2 = subprocess.Popen(['vlc', '--sub-filter', 'marq', '--marq-marquee', '(c) copyright 2008, Blender Foundation / www.bigbuckbunny.org', '--marq-position=8', - '--no-video-title-show', '-'], + '--no-video-title-show', '-'], stdin=proc1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return proc2 def create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, - port_base, root_dir, delay): + port_base, root_dir, delay, port): # Create the experiment description object exp_desc = ExperimentDescription() @@ -144,21 +161,21 @@ def create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh for hostname in hostnames: pl_node = pl_nodes[hostname] routes = ccn_routes[hostname] - create_ccnd(pl_node, routes, slice_desc) + create_ccnd(pl_node, port, routes, slice_desc) # Create a ccnsendchunks application box in the first node hostname = hostnames[0] pl_node = pl_nodes[hostname] - pl_app = create_ccnsendchunks(pl_node, slice_desc) + pl_app = create_ccnsendchunks(pl_node, port, slice_desc) return exp_desc, pl_nodes, hostname, pl_app def run(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, - port_base, root_dir, delay): + port_base, root_dir, delay, port): exp_desc, pl_nodes, hostname, pl_app = create_ed(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, port_base, - root_dir, delay) + root_dir, delay, port) xml = exp_desc.to_xml() controller = ExperimentController(xml, root_dir) @@ -170,7 +187,7 @@ def run(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, proc1 = None if not TERMINATE: hostname = hostnames[-1] - proc1 = exec_ccncatchunks(slicename, hostname) + proc1 = exec_ccncatchunks(slicename, port, hostname) if not TERMINATE and proc1: time.sleep(delay) @@ -178,7 +195,7 @@ def run(hostnames, vsys_vnet, slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, proc2 = None if not TERMINATE: hostname = hostnames[-2] - proc2 = exec_ccncatchunks(slicename, hostname) + proc2 = exec_ccncatchunks(slicename, port, hostname) while not TERMINATE and proc1 and proc2 and proc2.poll() is None: time.sleep(0.5) @@ -229,8 +246,9 @@ if __name__ == '__main__': 'planetlabpc2.upf.edu', 'planet2.elte.hu', 'planetlab2.esprit-tn.com' ] + ccn_local_port = os.environ.get('CCN_LOCAL_PORT') - usage = "usage: %prog -s -H -k -u -p -v -N -c -d " + usage = "usage: %prog -s -H -k -u -p -v -N -c -d -P " parser = OptionParser(usage=usage) parser.add_option("-s", "--slicename", dest="slicename", @@ -258,6 +276,9 @@ if __name__ == '__main__': parser.add_option("-d", "--delay", dest="delay", help="Time to wait before retrieveing the second video stream in seconds", default=40, type="int") + parser.add_option("-P", "--ccn-local-port", dest="port", + help="Port to bind the CCNx daemon", + default=ccn_local_port, type="int") (options, args) = parser.parse_args() hostnames = map(string.strip, options.hostnames.split(",")) if options.hostnames else default_hostnames @@ -270,7 +291,8 @@ if __name__ == '__main__': pl_pwd = options.pl_pwd pl_ssh_key = options.pl_ssh_key delay = options.delay + port = options.port run(hostnames, vsys_vnet, slicename, pl_host, pl_user, pl_pwd, pl_ssh_key, - port_base, root_dir, delay) + port_base, root_dir, delay, port) diff --git a/src/nepi/testbeds/planetlab/application.py b/src/nepi/testbeds/planetlab/application.py index da4748ae..a192707d 100644 --- a/src/nepi/testbeds/planetlab/application.py +++ b/src/nepi/testbeds/planetlab/application.py @@ -19,6 +19,8 @@ import re from nepi.util.constants import ApplicationStatus as AS +_ccnre = re.compile("\s*(udp|tcp)\s+(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\s*$") + class Dependency(object): """ A Dependency is in every respect like an application. @@ -1105,9 +1107,9 @@ class CCNxDaemon(Application): super(CCNxDaemon,self).__init__(api) # Attributes - self.ccnroutes = None - self.ccnsources = None - self.ccnxversion = "ccnx-0.6.0" + self.ccnLocalPort = None + self.ccnRoutes = None + self.ccnxVersion = "ccnx-0.6.0" self.ccnx_0_5_1_sources = "http://www.ccnx.org/releases/ccnx-0.5.1.tar.gz" self.ccnx_0_6_0_sources = "http://www.ccnx.org/releases/ccnx-0.6.0.tar.gz" @@ -1171,27 +1173,40 @@ class CCNxDaemon(Application): def setup(self): # setting ccn sources if not self.build: - if self.ccnxversion == 'ccnx-0.6.0': + if self.ccnxVersion == 'ccnx-0.6.0': self.build = self.ccnx_0_6_0_build - elif self.ccnxversion == 'ccnx-0.5.1': + elif self.ccnxVersion == 'ccnx-0.5.1': self.build = self.ccnx_0_5_1_build if not self.install: - if self.ccnxversion == 'ccnx-0.6.0': + if self.ccnxVersion == 'ccnx-0.6.0': self.install = self.ccnx_0_6_0_install - elif self.ccnxversion == 'ccnx-0.5.1': + elif self.ccnxVersion == 'ccnx-0.5.1': self.install = self.ccnx_0_5_1_install super(CCNxDaemon, self).setup() def start(self): + self.command = "" + if self.ccnLocalPort: + self.command = "export CCN_LOCAL_PORT=%s ; " % self.ccnLocalPort + self.command += " ccndstart " + # configure ccn routes - routes = "" - if self.ccnroutes: + if self.ccnRoutes: + routes = self.ccnRoutes.split("|") + + if self.ccnLocalPort: + routes = map(lambda route: "%s %s" %(route, + self.ccnLocalPort) if _ccnre.match(route) else route, + routes) + routes = map(lambda route: "ccndc add ccnx:/ %s" % route, - self.ccnroutes.split("|")) - routes = "; " + " ; ".join(routes) - self.command = "ccndstart %s" % routes + routes) + + routescmd = " ; ".join(routes) + self.command += " ; " + self.command += routescmd # Start will be invoked in prestart step super(CCNxDaemon, self).start() @@ -1199,7 +1214,12 @@ class CCNxDaemon(Application): def kill(self): self._logger.info("Killing %s", self) - cmd = self._replace_paths("${SOURCES}/bin/ccndstop") + command = "${SOURCES}/bin/ccndstop" + + if self.ccnLocalPort: + self.command = "export CCN_LOCAL_PORT=%s; %s" % (self.ccnLocalPort, command) + + cmd = self._replace_paths(command) command = cStringIO.StringIO() command.write(cmd) command.seek(0) diff --git a/src/nepi/testbeds/planetlab/metadata.py b/src/nepi/testbeds/planetlab/metadata.py index 39f506dc..e69f3e70 100644 --- a/src/nepi/testbeds/planetlab/metadata.py +++ b/src/nepi/testbeds/planetlab/metadata.py @@ -1127,7 +1127,7 @@ attributes = dict({ "validation_function": validation.is_string }), "ccnroutes": dict({ - "name": "ccnroutes", + "name": "ccnRoutes", "help": "Route can be static (e.g. udp ip) or multicast (e.g. udp 224.0.0.204 2869). To separate different route use '|' ", "type": Attribute.STRING, "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable, @@ -1179,16 +1179,8 @@ attributes = dict({ "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable, "validation_function": validation.is_string }), - "ccnsources": dict({ - "name": "ccnsources", - "help": "Path to local tar with ccnx sources." - "Default source is http://www.ccnx.org/releases/ccnx-0.5.1.tar.gz", - "type": Attribute.STRING, - "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable, - "validation_function": validation.is_string - }), "ccnxversion": dict({ - "name": "ccnxversion", + "name": "ccnxVersion", "help": "Version of ccnx source code to install in the node.", "type": Attribute.ENUM, "value": "ccnx-0.6.0", @@ -1197,6 +1189,16 @@ attributes = dict({ "ccnx-0.5.1"], "validation_function": validation.is_enum, }), + "ccnlocalport" : dict({ + "name" : "ccnLocalPort", + "help" : "Local port to bind the ccn daemon. (i.e. CCN_LOCAL_PORT=)", + "type" : Attribute.INTEGER, + "flags" : Attribute.DesignInvisible | \ + Attribute.ExecInvisible | \ + Attribute.ExecImmutable | \ + Attribute.Metadata, + "validation_function" : validation.is_integer, + }), "build": dict({ "name": "build", "help": "Build commands to execute after deploying the sources. " @@ -1583,7 +1585,7 @@ factories_info = dict({ "status_function": status_application, "stop_function": stop_application, "configure_function": configure_application, - "box_attributes": ["ccnroutes", "ccnsources", "build", + "box_attributes": ["ccnroutes", "build", "ccnlocalport", "install", "ccnxversion", "sources"], "connector_types": ["node"], "traces": ["stdout", "stderr", "buildlog", "output"],