Merge classqueue
authorClaudio-Daniel Freire <claudio-daniel.freire@inria.fr>
Wed, 30 May 2012 00:26:07 +0000 (21:26 -0300)
committerClaudio-Daniel Freire <claudio-daniel.freire@inria.fr>
Wed, 30 May 2012 00:26:07 +0000 (21:26 -0300)
102 files changed:
examples/Multicast/multicast_experiment.py [changed mode: 0644->0755]
examples/POPI/popi-tun-classfilter-2MB-q500-pl-hibw.xml
examples/POPI/popi-tun-classfilter-2MB-q500-pl.xml
examples/POPI/run_one_experiment.py [changed mode: 0644->0755]
examples/POPI/run_popi_experiments.py [changed mode: 0644->0755]
examples/big_buck_bunny_license_information [new file with mode: 0644]
examples/ccnx/ccnx-0.6.0rc3.tar.gz [new file with mode: 0644]
examples/ccnx/planetlab_ccnx_multicast.py [new file with mode: 0644]
examples/ccnx/planetlab_ccnx_unicast.py [new file with mode: 0644]
examples/daemonized_testbed_controller.py [new file with mode: 0644]
examples/fd_cross_testbed_experiment.py [new file with mode: 0644]
examples/multicast_overlay.py [deleted file]
examples/netns_routing_experiment.py [new file with mode: 0644]
examples/netns_xterm_experiment.py [new file with mode: 0644]
examples/ns3_runtime_attribute_change.py [new file with mode: 0644]
examples/planetlab_simple_experiment.py [new file with mode: 0644]
examples/roads09.py [deleted file]
examples/tunnel_cross_testbed_experiment.py [new file with mode: 0644]
examples/vlc_wireless_netns_ns3.py [deleted file]
examples/wimax_ns3.py [deleted file]
examples/wimax_overlay.py [deleted file]
examples/wireless_overlay.py [deleted file]
setup.py
src/nepi/core/attributes.py
src/nepi/core/connector.py
src/nepi/core/design.py
src/nepi/core/execute.py
src/nepi/core/factory.py
src/nepi/core/metadata.py
src/nepi/core/testbed_impl.py
src/nepi/testbeds/netns/__init__.py
src/nepi/testbeds/netns/constants.py
src/nepi/testbeds/netns/execute.py
src/nepi/testbeds/netns/metadata.py
src/nepi/testbeds/ns3/__init__.py
src/nepi/testbeds/ns3/attributes_metadata.py
src/nepi/testbeds/ns3/connection_metadata.py
src/nepi/testbeds/ns3/constants.py
src/nepi/testbeds/ns3/execute.py
src/nepi/testbeds/ns3/factories_metadata.py
src/nepi/testbeds/ns3/metadata.py
src/nepi/testbeds/ns3/ns3_bindings_import.py
src/nepi/testbeds/ns3/traces_metadata.py
src/nepi/testbeds/ns3/util.py [new file with mode: 0644]
src/nepi/testbeds/ns3/validation.py
src/nepi/testbeds/planetlab/__init__.py
src/nepi/testbeds/planetlab/application.py
src/nepi/testbeds/planetlab/constants.py
src/nepi/testbeds/planetlab/execute.py
src/nepi/testbeds/planetlab/interfaces.py
src/nepi/testbeds/planetlab/metadata.py
src/nepi/testbeds/planetlab/multicast.py
src/nepi/testbeds/planetlab/node.py
src/nepi/testbeds/planetlab/plcapi.py
src/nepi/testbeds/planetlab/resourcealloc.py
src/nepi/testbeds/planetlab/scripts/tun_connect.py
src/nepi/testbeds/planetlab/tunproto.py
src/nepi/testbeds/planetlab/util.py
src/nepi/util/constants.py
src/nepi/util/environ.py
src/nepi/util/graphical_info.py
src/nepi/util/guid.py
src/nepi/util/ipaddr2.py
src/nepi/util/parallel.py
src/nepi/util/parser/_xml.py
src/nepi/util/parser/base.py
src/nepi/util/parser/sfa.py [new file with mode: 0644]
src/nepi/util/proxy.py
src/nepi/util/server.py
src/nepi/util/sfiapi.py [new file with mode: 0644]
src/nepi/util/tags.py
src/nepi/util/tunchannel.py
src/nepi/util/tunchannel_impl.py
src/nepi/util/validation.py
test/core/design.py
test/core/execute.py
test/core/integration.py
test/lib/mock/__init__.py
test/lib/mock/constants.py
test/lib/mock/execute.py
test/lib/mock/metadata.py
test/lib/mock2/__init__.py
test/lib/mock2/constants.py
test/lib/mock2/execute.py
test/lib/mock2/metadata.py
test/lib/test_util.py
test/testbeds/netns/design.py
test/testbeds/netns/execute.py
test/testbeds/netns/integration.py
test/testbeds/ns3/design.py
test/testbeds/ns3/execute.py
test/testbeds/ns3/execute2.py
test/testbeds/ns3/integration.py
test/testbeds/planetlab/design.py
test/testbeds/planetlab/execute.py
test/testbeds/planetlab/integration.py
test/testbeds/planetlab/integration_cross.py
test/testbeds/planetlab/integration_multi.py
test/testbeds/planetlab/integration_ns3.py
test/util/tunchannel.py [new file with mode: 0644]
util_scripts/pl_maintenance.py [new file with mode: 0644]
util_scripts/tunbench.py [moved from tunbench.py with 92% similarity]

old mode 100644 (file)
new mode 100755 (executable)
index b54157a..0f93259
@@ -91,7 +91,7 @@ class PlanetLabMulticastOverlay:
         pl_desc.set_attribute_value("plcHost", plchost)
         pl_desc.set_attribute_value("tapPortBase", self.port_base)
         pl_desc.set_attribute_value("p2pDeployment", not self.no_p2p_deploy)
-        pl_desc.set_attribute_value("dedicatedSlice", True)
+        pl_desc.set_attribute_value("cleanProc", True)
         pl_desc.set_attribute_value("plLogLevel", "INFO")
         
         return pl_desc, exp_desc
index 976fb55..6ee1bc7 100644 (file)
@@ -7,7 +7,7 @@
                 <attribute name="slice" type="STRING" value="##plslice##"/>
                 <attribute name="plLogLevel" type="STRING" value="INFO"/>
                 <attribute name="logLevel" type="STRING" value="Debug"/>
-                <attribute name="dedicatedSlice" type="BOOL" value="True"/>
+                <attribute name="cleanProc" type="BOOL" value="True"/>
                 <attribute name="plcUrl" type="STRING" value="https://%(hostname)s:443/PLCAPI/"/>
                 <attribute name="recoveryPolicy" type="STRING" value="Recover"/>
                 <attribute name="p2pDeployment" type="BOOL" value="False"/>
index c73848d..ddf70bc 100644 (file)
@@ -7,7 +7,7 @@
                 <attribute name="slice" type="STRING" value="##plslice##"/>
                 <attribute name="plLogLevel" type="STRING" value="INFO"/>
                 <attribute name="logLevel" type="STRING" value="Debug"/>
-                <attribute name="dedicatedSlice" type="BOOL" value="True"/>
+                <attribute name="cleanProc" type="BOOL" value="True"/>
                 <attribute name="plcUrl" type="STRING" value="https://%(hostname)s:443/PLCAPI/"/>
                 <attribute name="recoveryPolicy" type="STRING" value="Recover"/>
                 <attribute name="p2pDeployment" type="BOOL" value="False"/>
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/examples/big_buck_bunny_license_information b/examples/big_buck_bunny_license_information
new file mode 100644 (file)
index 0000000..f0b35ff
--- /dev/null
@@ -0,0 +1 @@
+(c) copyright 2008, Blender Foundation / www.bigbuckbunny.org
diff --git a/examples/ccnx/ccnx-0.6.0rc3.tar.gz b/examples/ccnx/ccnx-0.6.0rc3.tar.gz
new file mode 100644 (file)
index 0000000..48d6ff7
Binary files /dev/null and b/examples/ccnx/ccnx-0.6.0rc3.tar.gz differ
diff --git a/examples/ccnx/planetlab_ccnx_multicast.py b/examples/ccnx/planetlab_ccnx_multicast.py
new file mode 100644 (file)
index 0000000..0327d08
--- /dev/null
@@ -0,0 +1,311 @@
+#!/usr/bin/env python
+
+##
+## Experiment topology:
+## 
+##  ccncatchunks                                ccnsendchunks
+##       |                                            |
+##       .->  node1 -- .. -- nodei -- .. -- nodeN   <-.
+##    
+##
+##  - Nodes are connected through an overlay network over the Intenet
+##  - On each node runs a CCNx daemon
+##  - Static multicast entries are added to the CCNx FIB on each node to communicate them in series.
+##    (Nodes only have FIB entries to at most two nodes)
+##
+
+
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+from nepi.util.constants import ApplicationStatus as AS
+import ipaddr
+import math
+from optparse import OptionParser, SUPPRESS_HELP
+import os
+import signal
+import string
+import subprocess
+import tempfile
+import time
+
+# Trak SIGTERM, and set global termination flag instead of dying
+TERMINATE = []
+def _finalize(sig,frame):
+    global TERMINATE
+    TERMINATE.append(None)
+signal.signal(signal.SIGTERM, _finalize)
+signal.signal(signal.SIGINT, _finalize)
+
+def create_slice_desc(slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, 
+        port_base, root_dir, exp_desc):
+    pl_provider = FactoriesProvider("planetlab")
+    slice_desc = exp_desc.add_testbed_description(pl_provider)
+    slice_desc.set_attribute_value("homeDirectory", root_dir)
+    slice_desc.set_attribute_value("slice", slicename)
+    slice_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
+    slice_desc.set_attribute_value("authUser", pl_user)
+    slice_desc.set_attribute_value("authPass", pl_pwd)
+    slice_desc.set_attribute_value("plcHost", plc_host)
+    slice_desc.set_attribute_value("tapPortBase", port_base)
+    # Kills all running processes before starting the experiment
+    slice_desc.set_attribute_value("cleanProc", True)
+    # NOTICE: Setting 'cleanHome' to 'True' will erase all previous
+    # folders in the sliver Home directory, including result files!
+    #slice_desc.set_attribute_value("cleanHome", True)
+    slice_desc.set_attribute_value("plLogLevel", "DEBUG")
+    return slice_desc
+def create_node(hostname, pl_inet, slice_desc):
+    pl_node = slice_desc.create("Node")
+    pl_node.set_attribute_value("hostname", hostname)
+    pl_node.set_attribute_value("label", hostname)
+    pl_iface = slice_desc.create("NodeInterface")
+    pl_iface.connector("inet").connect(pl_inet.connector("devs"))
+    pl_node.connector("devs").connect(pl_iface.connector("node"))
+    return pl_node
+
+def create_tunnel(node, peer, pl_nodes, slice_desc, subnet):
+    pl_node = pl_nodes[node]
+    pl_peer = pl_nodes[peer]
+
+    pl_tun = slice_desc.create("TunInterface")
+    pl_tun.set_attribute_value("label", "tun_%s%s" % (node, peer))
+    pl_node.connector("devs").connect(pl_tun.connector("node"))
+
+    pl_tunpeer = slice_desc.create("TunInterface")
+    pl_tunpeer.set_attribute_value("label", "tun_%s%s" % (peer, node))
+    pl_peer.connector("devs").connect(pl_tunpeer.connector("node"))
+
+    pl_tun.connector("udp").connect(pl_tunpeer.connector("udp"))
+    
+    iterhosts = subnet.iterhosts()
+    addr = iterhosts.next()
+    ip = pl_tun.add_address()
+    ip.set_attribute_value("Address", addr.exploded)
+    ip.set_attribute_value("NetPrefix", subnet.prefixlen)
+
+    peeraddr = iterhosts.next()
+    peerip = pl_tunpeer.add_address()
+    peerip.set_attribute_value("Address", peeraddr.exploded)
+    peerip.set_attribute_value("NetPrefix", subnet.prefixlen)
+
+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)
+    # 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, 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)
+
+    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, 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)
+    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',  '-'], 
+        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, port):
+
+    # Create the experiment description object
+    exp_desc = ExperimentDescription()
+
+    # Create the slice description object
+    slice_desc = create_slice_desc(slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, 
+        port_base, root_dir, exp_desc)
+    
+    # Create the Internet box object
+    pl_inet = slice_desc.create("Internet")
+    
+    # Create the Node boxes
+    pl_nodes = dict()
+    ccn_routes = dict()
+    prev_hostname = None
+    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, mport))
+            ccn_routes[prev_hostname].append((hostname, mport))
+            mport = port if mport != port else port + 1
+        prev_hostname = hostname
+
+    # Get the base network segment (slice vsys_vnet) to assign all the IP addresses
+    # to the virtual interfaces
+    base = ipaddr.IPNetwork(vsys_vnet)
+
+    # Calculate the number of virtual networks required to connect all the nodes 
+    # with all other nodes as the binomial coeficient C(n, 2), with n = #nodes
+    n = len(hostnames)
+    c = n * (n-1) / 2
+
+    # Validate that we can get 'c' /30 subnetworks
+    if c > math.pow(2, (30 - base.prefixlen)):
+        raise RuntimeError("Insufficient address segment %s for experiment", vsys_vnet)
+            
+    # Create the subnetwors iterator 
+    iter_sub = base.iter_subnets(new_prefix=30)
+
+    # Create tunnels between nodes
+    for i, node in enumerate(hostnames):
+        peers = hostnames[i+1:]
+        for peer in peers:
+            subnet = iter_sub.next()
+            create_tunnel(node, peer, pl_nodes, slice_desc, subnet)
+
+    # Create ccnd daemons in all nodes
+    for hostname, pl_node in pl_nodes.iteritems():
+        routes = ccn_routes[hostname]
+        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, 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):
+
+    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, port)
+
+    xml = exp_desc.to_xml()
+    controller = ExperimentController(xml, root_dir)
+    controller.start()
+    
+    while not TERMINATE and controller.status(pl_app.guid) == AS.STATUS_NOT_STARTED:
+        time.sleep(0.5)
+
+    proc = None
+    if not TERMINATE:
+        hostname = hostnames[-1]
+        proc = exec_ccncatchunks(slicename, port, hostname)
+
+    while not TERMINATE and proc and proc.poll() is None:
+        time.sleep(0.5)
+    
+    if proc:
+        if proc.poll() < 1:
+           err = proc.stderr.read()
+           print "ERROR ", err
+        else:   
+           out = proc.stdout.read()
+           print "OUTPUT ", out
+
+    controller.stop()
+    controller.shutdown()
+
+if __name__ == '__main__':
+    root_dir = tempfile.mkdtemp()
+    slicename = os.environ.get("PL_SLICE")
+    pl_host = os.environ.get("PL_HOST", "www.planet-lab.eu")
+    port_base = 2000 + (os.getpid() % 1000) * 13
+    pl_ssh_key = os.environ.get(
+        "PL_SSH_KEY",
+        "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
+    pl_user = os.environ.get('PL_USER')
+    pl_pwd = os.environ.get('PL_PASS')
+    pl_vsys_vnet = os.environ.get('PL_VSYS_NET')
+    pl_hostnames = os.environ.get('PL_HOSTNAMES')
+    default_hostnames = ['openlab02.pl.sophia.inria.fr',
+                 'ple4.ipv6.lip6.fr',
+                 'planetlab2.di.unito.it',
+                 'merkur.planetlab.haw-hamburg.de',
+                 'planetlab1.cs.uit.no',
+                 'planetlab3.cs.st-andrews.ac.uk',
+                 'planetlab2.cs.uoi.gr',
+                 'planetlab3.xeno.cl.cam.ac.uk',
+                 'planet2.inf.tu-dresden.de',
+                 'planetlab2.csg.uzh.ch',
+                 'planetlab2.upm.ro',
+                 'planetlab-um00.di.uminho.pt',
+                 'planetlabpc2.upf.edu',
+                 'planet2.elte.hu',
+                 'planetlab2.esprit-tn.com' ]
+    ccn_local_port = os.environ.get('CCN_LOCAL_PORT', 49695)
+
+    usage = "usage: %prog -s <pl_slice> -H <pl_host> -k <ssh_key> -u <pl_user> -p <pl_password> -v <vsys_vnet> -N <host_names> -c <node_count> -P <ccn-local-port>"
+
+    parser = OptionParser(usage=usage)
+    parser.add_option("-s", "--slicename", dest="slicename", 
+            help="PlanetLab slicename", default=slicename, type="str")
+    parser.add_option("-H", "--pl-host", dest="pl_host", 
+            help="PlanetLab site (e.g. www.planet-lab.eu)", 
+            default=pl_host, type="str")
+    parser.add_option("-k", "--ssh-key", dest="pl_ssh_key", 
+            help="Path to private ssh key used for PlanetLab authentication", 
+            default=pl_ssh_key, type="str")
+    parser.add_option("-u", "--pl-user", dest="pl_user", 
+            help="PlanetLab account user (i.e. Registration email address)", 
+            default=pl_user, type="str")
+    parser.add_option("-p", "--pl-pwd", dest="pl_pwd", 
+            help="PlanetLab account password", default=pl_pwd, type="str")
+    parser.add_option("-v", "--vsys-vnet", dest="vsys_vnet", 
+            help="Value of the vsys_vnet tag addigned to your slice. (e.g. 192.168.3.0/16)", 
+            default=pl_vsys_vnet, type="str")
+    parser.add_option("-N", "--host-names", dest="hostnames", 
+            help="Comma separated list of PlanetLab hostnames to use", 
+            default=pl_hostnames, type="str")
+    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
+    if options.node_count > 0 and options.node_count < len(hostnames):
+       hostnames = hostnames[0:options.node_count]
+    vsys_vnet = options.vsys_vnet
+    slicename = options.slicename
+    pl_host = options.pl_host
+    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)
+
diff --git a/examples/ccnx/planetlab_ccnx_unicast.py b/examples/ccnx/planetlab_ccnx_unicast.py
new file mode 100644 (file)
index 0000000..7808081
--- /dev/null
@@ -0,0 +1,298 @@
+#!/usr/bin/env python
+
+##
+## Experiment topology:
+## 
+##  ccncatchunks                                ccnsendchunks
+##       |                                            |
+##       .->  node1 -- .. -- nodei -- .. -- nodeN   <-.
+##    
+##
+##  - Nodes are connected through Intenet
+##  - On each node runs a CCNx daemon
+##  - Static entries are added to the CCNx FIB on each node to communicate them in series.
+##    (Nodes only have FIB entries to at most two nodes)
+##
+
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+from nepi.util.constants import ApplicationStatus as AS
+import ipaddr
+import math
+from optparse import OptionParser, SUPPRESS_HELP
+import os
+import signal
+import string
+import subprocess
+import tempfile
+import time
+
+# Trak SIGTERM, and set global termination flag instead of dying
+TERMINATE = []
+def _finalize(sig,frame):
+    global TERMINATE
+    TERMINATE.append(None)
+signal.signal(signal.SIGTERM, _finalize)
+signal.signal(signal.SIGINT, _finalize)
+
+def create_slice_desc(slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, 
+        port_base, root_dir, exp_desc):
+    pl_provider = FactoriesProvider("planetlab")
+    slice_desc = exp_desc.add_testbed_description(pl_provider)
+    slice_desc.set_attribute_value("homeDirectory", root_dir)
+    slice_desc.set_attribute_value("slice", slicename)
+    slice_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
+    slice_desc.set_attribute_value("authUser", pl_user)
+    slice_desc.set_attribute_value("authPass", pl_pwd)
+    slice_desc.set_attribute_value("plcHost", plc_host)
+    slice_desc.set_attribute_value("tapPortBase", port_base)
+    slice_desc.set_attribute_value("p2pDeployment", True)
+    # Kills all running processes before starting the experiment
+    slice_desc.set_attribute_value("cleanProc", True)
+    # NOTICE: Setting 'cleanHome' to 'True' will erase all previous
+    # folders in the sliver Home directory, including result files!
+    #slice_desc.set_attribute_value("cleanHome", True)
+    slice_desc.set_attribute_value("plLogLevel", "DEBUG")
+    return slice_desc
+def create_node(hostname, pl_inet, slice_desc):
+    pl_node = slice_desc.create("Node")
+    pl_node.set_attribute_value("hostname", hostname)
+    pl_node.set_attribute_value("label", hostname)
+    pl_iface = slice_desc.create("NodeInterface")
+    pl_iface.set_attribute_value("label", "iface_%s" % hostname)
+    pl_iface.connector("inet").connect(pl_inet.connector("devs"))
+    pl_node.connector("devs").connect(pl_iface.connector("node"))
+    return pl_node
+
+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")
+    # 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")
+    pl_app.set_attribute_value("sources", path_to_source)
+    pl_app.set_attribute_value("build", 
+            "tar xzf ${SOURCES}/ccnx-0.6.0rc3.tar.gz && "
+            "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,
+    # once this IP is known
+    routes = "|".join(map(lambda route: "udp {#[iface_%s].addr[0].[Address]#}" % route, 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, 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)
+
+    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, 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)
+    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', '-'], 
+        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):
+
+    # Create the experiment description object
+    exp_desc = ExperimentDescription()
+
+    # Create the slice description object
+    slice_desc = create_slice_desc(slicename, plc_host, pl_user, pl_pwd, pl_ssh_key, 
+        port_base, root_dir, exp_desc)
+    
+    # Create the Internet box object
+    pl_inet = slice_desc.create("Internet")
+    
+    # Create the Node boxes
+    pl_nodes = dict()
+    ccn_routes = dict()
+    prev_hostname = None
+    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)
+            ccn_routes[prev_hostname].append(hostname)
+        prev_hostname = hostname
+     
+    for hostname in hostnames:
+        pl_node = pl_nodes[hostname] 
+        routes = ccn_routes[hostname]
+        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, 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):
+
+    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, port)
+
+    xml = exp_desc.to_xml()
+    controller = ExperimentController(xml, root_dir)
+    controller.start()
+    
+    while not TERMINATE and controller.status(pl_app.guid) == AS.STATUS_NOT_STARTED:
+        time.sleep(0.5)
+
+    proc1 = None
+    if not TERMINATE:
+        hostname = hostnames[-1]
+        proc1 = exec_ccncatchunks(slicename, port, hostname)
+
+    if not TERMINATE and proc1:
+        time.sleep(delay)
+
+    proc2 = None
+    if not TERMINATE:
+        hostname = hostnames[-2]
+        proc2 = exec_ccncatchunks(slicename, port, hostname)
+
+    while not TERMINATE and proc1 and proc2 and proc2.poll() is None:
+        time.sleep(0.5)
+   
+    if proc1:
+        if proc1.poll() < 1:
+           err = proc1.stderr.read()
+           print "Stream 1 ERROR ", err
+        else:   
+           out = proc1.stdout.read()
+           print "Stream 1 OUTPUT ", out
+
+    if proc2:
+        if proc2.poll() < 1:
+           err = proc2.stderr.read()
+           print "Stream 2 ERROR ", err
+        else:   
+           out = proc2.stdout.read()
+           print "Stream 2 OUTPUT ", out
+
+    controller.stop()
+    controller.shutdown()
+
+if __name__ == '__main__':
+    root_dir = tempfile.mkdtemp()
+    slicename = os.environ.get("PL_SLICE")
+    pl_host = os.environ.get("PL_HOST", "www.planet-lab.eu")
+    port_base = 2000 + (os.getpid() % 1000) * 13
+    pl_ssh_key = os.environ.get(
+        "PL_SSH_KEY",
+        "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
+    pl_user = os.environ.get('PL_USER')
+    pl_pwd = os.environ.get('PL_PASS')
+    pl_vsys_vnet = os.environ.get('PL_VSYS_NET')
+    pl_hostnames = os.environ.get('PL_HOSTNAMES')
+    default_hostnames = ['openlab02.pl.sophia.inria.fr',
+                 'ple4.ipv6.lip6.fr',
+                 'planetlab2.di.unito.it',
+                 'merkur.planetlab.haw-hamburg.de',
+                 'planetlab1.cs.uit.no',
+                 'planetlab3.cs.st-andrews.ac.uk',
+                 'planetlab2.cs.uoi.gr',
+                 'planetlab3.xeno.cl.cam.ac.uk',
+                 'planet2.inf.tu-dresden.de',
+                 'planetlab2.csg.uzh.ch',
+                 'planetlab2.upm.ro',
+                 'planetlab-um00.di.uminho.pt',
+                 'planetlabpc2.upf.edu',
+                 'planet2.elte.hu',
+                 'planetlab2.esprit-tn.com' ]
+    ccn_local_port = os.environ.get('CCN_LOCAL_PORT')
+
+    usage = "usage: %prog -s <pl_slice> -H <pl_host> -k <ssh_key> -u <pl_user> -p <pl_password> -v <vsys_vnet> -N <host_names> -c <node_count> -d <delay> -P <ccn-local-port>"
+
+    parser = OptionParser(usage=usage)
+    parser.add_option("-s", "--slicename", dest="slicename", 
+            help="PlanetLab slicename", default=slicename, type="str")
+    parser.add_option("-H", "--pl-host", dest="pl_host", 
+            help="PlanetLab site (e.g. www.planet-lab.eu)", 
+            default=pl_host, type="str")
+    parser.add_option("-k", "--ssh-key", dest="pl_ssh_key", 
+            help="Path to private ssh key used for PlanetLab authentication", 
+            default=pl_ssh_key, type="str")
+    parser.add_option("-u", "--pl-user", dest="pl_user", 
+            help="PlanetLab account user (i.e. Registration email address)", 
+            default=pl_user, type="str")
+    parser.add_option("-p", "--pl-pwd", dest="pl_pwd", 
+            help="PlanetLab account password", default=pl_pwd, type="str")
+    parser.add_option("-v", "--vsys-vnet", dest="vsys_vnet", 
+            help="Value of the vsys_vnet tag addigned to your slice. (e.g. 192.168.3.0/16)", 
+            default=pl_vsys_vnet, type="str")
+    parser.add_option("-N", "--host-names", dest="hostnames", 
+            help="Comma separated list of PlanetLab hostnames to use", 
+            default=pl_hostnames, type="str")
+    parser.add_option("-c", "--node-count", dest="node_count", 
+            help="Number of nodes to use", 
+            default=9, type="str")
+    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
+    if options.node_count > 0 and options.node_count < len(hostnames):
+       hostnames = hostnames[0:options.node_count]
+    vsys_vnet = options.vsys_vnet
+    slicename = options.slicename
+    pl_host = options.pl_host
+    pl_user= options.pl_user
+    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)
+
diff --git a/examples/daemonized_testbed_controller.py b/examples/daemonized_testbed_controller.py
new file mode 100644 (file)
index 0000000..2110d70
--- /dev/null
@@ -0,0 +1,85 @@
+#!/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
+from nepi.util import proxy
+from nepi.util.constants import DeploymentConfiguration as DC
+import getpass
+import tempfile
+import time
+import os
+
+user = getpass.getuser()
+root_dir = tempfile.mkdtemp()
+netns_dir = os.path.join(root_dir, "netns")
+daemon_dir = os.path.join(netns_dir, "daemon")
+os.makedirs(daemon_dir)
+
+
+exp_desc = ExperimentDescription()
+
+netns_provider = FactoriesProvider("netns")
+netns_desc = exp_desc.add_testbed_description(netns_provider)
+netns_desc.set_attribute_value("homeDirectory", netns_dir)
+#netns_desc.set_attribute_value("enableDebug", True)
+netns_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
+netns_desc.set_attribute_value(DC.ROOT_DIRECTORY, daemon_dir)
+netns_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
+netns_desc.set_attribute_value(DC.USE_SUDO, True)
+
+node1 = netns_desc.create("Node")
+node2 = netns_desc.create("Node")
+
+iface12 = netns_desc.create("P2PNodeInterface")
+iface12.set_attribute_value("up", True)
+node1.connector("devs").connect(iface12.connector("node"))
+
+iface21 = netns_desc.create("P2PNodeInterface")
+iface21.set_attribute_value("up", True)
+node2.connector("devs").connect(iface21.connector("node"))
+
+iface12.connector("p2p").connect(iface21.connector("p2p"))
+
+ip12 = iface12.add_address()
+ip12.set_attribute_value("Address", "192.168.0.1")
+ip12.set_attribute_value("NetPrefix", 30)
+
+ip21 = iface21.add_address()
+ip21.set_attribute_value("Address", "192.168.0.2")
+ip21.set_attribute_value("NetPrefix", 30)
+
+app1 = netns_desc.create("Application")
+app1.set_attribute_value("command", "ping -qc 10 192.168.0.1")
+app1.set_attribute_value("user", user)
+app1.connector("node").connect(node1.connector("apps"))
+
+app1.enable_trace("stdout")
+
+xml = exp_desc.to_xml()
+
+controller_access_config = proxy.AccessConfiguration()
+controller_access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
+controller_access_config.set_attribute_value(DC.ROOT_DIRECTORY, root_dir)
+controller_access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
+
+controller = proxy.create_experiment_controller(xml, controller_access_config)
+
+controller.start()
+while not controller.is_finished(app1.guid):
+    time.sleep(0.5)
+
+result = controller.trace(app1.guid, "stdout")
+
+controller.stop()
+controller.shutdown()
+
+print result
+
diff --git a/examples/fd_cross_testbed_experiment.py b/examples/fd_cross_testbed_experiment.py
new file mode 100644 (file)
index 0000000..15c219f
--- /dev/null
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#
+# Experiment Topology:
+#
+#  ns-3        |     NETNS 
+#              |
+
+#             fd   
+#  n1 --- n2 ----- n3 --- n4
+#              
+#     0.0     1.0     2.0 
+
+
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+import getpass
+import tempfile
+import time
+
+user = getpass.getuser()
+root_dir = tempfile.mkdtemp()
+
+def create_ns3_node(ns3_desc):
+    node = ns3_desc.create("ns3::Node")
+    ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
+    arp  = ns3_desc.create("ns3::ArpL3Protocol")
+    icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
+    udp = ns3_desc.create("ns3::UdpL4Protocol")
+    node.connector("protos").connect(ipv4.connector("node"))
+    node.connector("protos").connect(arp.connector("node"))
+    node.connector("protos").connect(icmp.connector("node"))
+    node.connector("protos").connect(udp.connector("node"))
+    return node
+
+exp_desc = ExperimentDescription()
+
+ns3_provider = FactoriesProvider("ns3")
+ns3_desc = exp_desc.add_testbed_description(ns3_provider)
+ns3_desc.set_attribute_value("homeDirectory", root_dir)
+ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
+ns3_desc.set_attribute_value("ChecksumEnabled", True)
+
+node1 = create_ns3_node(ns3_desc)
+iface12 = ns3_desc.create("ns3::PointToPointNetDevice")
+queue12 = ns3_desc.create("ns3::DropTailQueue")
+node1.connector("devs").connect(iface12.connector("node"))
+iface12.connector("queue").connect(queue12.connector("dev"))
+ip12 = iface12.add_address()
+ip12.set_attribute_value("Address", "10.0.0.1")
+
+node2 = create_ns3_node(ns3_desc)
+iface21 = ns3_desc.create("ns3::PointToPointNetDevice")
+queue21 = ns3_desc.create("ns3::DropTailQueue")
+node2.connector("devs").connect(iface21.connector("node"))
+iface21.connector("queue").connect(queue21.connector("dev"))
+ip21 = iface21.add_address()
+ip21.set_attribute_value("Address", "10.0.0.2")
+
+chan = ns3_desc.create("ns3::PointToPointChannel")
+iface12.connector("chan").connect(chan.connector("dev2"))
+iface21.connector("chan").connect(chan.connector("dev2"))
+
+iface23 = ns3_desc.create("ns3::FdNetDevice")
+node2.connector("devs").connect(iface23.connector("node"))
+ip23 = iface23.add_address()
+ip23.set_attribute_value("Address", "10.0.1.1")
+
+netns_provider = FactoriesProvider("netns")
+netns_desc = exp_desc.add_testbed_description(netns_provider)
+netns_desc.set_attribute_value("homeDirectory", root_dir)
+#netns_desc.set_attribute_value("enableDebug", True)
+
+node3 = netns_desc.create("Node")
+iface32 = netns_desc.create("TapNodeInterface")
+iface32.set_attribute_value("up", True)
+node3.connector("devs").connect(iface32.connector("node"))
+ip32 = iface32.add_address()
+ip32.set_attribute_value("Address", "10.0.1.2")
+
+iface23.connector("->fd").connect(iface32.connector("fd->"))
+
+iface34 = netns_desc.create("P2PNodeInterface")
+iface34.set_attribute_value("up", True)
+node3.connector("devs").connect(iface34.connector("node"))
+ip34 = iface34.add_address()
+ip34.set_attribute_value("Address", "10.0.2.1")
+
+node4 = netns_desc.create("Node")
+node4.set_attribute_value("forward_X11", True)
+iface43 = netns_desc.create("P2PNodeInterface")
+iface43.set_attribute_value("up", True)
+node4.connector("devs").connect(iface43.connector("node"))
+ip43 = iface43.add_address()
+ip43.set_attribute_value("Address", "10.0.2.2")
+
+iface34.connector("p2p").connect(iface43.connector("p2p"))
+
+route = node1.add_route()
+route.set_attribute_value("Destination", "10.0.2.0")
+route.set_attribute_value("NextHop", "10.0.0.2")
+
+route = node2.add_route()
+route.set_attribute_value("Destination", "10.0.2.0")
+route.set_attribute_value("NextHop", "10.0.1.2")
+
+route = node3.add_route()
+route.set_attribute_value("Destination", "10.0.0.0")
+route.set_attribute_value("NextHop", "10.0.1.1")
+
+route = node4.add_route()
+route.set_attribute_value("Destination", "10.0.0.0")
+route.set_attribute_value("NextHop", "10.0.2.1")
+
+app = netns_desc.create("Application")
+app.set_attribute_value("command", "ping -qc 3 10.0.0.1")
+app.set_attribute_value("user", user)
+app.connector("node").connect(node4.connector("apps"))
+app.enable_trace("stdout")
+      
+xml = exp_desc.to_xml()
+
+controller = ExperimentController(xml, root_dir)
+
+controller.start()
+while not controller.is_finished(app.guid):
+    time.sleep(0.5)
+
+result = controller.trace(app.guid, "stdout")
+
+controller.stop()
+controller.shutdown()
+
+print result
+
diff --git a/examples/multicast_overlay.py b/examples/multicast_overlay.py
deleted file mode 100644 (file)
index 6dcf490..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import getpass
-from optparse import OptionParser
-import os
-import sys
-import shutil
-import tempfile
-import time
-import struct
-import socket
-import operator
-import ipaddr
-import gzip
-import random
-import math
-
-sys.path.append("../../src")
-
-from nepi.core.design import ExperimentDescription, FactoriesProvider
-from nepi.core.execute import ExperimentController
-from nepi.util import proxy
-from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
-from nepi.testbeds.planetlab import util as plutil
-
-class PlanetLabMulticastOverlay:
-    testbed_id = "planetlab"
-    slicename = "inria_nepi12"
-    plchost = "www.planet-lab.eu"
-    plkey = os.environ.get(
-            "PL_SSH_KEY",
-            "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
-    pluser = os.environ.get("PL_USER")
-    plpass = os.environ.get("PL_PASS")
-    vnet = "192.168.2.0"
-    
-    port_base = 2000 + (os.getpid() % 1000) * 13
-    
-    def setUp(self):
-        self.root_dir = tempfile.mkdtemp()
-        self.__class__.port_base = self.__class__.port_base + 100
-
-    def tearDown(self):
-        try:
-            shutil.rmtree(self.root_dir)
-        except:
-            # retry
-            time.sleep(0.1)
-            shutil.rmtree(self.root_dir)
-
-    def make_experiment_desc(self):
-        testbed_id = self.testbed_id
-        slicename = self.slicename
-        plchost = self.plchost
-        pl_ssh_key = self.plkey
-        pl_user = self.pluser
-        pl_pwd = self.plpass
-
-        exp_desc = ExperimentDescription()
-        pl_provider = FactoriesProvider(testbed_id)
-        pl_desc = exp_desc.add_testbed_description(pl_provider)
-        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
-        pl_desc.set_attribute_value("slice", slicename)
-        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
-        pl_desc.set_attribute_value("authUser", pl_user)
-        pl_desc.set_attribute_value("authPass", pl_pwd)
-        pl_desc.set_attribute_value("plcHost", plchost)
-        pl_desc.set_attribute_value("tapPortBase", self.port_base)
-        pl_desc.set_attribute_value("p2pDeployment", True)
-        pl_desc.set_attribute_value("dedicatedSlice", True)
-        pl_desc.set_attribute_value("plLogLevel", "INFO")
-   
-        netns_provider = FactoriesProvider("netns")
-        netns = exp_desc.add_testbed_description(netns_provider)
-        netns.set_attribute_value("homeDirectory", self.root_dir)
-        netns.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
-        netns_root_dir = os.path.join(self.root_dir, "netns")
-        os.mkdir(netns_root_dir)
-        netns.set_attribute_value(DC.ROOT_DIRECTORY, netns_root_dir)
-        netns.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        netns.set_attribute_value(DC.USE_SUDO, True)
-
-        return pl_desc, netns, exp_desc
-
-    def make_pl_tapnode(self, pl, ip, inet = None, label = None, hostname = None, routes = None, mcast = False, mcastrouter = False):
-        if not isinstance(ip, list):
-            ips = [ip]
-        else:
-            ips = ip
-        node1 = pl.create("Node")
-        if label: 
-            node1.set_attribute_value("label", label)
-        if hostname: 
-            node1.set_attribute_value("hostname", hostname)
-        iface1 = pl.create("NodeInterface")
-        if label:
-            iface1.set_attribute_value("label", label+"iface")
-        tap1 = []
-        tap1ip = []
-        for i,ip in enumerate(ips):
-            _tap1 = pl.create("TapInterface")
-            _tap1.set_attribute_value("multicast", True)
-            _tap1.enable_trace("pcap") # for error output
-            if label:
-                _tap1.set_attribute_value("label", label+"tap"+(str(i+1) if i else ""))
-        
-            _tap1ip = self.add_ip_address(_tap1, ip, 32)
-            
-            node1.connector("devs").connect(_tap1.connector("node"))
-            
-            tap1.append(_tap1)
-            tap1ip.append(_tap1ip)
-            
-        inet = inet or pl.create("Internet")
-        node1.connector("devs").connect(iface1.connector("node"))
-        iface1.connector("inet").connect(inet.connector("devs"))
-        
-        for destip, destprefix, nexthop in routes:
-            r1 = self.add_route(node1, destip, destprefix, nexthop)
-        
-        if mcast:
-            fwd = pl.create("MulticastForwarder")
-            fwd.enable_trace("stderr")
-            fwd.connector("node").connect(node1.connector("apps"))
-            if mcastrouter:
-                mrt = pl.create("MulticastRouter")
-                mrt.connector("fwd").connect(fwd.connector("router"))
-                mrt.enable_trace("stderr")
-                
-        return node1, iface1, tap1, tap1ip, inet
-
-    def add_ip_address(self, iface, address, netprefix, broadcast = False):
-        ip = iface.add_address()
-        ip.set_attribute_value("Address", address)
-        ip.set_attribute_value("NetPrefix", netprefix)
-        ip.set_attribute_value("Broadcast", broadcast)
-        return ip
-
-    def add_route(self, node, destination, netprefix, nexthop):
-        route = node.add_route()
-        route.set_attribute_value("Destination", destination)
-        route.set_attribute_value("NetPrefix", netprefix)
-        route.set_attribute_value("NextHop", nexthop)
-        return route
-
-    def add_vlc_base(self, pl, node):
-        app = pl.create("Application")
-        app.set_attribute_value("rpmFusion", True)
-        app.set_attribute_value("depends", "vlc")
-        app.set_attribute_value("command", "vlc --version")
-        app.enable_trace("stdout")
-        app.enable_trace("stderr")
-        node.connector("apps").connect(app.connector("node"))
-        return app
-    
-    def add_vlc_restreamer(self, pl, node):
-        hostname = node.get_attribute_value("hostname")
-        app = self.add_vlc_base(pl, node)
-        app.set_attribute_value("label","vlc_restreamer_%d" % (node.guid,))
-        app.set_attribute_value("command",
-            "vlc -vvv -I dummy"
-            " udp://@239.255.12.42"
-            " --sout '#rtp{port=6060,sdp=rtsp://"+hostname+":8080/test.sdp}'")
-        return app
-    
-    def add_vlc_dumper(self, pl, node):
-        app = self.add_vlc_base(pl, node)
-        app.set_attribute_value("label","vlc_dumper_%d" % (node.guid,))
-        app.set_attribute_value("command",
-            "vlc -vvv -I dummy"
-            " udp://@239.255.12.42"
-            " --sout output")
-        app.enable_trace("output")
-        return app
-    
-    def add_vlc_source(self, netns, node, iflabel):
-        app = netns.create("Application")
-        app.set_attribute_value("user", self.user)
-        app.set_attribute_value("label","vlc_source_%d" % (node.guid,))
-        app.set_attribute_value("command",
-            "vlc -vvv -I dummy "
-            +os.path.basename(self.movie_source)
-            +"--miface-addr {#[%s].addr[0].[Address]#} " % (iflabel,)
-            +"--sout '#udp{dst=239.255.12.42,ttl=64}'")
-        app.connector("node").connect(node.connector("apps"))
-        return app
-    
-    def add_net_monitor(self, pl, node):
-        app = pl.create("Application")
-        app.set_attribute_value("label","network_monitor_%d" % (node.guid,))
-        app.set_attribute_value("command", 
-            r"""head -n 2 /proc/net/dev ; while true ; do cat /proc/net/dev | sed -r 's/.*/'"$(date -R)"': \0/' | grep eth0 ; sleep 1 ; done""")
-        app.enable_trace("stdout")
-        node.connector("apps").connect(app.connector("node"))
-        return app
-    
-    def make_ns_in_pl(self, pl, exp, node1, iface1, root):
-        ns3_testbed_id = "ns3"
-        
-        # Add NS3 support in node1
-        plnepi = pl.create("NepiDependency")
-        plns3 = pl.create("NS3Dependency")
-        plnepi.connector("node").connect(node1.connector("deps"))
-        plns3.connector("node").connect(node1.connector("deps"))
-
-        # Create NS3 testbed running in node1
-        ns3_provider = FactoriesProvider(ns3_testbed_id)
-        ns = exp.add_testbed_description(ns3_provider)
-        ns.set_attribute_value("rootDirectory", root)
-        ns.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
-        ns.set_attribute_value("ChecksumEnabled", True)
-        ns.set_attribute_value(DC.DEPLOYMENT_HOST, "{#[%s].addr[0].[Address]#}" % (
-            iface1.get_attribute_value("label"),))
-        ns.set_attribute_value(DC.DEPLOYMENT_USER, 
-            pl.get_attribute_value("slice"))
-        ns.set_attribute_value(DC.DEPLOYMENT_KEY, 
-            pl.get_attribute_value("sliceSSHKey"))
-        ns.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
-        ns.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
-        ns.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP,
-            "{#[%s].[%s]#}" % (
-                node1.get_attribute_value("label"),
-                ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP,))
-        ns.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        
-        return ns
-  
-    def add_pl_ns_node(self, pl_desc, inet, label_prefix):
-        node = pl_desc.create("Node")
-        node.set_attribute_value("label", label_prefix)
-        iface = pl_desc.create("NodeInterface")
-        iface.set_attribute_value("label", label_prefix+"iface")
-        iface.connector("inet").connect(inet.connector("devs"))
-        node.connector("devs").connect(iface.connector("node"))
-        forwarder = pl_desc.create("MulticastForwarder")
-        forwarder.enable_trace("stderr")
-        node.connector("apps").connect(forwarder.connector("node"))
-        return node, iface
-
-    def add_pl_ns_connection(self, pl_desc, pl_node, pl_addr,
-            ns, ns_node, ns_addr):
-        pl_tap = pl_desc.create("TapInterface")
-        pl_tap.set_attribute_value("tun_cipher", "PLAIN") 
-        self.add_ip_address(pl_tap, pl_addr, 31)
-        pl_node.connector("devs").connect(pl_tap.connector("node"))
-        ns_fdnd = ns.create("ns3::FdNetDevice")
-        ns_node.connector("devs").connect(ns_fdnd.connector("node"))
-        self.add_ip_address(ns_fdnd, ns_addr, 31)
-        pl_tap.connector("fd->").connect(ns_fdnd.connector("->fd"))
-
-    def add_pl_ns_tunchan_connection(self, pl_desc, pl_node, pl_addr,
-            ns, ns_node, ns_addr):
-        pl_tap = pl_desc.create("TunInterface")
-        self.add_ip_address(pl_tap, pl_addr, 31)
-        pl_node.connector("devs").connect(pl_tap.connector("node"))
-        ns_fdnd = ns.create("ns3::FdNetDevice")
-        ns_fdnd.enable_trace("FdPcapTrace")
-        self.add_ip_address(ns_fdnd, ns_addr, 31)
-        ns_node.connector("devs").connect(ns_fdnd.connector("node"))
-        ns_tc = ns.create("ns3::Nepi::TunChannel")
-        ns_tc.connector("fd->").connect(ns_fdnd.connector("->fd"))
-        pl_tap.connector("tcp").connect(ns_tc.connector("tcp"))
-
-    def make_netns_node(self, netns):
-        node = netns.create("Node")
-        node.set_attribute_value("forward_X11", True)
-        command = "xterm" 
-        app = netns.create("Application")
-        app.set_attribute_value("command", command)
-        app.set_attribute_value("user", self.user)
-        app.connector("node").connect(node.connector("apps"))
-        return node
-
-    def make_pl_netns_connection(self, pl_desc, pl_node, netns,
-            netns_node, netns_iface_label):
-        base=struct.unpack('!L',socket.inet_aton(self.vnet))[0]
-        netns_addr = socket.inet_ntoa(struct.pack('!L',(base | 1)))
-        pl_addr = socket.inet_ntoa(struct.pack('!L',(base | 2)))
-        pl_tap = pl_desc.create("TunInterface")
-        pl_tap.set_attribute_value("multicast", True) 
-        #pl_tap.set_attribute_value("tun_cipher", "PLAIN") 
-        #pl_tap.enable_trace("pcap")
-        #pl_tap.enable_trace("packets")
-        self.add_ip_address(pl_tap, pl_addr, 31)
-        pl_node.connector("devs").connect(pl_tap.connector("node"))
-        
-        netns_tap = netns.create("TunNodeInterface")
-        netns_tap.set_attribute_value("label", netns_iface_label)
-        netns_tap.set_attribute_value("up", True)
-        netns_tap.set_attribute_value("mtu", 1448)
-        self.add_ip_address(netns_tap, netns_addr, 31)
-        self.add_route(netns_node, self.vnet, 24, pl_addr)
-        netns_node.connector("devs").connect(netns_tap.connector("node"))
-
-        netns_tunchannel = netns.create("TunChannel")
-        #netns_tunchannel.set_attribute_value("tun_cipher", "PLAIN") 
-        netns_tunchannel.connector("->fd").connect(netns_tap.connector("fd->"))
-        pl_tap.connector("tcp").connect(netns_tunchannel.connector("tcp"))
-
-    def add_ns_fdnd(self, ns, node):
-        fdnd = ns.create("ns3::FdNetDevice")
-        node.connector("devs").connect(fdnd.connector("node"))
-        #fdnd.enable_trace("FdPcapTrace")
-        return fdnd
-
-    def add_ns_node(self, ns):
-        node = ns.create("ns3::Node")
-        ipv4 = ns.create("ns3::Ipv4L3Protocol")
-        arp  = ns.create("ns3::ArpL3Protocol")
-        icmp = ns.create("ns3::Icmpv4L4Protocol")
-        udp = ns.create("ns3::UdpL4Protocol")
-        node.connector("protos").connect(ipv4.connector("node"))
-        node.connector("protos").connect(arp.connector("node"))
-        node.connector("protos").connect(icmp.connector("node"))
-        node.connector("protos").connect(udp.connector("node"))
-        return node
-
-    def add_ns_wifi_dev(self, ns, node, access_point = False):
-        wifi = ns.create("ns3::WifiNetDevice")
-        node.connector("devs").connect(wifi.connector("node"))
-
-        phy = ns.create("ns3::YansWifiPhy")
-        error = ns.create("ns3::NistErrorRateModel")
-        manager = ns.create("ns3::ArfWifiManager")
-        if access_point:
-            mac = ns.create("ns3::ApWifiMac")
-        else:
-            mac = ns.create("ns3::StaWifiMac")
-
-        phy.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        mac.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        phy.connector("err").connect(error.connector("phy"))
-        wifi.connector("phy").connect(phy.connector("dev"))
-        wifi.connector("mac").connect(mac.connector("dev"))
-        wifi.connector("manager").connect(manager.connector("dev"))
-
-        #phy.enable_trace("YansWifiPhyPcapTrace")
-        return wifi, phy
-
-    def add_ns_constant_mobility(self, ns, node, x, y, z):
-        mobility = ns.create("ns3::ConstantPositionMobilityModel") 
-        position = "%d:%d:%d" % (x, y, z)
-        mobility.set_attribute_value("Position", position)
-        node.connector("mobility").connect(mobility.connector("node"))
-        return mobility
-
-    def add_ns_wifi_channel(self, ns):
-        channel = ns.create("ns3::YansWifiChannel")
-        delay = ns.create("ns3::ConstantSpeedPropagationDelayModel")
-        loss  = ns.create("ns3::LogDistancePropagationLossModel")
-        channel.connector("delay").connect(delay.connector("chan"))
-        channel.connector("loss").connect(loss.connector("prev"))
-        return channel
-
-    def make_ns_wifi(self, ns, pl, pl_ns_root, inet, numwifinodes, nextip): 
-        base=struct.unpack('!L',socket.inet_aton(self.vnet))[0]
-        error = False
-        for i in xrange(2, 6):
-            nr = int(math.pow(2, i))
-            if nr <= (numwifinodes + 2):
-                break
-        else:
-            error = True
-        
-        # how many IPs will we need?
-        # 1 for the AP, 2 for each station and one for each extra PL node
-        # BUT we need to also reserve IPs to sum up to a posible subnetwork
-        # number of nodes: 2, 4, 8, 16, etc ...
-        # And finally, we need 2 extra IPs for the PL-AP iface
-       
-        nrips = (1 + 2*numwifinodes + nr + 2)
-        if nrips + nextip[0] > 255:
-            error = True
-        if error:
-            raise RuntimeError("There are not enough IP addresses for the wireless network", )
-        
-        netprefix = 32 - i
-        _nextwifiip = [254]
-        def nextwifiip():
-            ip = socket.inet_ntoa(struct.pack('!L',(base | _nextwifiip[0])))
-            _nextwifiip[0] -= 1
-            return ip
-
-        _nextnstapip = [(254 - nr -1)]
-        def nextnstapip():
-            ip = socket.inet_ntoa(struct.pack('!L',(base | _nextnstapip[0])))
-            _nextnstapip[0] -= 1
-            return ip
-
-        _nexttapip = [(254 - nr - 1 - numwifinodes)]
-        def nexttapip():
-            ip = socket.inet_ntoa(struct.pack('!L',(base | _nexttapip[0])))
-            _nexttapip[0] -= 1
-            return ip
-
-        # WIFI network
-        wifi_chan = self.add_ns_wifi_channel(ns)
-        
-        # AP node
-        ap_node = self.add_ns_node(ns)
-        self.add_ns_constant_mobility(ns, ap_node, 0, 0, 0)
-        ap_wifi, ap_phy = self.add_ns_wifi_dev(ns, ap_node, access_point = True)
-        ap_phy.connector("chan").connect(wifi_chan.connector("phys"))
-
-        # connect AP to PL
-        _nextplip = (254 - nrips)
-        pl_ip = socket.inet_ntoa(struct.pack('!L',(base | _nextplip)))
-        print "PL IP %s" % pl_ip
-        _nextplip -= 1
-        ns_ip = socket.inet_ntoa(struct.pack('!L',(base | _nextplip)))
-        print "NS IP %s" % ns_ip
-        self.add_pl_ns_connection(pl, pl_ns_root, pl_ip, ns, ap_node, ns_ip)
-
-        # routes in and out ns
-        self.add_route(ap_node, self.vnet, 24, pl_ip)
-        net = 256 - nr
-        ip = socket.inet_ntoa(struct.pack('!L',(base | net)))
-        self.add_route(pl_ns_root, ip, netprefix, ns_ip)
-        
-        ap_ip = nextwifiip()
-        print "AP IP %s" % ap_ip
-        self.add_ip_address(ap_wifi, ap_ip, netprefix)
-        
-        r = 50
-        # STA nodes
-        for i in xrange(0, numwifinodes):
-            stai = self.add_ns_node(ns)
-            angi = (360/numwifinodes)*i
-            xi = r*math.cos(angi)
-            yi = r*math.sin(angi)
-            self.add_ns_constant_mobility(ns, stai, xi, yi, 0)
-            wifi, phy = self.add_ns_wifi_dev(ns, stai, access_point = False)
-            phy.connector("chan").connect(wifi_chan.connector("phys"))
-            
-            wifi_ip = nextwifiip()
-            print "WIFI IP %s" % wifi_ip
-            self.add_ip_address(wifi, wifi_ip, netprefix)
-            self.add_route(stai, self.vnet, 24, ap_ip)
-            
-            """
-            pl_nodei, pl_ifacei = self.add_pl_ns_node(pl, inet, 
-                    "node2%d_pl"%i)
-           
-            pl_addr = (self.base_addr%(net+1))
-            ns3_addr = (self.base_addr%(net+2))
-            self.add_pl_ns_tunchan_connection(pl_desc, pl_nodei, pl_addr,
-                ns, stai, ns3_addr)
-            self.add_route(pl_nodei, (self.base_addr%32), 27, ns3_addr)
-            self.add_route(pl_nodei, (self.base_addr%0), 30, ns3_addr)
-            self.add_route(pl_nodei, (self.base_addr%4), 30, ns3_addr)
-
-            network = (self.base_addr%net)
-            self.add_route(netns_node, network, 30, (self.base_addr%2))
-            self.add_route(pl_node1, network, 30, (self.base_addr%6))
-            self.add_route(ap_node, network, 30, wifi_addr)
-            """
-
-    def make_pl_overlay(self, numnodes, numwifinodes):
-        print "make_pl_overlay ..."
-        ns3_testbed_id = "ns3"
-        
-        pl, netns, exp = self.make_experiment_desc()
-        # We'll make a distribution spanning tree using prefix matching as a distance
-        api = plutil.getAPI(self.pluser, self.plpass)
-        nodes = plutil.getNodes(api, numnodes, operatingSystem = 'f12')
-        root = min(nodes, key=operator.attrgetter('hostname'))
-        links = list(plutil.getSpanningTree(nodes, root=root))
-      
-        for node in nodes:
-            node.vif_ips = set()
-            node.children = []
-            node.childips = set()
-        
-        # Build an explicit tree
-        for slave, master in links:
-            master.children.append(slave)
-        
-        # We have to assign IPs and routes.
-        # The IP will be assigned sequentially, depth-first.
-        # This will result in rather compact routing rules
-        nextip = [128-numnodes]
-        def traverse(traverse, node, parent=None, base=struct.unpack('!L',socket.inet_aton(self.vnet))[0]):
-            if nextip[0] >= 254:
-                raise RuntimeError, "Too many IPs to assign!"
-            
-            node.vif_addr = base | (nextip[0])
-            nips = 1+len(node.children) # one vif per child, plus one for the parent
-            nextip[0] += nips
-            
-            for i in xrange(nips):
-                node.vif_ips.add(node.vif_addr+i)
-
-            if parent:
-                parent.childips.update(node.vif_ips)
-
-            for i,child in enumerate(node.children):
-                traverse(traverse, child, node, base)
-                
-            if parent:
-                parent.childips.update(node.childips)
-                
-        print "traverse..."
-        traverse(traverse, root)
-        
-        def printtree(printtree, node, indent=''):
-            print indent, '-', socket.inet_ntoa(struct.pack('!L',node.vif_addr)), node.country, node.city, node.site
-            for child in node.children:
-                childips = map(ipaddr.IPAddress, child.childips)
-                childnets = ipaddr.collapse_address_list(childips)
-                cip = ipaddr.IPAddress(child.vif_addr)
-                for cnet in childnets:
-                    print indent, '|- R', cnet, '->', cip
-                printtree(printtree, child, indent+' | ')
-        printtree(printtree, root)
-        
-        inet = pl.create("Internet")
-       
-        ns_chosen = []
-
-        def maketree(maketree, node, parent=None, parentIp=None):
-            routes = []
-            ctaps = []
-            for i,child in enumerate(node.children):
-                childips = map(ipaddr.IPAddress, child.childips)
-                childnets = ipaddr.collapse_address_list(childips)
-                cip = ipaddr.IPAddress(child.vif_addr)
-                pip = ipaddr.IPAddress(node.vif_addr+1+i)
-                for cnet in childnets:
-                    routes.append((cnet.ip.exploded, cnet.prefixlen, cip.exploded))
-                ctaps.append( maketree(maketree, child, node, pip) )
-
-            if parentIp:
-                routes.append((self.vnet,24,parentIp))
-            
-            if not parent:
-                label = "root"
-            else:
-                label = None
-                if not ns_chosen and node.children:
-                    ns_chosen.append(True)
-                    label = "ns_root"
-            ips = [ ipaddr.IPAddress(node.vif_addr+i) for i in xrange(1+len(node.children)) ]
-            node1, iface1, tap1, tap1ip, _ = self.make_pl_tapnode(pl, ips, inet, 
-                hostname = node.hostname,
-                routes = routes,
-                mcastrouter = bool(node.children),
-                mcast = True,
-                label = label )
-            
-            for tap, ctap in zip(tap1[1:], ctaps):
-                tap.connector("udp").connect(ctap.connector("udp"))
-
-            self.add_net_monitor(pl, node1)
-            self.add_vlc_restreamer(pl, node1)
-            if random.random() < 0.1 and parent:
-                self.add_vlc_dumper(pl, node1)
-            
-            return tap1[0]
-        
-        print "maketree..."
-        maketree(maketree, root)
-
-        # create a netns node and connect it to the root pl node
-        pl_root = exp.get_element_by_label("root")
-        netns_source = self.make_netns_node(netns)
-        iflabel = "source-iface"
-        self.make_pl_netns_connection(pl, pl_root, netns, 
-                netns_source, iflabel)
-        self.add_vlc_source(netns, netns_source, iflabel)
-        # add ns wireless network 
-        pl_ns_root = exp.get_element_by_label("ns_root")
-        pl_ns_root_iface = exp.get_element_by_label("ns_rootiface")
-        ns = self.make_ns_in_pl(pl, exp, pl_ns_root, pl_ns_root_iface, "ns3")
-        self.make_ns_wifi(ns, pl, pl_ns_root, inet, numwifinodes, nextip)
-
-        xml = exp.to_xml()
-        test_dir = "./results"
-
-        try:
-            controller = ExperimentController(xml, self.root_dir)
-            controller.start()
-            
-            print >>sys.stderr, "Press CTRL-C to shut down"
-            try:
-                while True:
-                    time.sleep(10)
-            except KeyboardInterrupt:
-                pass
-            
-            # download results
-            for testbed_guid, guids in controller.traces_info().iteritems():
-                for guid, traces in guids.iteritems():
-                    for name, data in traces.iteritems():
-                        path = data["filepath"]
-                        
-                        if not path:
-                            continue
-                        
-                        print >>sys.stderr, "Downloading trace", path
-                        
-                        filepath = os.path.join(test_dir, path)
-                        
-                        try:
-                            trace = controller.trace(guid, name)
-                        except:
-                            traceback.print_exc(file=sys.stderr)
-                            continue
-                        try:
-                            if not os.path.exists(os.path.dirname(filepath)):
-                                os.makedirs(os.path.dirname(filepath))
-                        except:
-                            traceback.print_exc(file=sys.stderr)
-                        
-                        try:
-                            if len(trace) >= 2**20:
-                                # Bigger than 1M, compress
-                                tracefile = gzip.GzipFile(filepath+".gz", "wb")
-                            else:
-                                tracefile = open(filepath,"wb")
-                            try:
-                                tracefile.write(trace)
-                            finally:
-                                tracefile.close()
-                        except:
-                            traceback.print_exc(file=sys.stderr)
-        finally:
-            try:
-                controller.stop()
-            except:
-                import traceback
-                traceback.print_exc()
-            try:
-                controller.shutdown()
-            except:
-                import traceback
-                traceback.print_exc()
-
-
-if __name__ == '__main__':
-    usage = "usage: %prog -n number_sta -m movie -u user"
-    parser = OptionParser(usage=usage)
-    parser.add_option("-u", "--user", dest="user", help="Valid linux system user (not root).", type="str", default=os.getlogin())
-    parser.add_option("-m", "--movie", dest="movie", help="Path to movie file to play", type="str")
-    parser.add_option("-n", "--nsta", dest="nsta", help="Number of wifi stations", type="int")
-    parser.add_option("-N", "--nodes", dest="nsta", help="Number of overlay nodes", type="int")
-    parser.add_option("-a", "--base_addr", dest="base_addr", help="Base address segment for the experiment", type="str")
-    parser.add_option("-s", "--slicename", dest="slicename", help="PlanetLab slice", type="str")
-    (options, args) = parser.parse_args()
-    if not options.movie:
-        parser.error("Missing 'movie' option.")
-    if options.user == 'root':
-        parser.error("Missing or invalid 'user' option.")
-    if options.nsta and options.nsta > 8:
-        parser.error("Try a number of stations under 9.")
-
-    exp = PlanetLabMulticastOverlay()
-    exp.movie_source = options.movie
-    exp.user = options.user
-    try:
-        exp.setUp()
-        exp.make_pl_overlay(5, 2)
-    finally:
-        exp.tearDown()
-
diff --git a/examples/netns_routing_experiment.py b/examples/netns_routing_experiment.py
new file mode 100644 (file)
index 0000000..f9f15ff
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#
+# Experiment Topology:
+#
+#  n1 --- n2 --- n3
+# 0.1  0.2  1.1  1.2
+#    
+
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+import getpass
+import tempfile
+import time
+
+user = getpass.getuser()
+root_dir = tempfile.mkdtemp()
+
+exp_desc = ExperimentDescription()
+
+testbed_id = "netns"
+netns_provider = FactoriesProvider(testbed_id)
+netns_desc = exp_desc.add_testbed_description(netns_provider)
+netns_desc.set_attribute_value("homeDirectory", root_dir)
+#netns_desc.set_attribute_value("enableDebug", True)
+
+node1 = netns_desc.create("Node")
+node2 = netns_desc.create("Node")
+node3 = netns_desc.create("Node")
+
+iface12 = netns_desc.create("P2PNodeInterface")
+iface12.set_attribute_value("up", True)
+node1.connector("devs").connect(iface12.connector("node"))
+
+iface21 = netns_desc.create("P2PNodeInterface")
+iface21.set_attribute_value("up", True)
+node2.connector("devs").connect(iface21.connector("node"))
+
+iface23 = netns_desc.create("P2PNodeInterface")
+iface23.set_attribute_value("up", True)
+node2.connector("devs").connect(iface23.connector("node"))
+
+iface32 = netns_desc.create("P2PNodeInterface")
+iface32.set_attribute_value("up", True)
+node3.connector("devs").connect(iface32.connector("node"))
+
+iface12.connector("p2p").connect(iface21.connector("p2p"))
+iface23.connector("p2p").connect(iface32.connector("p2p"))
+
+ip12 = iface12.add_address()
+ip12.set_attribute_value("Address", "192.168.0.1")
+ip12.set_attribute_value("NetPrefix", 30)
+
+ip21 = iface21.add_address()
+ip21.set_attribute_value("Address", "192.168.0.2")
+ip21.set_attribute_value("NetPrefix", 30)
+
+ip23 = iface23.add_address()
+ip23.set_attribute_value("Address", "192.168.1.1")
+ip23.set_attribute_value("NetPrefix", 30)
+
+ip32 = iface32.add_address()
+ip32.set_attribute_value("Address", "192.168.1.2")
+ip32.set_attribute_value("NetPrefix", 30)
+
+route1 = node1.add_route()
+route1.set_attribute_value("Destination", "192.168.1.0")
+route1.set_attribute_value("NetPrefix", 30)
+route1.set_attribute_value("NextHop", "192.168.0.2")
+
+route2 = node3.add_route()
+route2.set_attribute_value("Destination", "192.168.0.0")
+route2.set_attribute_value("NetPrefix", 30)
+route2.set_attribute_value("NextHop", "192.168.1.1")
+
+app1 = netns_desc.create("Application")
+app1.set_attribute_value("command", "ping -qc 3 192.168.1.2")
+app1.set_attribute_value("user", user)
+app1.connector("node").connect(node1.connector("apps"))
+
+app1.enable_trace("stdout")
+
+app2 = netns_desc.create("Application")
+app2.set_attribute_value("command", "ping -qc 3 192.168.0.1")
+app2.set_attribute_value("user", user)
+app2.connector("node").connect(node3.connector("apps"))
+
+app2.enable_trace("stdout")
+
+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)
+
+result1 = controller.trace(app1.guid, "stdout")
+result2 = controller.trace(app2.guid, "stdout")
+
+controller.stop()
+controller.shutdown()
+
+print result1
+print result2
diff --git a/examples/netns_xterm_experiment.py b/examples/netns_xterm_experiment.py
new file mode 100644 (file)
index 0000000..b6f2bad
--- /dev/null
@@ -0,0 +1,70 @@
+#!/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
+
+user = getpass.getuser()
+root_dir = tempfile.mkdtemp()
+
+exp_desc = ExperimentDescription()
+
+testbed_id = "netns"
+netns_provider = FactoriesProvider(testbed_id)
+netns_desc = exp_desc.add_testbed_description(netns_provider)
+netns_desc.set_attribute_value("homeDirectory", root_dir)
+#netns_desc.set_attribute_value("enableDebug", True)
+
+node1 = netns_desc.create("Node")
+node1.set_attribute_value("forward_X11", True)
+node2 = netns_desc.create("Node")
+node2.set_attribute_value("forward_X11", True)
+
+iface12 = netns_desc.create("P2PNodeInterface")
+iface12.set_attribute_value("up", True)
+node1.connector("devs").connect(iface12.connector("node"))
+
+iface21 = netns_desc.create("P2PNodeInterface")
+iface21.set_attribute_value("up", True)
+node2.connector("devs").connect(iface21.connector("node"))
+
+iface12.connector("p2p").connect(iface21.connector("p2p"))
+
+ip12 = iface12.add_address()
+ip12.set_attribute_value("Address", "192.168.0.1")
+ip12.set_attribute_value("NetPrefix", 30)
+
+ip21 = iface21.add_address()
+ip21.set_attribute_value("Address", "192.168.0.2")
+ip21.set_attribute_value("NetPrefix", 30)
+
+app1 = netns_desc.create("Application")
+app1.set_attribute_value("command", "xterm")
+app1.set_attribute_value("user", user)
+app1.connector("node").connect(node1.connector("apps"))
+
+app2 = netns_desc.create("Application")
+app2.set_attribute_value("command", "xterm")
+app2.set_attribute_value("user", user)
+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)
+
+controller.stop()
+controller.shutdown()
diff --git a/examples/ns3_runtime_attribute_change.py b/examples/ns3_runtime_attribute_change.py
new file mode 100644 (file)
index 0000000..7481888
--- /dev/null
@@ -0,0 +1,87 @@
+#!/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 tempfile
+import time
+
+root_dir = tempfile.mkdtemp()
+
+exp_desc = ExperimentDescription()
+
+testbed_id = "ns3"
+ns3_provider = FactoriesProvider(testbed_id)
+ns3_desc = exp_desc.add_testbed_description(ns3_provider)
+ns3_desc.set_attribute_value("homeDirectory", root_dir)
+ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
+ns3_desc.set_attribute_value("ChecksumEnabled", True)
+
+node1 = ns3_desc.create("ns3::Node")
+ipv41 = ns3_desc.create("ns3::Ipv4L3Protocol")
+arp1  = ns3_desc.create("ns3::ArpL3Protocol")
+icmp1 = ns3_desc.create("ns3::Icmpv4L4Protocol")
+node1.connector("protos").connect(ipv41.connector("node"))
+node1.connector("protos").connect(arp1.connector("node"))
+node1.connector("protos").connect(icmp1.connector("node"))
+iface1 = ns3_desc.create("ns3::PointToPointNetDevice")
+queue1 = ns3_desc.create("ns3::DropTailQueue")
+node1.connector("devs").connect(iface1.connector("node"))
+iface1.connector("queue").connect(queue1.connector("dev"))
+trace1 = iface1.enable_trace("P2PAsciiTrace")
+ip1 = iface1.add_address()
+ip1.set_attribute_value("Address", "10.0.0.1")
+
+node2 = ns3_desc.create("ns3::Node")
+ipv42 = ns3_desc.create("ns3::Ipv4L3Protocol")
+arp2  = ns3_desc.create("ns3::ArpL3Protocol")
+icmp2 = ns3_desc.create("ns3::Icmpv4L4Protocol")
+node2.connector("protos").connect(ipv42.connector("node"))
+node2.connector("protos").connect(arp2.connector("node"))
+node2.connector("protos").connect(icmp2.connector("node"))
+iface2 = ns3_desc.create("ns3::PointToPointNetDevice")
+queue2 = ns3_desc.create("ns3::DropTailQueue")
+node2.connector("devs").connect(iface2.connector("node"))
+iface2.connector("queue").connect(queue2.connector("dev"))
+trace2 = iface2.enable_trace("P2PAsciiTrace")
+ip2 = iface2.add_address()
+ip2.set_attribute_value("Address", "10.0.0.2")
+
+chan = ns3_desc.create("ns3::PointToPointChannel")
+chan.set_attribute_value("Delay", "0ns")
+iface1.connector("chan").connect(chan.connector("dev2"))
+iface2.connector("chan").connect(chan.connector("dev2"))
+
+app = ns3_desc.create("ns3::V4Ping")
+app.set_attribute_value("Remote", "10.0.0.2")
+app.set_attribute_value("Verbose", True)
+app.set_attribute_value("StartTime", "0s")
+app.set_attribute_value("StopTime", "20s")
+
+app.connector("node").connect(node1.connector("apps"))
+
+xml = exp_desc.to_xml()
+
+controller = ExperimentController(xml, root_dir)
+controller.start()
+
+time.sleep(5)
+
+controller.set(chan.guid, "Delay", "10s")
+
+time.sleep(5)
+
+controller.set(chan.guid, "Delay", "0s")
+
+while not controller.is_finished(app.guid):
+    time.sleep(0.5)
+
+controller.stop()
+controller.shutdown()
diff --git a/examples/planetlab_simple_experiment.py b/examples/planetlab_simple_experiment.py
new file mode 100644 (file)
index 0000000..a1be197
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import getpass
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+from nepi.util import proxy
+from nepi.util.constants import DeploymentConfiguration as DC
+import os
+import shutil
+import tempfile
+import time
+
+root_dir = tempfile.mkdtemp()
+user = getpass.getuser()
+slicename = os.environ["PL_SLICE"]
+plchost = "www.planet-lab.eu"
+port_base = 2000 + (os.getpid() % 1000) * 13
+pl_ssh_key = os.environ.get(
+    "PL_SSH_KEY",
+    "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
+pl_user = os.environ.get('PL_USER')
+pl_pwd = os.environ.get('PL_PASS')
+
+exp_desc = ExperimentDescription()
+
+pl_provider = FactoriesProvider("planetlab")
+pl_desc = exp_desc.add_testbed_description(pl_provider)
+pl_desc.set_attribute_value("homeDirectory", root_dir)
+pl_desc.set_attribute_value("slice", slicename)
+pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
+pl_desc.set_attribute_value("authUser", pl_user)
+pl_desc.set_attribute_value("authPass", pl_pwd)
+pl_desc.set_attribute_value("plcHost", plchost)
+pl_desc.set_attribute_value("tapPortBase", port_base)
+pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
+pl_desc.set_attribute_value("cleanProc", True)
+pl_desc.set_attribute_value("plLogLevel", "DEBUG")
+       
+pl_inet = pl_desc.create("Internet")
+
+pl_node1 = pl_desc.create("Node")
+pl_iface1 = pl_desc.create("NodeInterface")
+pl_iface1.set_attribute_value("label", "iface1")
+pl_iface1.connector("inet").connect(pl_inet.connector("devs"))
+pl_node1.connector("devs").connect(pl_iface1.connector("node"))
+
+pl_node2 = pl_desc.create("Node")
+pl_iface2 = pl_desc.create("NodeInterface")
+pl_iface2.set_attribute_value("label", "iface2")
+pl_iface2.connector("inet").connect(pl_inet.connector("devs"))
+pl_node2.connector("devs").connect(pl_iface2.connector("node"))
+
+pl_app1 = pl_desc.create("Application")
+pl_app1.set_attribute_value("command", "ping -qc3 {#[iface2].addr[0].[Address]#}")
+pl_app1.enable_trace("stdout")
+pl_app1.connector("node").connect(pl_node1.connector("apps"))
+
+pl_app2 = pl_desc.create("Application")
+pl_app2.set_attribute_value("command", "ping -qc3 {#[iface1].addr[0].[Address]#}")
+pl_app2.enable_trace("stdout")
+pl_app2.connector("node").connect(pl_node2.connector("apps"))
+
+xml = exp_desc.to_xml()
+
+controller = ExperimentController(xml, root_dir)
+controller.start()
+while (not controller.is_finished(pl_app1.guid) or not controller.is_finished(pl_app1.guid)):
+    time.sleep(0.5)
+
+ping_result1 = controller.trace(pl_app1.guid, "stdout")
+print ping_result1
+ping_result2 = controller.trace(pl_app2.guid, "stdout")
+print ping_result2
+
+controller.stop()
+controller.shutdown()
+
diff --git a/examples/roads09.py b/examples/roads09.py
deleted file mode 100644 (file)
index 47b42b2..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from nepi.core.design import ExperimentDescription, FactoriesProvider
-from nepi.core.execute import ExperimentController
-from optparse import OptionParser, SUPPRESS_HELP
-from nepi.util import proxy
-from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
-import os
-import shutil
-import tempfile
-import time
-import sys
-import random
-
-def pl_auth():
-    user = os.environ.get('PL_USER')
-    pwd = os.environ.get('PL_PASS')
-     
-    if user and pwd:
-        return (user,pwd)
-    else:
-        return None
-
-class Roads09Ns3PLExample(object):
-    testbed_id = "planetlab"
-    slicename = "inria_nepi"
-    plchost = "nepiplc.pl.sophia.inria.fr"
-    
-    host1 = "nepi1.pl.sophia.inria.fr"
-    host2 = "nepi2.pl.sophia.inria.fr"
-    host3 = "nepi3.pl.sophia.inria.fr"
-    host4 = "nepi5.pl.sophia.inria.fr"
-    
-    def __init__(self):
-        #usage = "usage: %prog -m movie -u user"
-        #parser = OptionParser(usage=usage)
-        #parser.add_option("-u", "--user", dest="user", help="Valid linux system user (not root).", type="str")
-        #parser.add_option("-m", "--movie", dest="movie", help="Path to movie file to play", type="str")
-        #(options, args) = parser.parse_args()
-        #if not options.movie:
-        #    parser.error("Missing 'movie' option.")
-        #if options.user == 'root':
-        #    parser.error("Missing or invalid 'user' option.")
-
-        #self.user = options.user if options.user else os.getlogin()
-        #self.movie =  options.movie
-        
-        if not pl_auth():
-            print "Example requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
-            sys.exit(1)
-        
-        self.root_dir = tempfile.mkdtemp()
-
-
-    def make_experiment_desc(self):
-        testbed_id = self.testbed_id
-        slicename = self.slicename
-        plchost = self.plchost
-        pl_ssh_key = os.environ.get(
-            "PL_SSH_KEY",
-            "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
-        pl_user, pl_pwd = pl_auth()
-
-        exp_desc = ExperimentDescription()
-        pl_provider = FactoriesProvider(testbed_id)
-        pl_desc = exp_desc.add_testbed_description(pl_provider)
-        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
-        pl_desc.set_attribute_value("slice", slicename)
-        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
-        pl_desc.set_attribute_value("authUser", pl_user)
-        pl_desc.set_attribute_value("authPass", pl_pwd)
-        pl_desc.set_attribute_value("plcHost", plchost)
-        
-        return pl_desc, exp_desc
-
-    def make_ns_in_pl(self, pl, exp, node1, iface1, root):
-        ns3_testbed_id = "ns3"
-        
-        # Add NS3 support in node1
-        plnepi = pl.create("NepiDependency")
-        plns3 = pl.create("NS3Dependency")
-        plnepi.connector("node").connect(node1.connector("deps"))
-        plns3.connector("node").connect(node1.connector("deps"))
-
-        # Create NS3 testbed running in node1
-        ns3_provider = FactoriesProvider(ns3_testbed_id)
-        ns3_desc = exp.add_testbed_description(ns3_provider)
-        ns3_desc.set_attribute_value("rootDirectory", root)
-        ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
-        ns3_desc.set_attribute_value("ChecksumEnabled", True)
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_HOST, "{#[%s].addr[0].[Address]#}" % (
-            iface1.get_attribute_value("label"),))
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_USER, 
-            pl.get_attribute_value("slice"))
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_KEY, 
-            pl.get_attribute_value("sliceSSHKey"))
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP,
-            "{#[%s].[%s]#}" % (
-                node1.get_attribute_value("label"),
-                ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP,))
-        ns3_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        
-        return ns3_desc
-    
-    
-
-    def add_ns3_fdnd(self, node, ns3_desc):
-        fdnd = ns3_desc.create("ns3::FdNetDevice")
-        node.connector("devs").connect(fdnd.connector("node"))
-        fdnd.enable_trace("FdPcapTrace")
-        return fdnd
-
-    def add_ns3_node(self, ns3_desc):
-        node = ns3_desc.create("ns3::Node")
-        ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
-        arp  = ns3_desc.create("ns3::ArpL3Protocol")
-        icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
-        udp = ns3_desc.create("ns3::UdpL4Protocol")
-        node.connector("protos").connect(ipv4.connector("node"))
-        node.connector("protos").connect(arp.connector("node"))
-        node.connector("protos").connect(icmp.connector("node"))
-        node.connector("protos").connect(udp.connector("node"))
-        return node
-
-    def add_ns3_wifi(self, node, ns3_desc, access_point = False, ip = None, prefix = 24):
-        wifi = ns3_desc.create("ns3::WifiNetDevice")
-        node.connector("devs").connect(wifi.connector("node"))
-
-        phy = ns3_desc.create("ns3::YansWifiPhy")
-        error = ns3_desc.create("ns3::NistErrorRateModel")
-        manager = ns3_desc.create("ns3::ArfWifiManager")
-        if access_point:
-            mac = ns3_desc.create("ns3::QapWifiMac")
-        else:
-            mac = ns3_desc.create("ns3::QstaWifiMac")
-
-        phy.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        mac.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        phy.connector("err").connect(error.connector("phy"))
-        wifi.connector("phy").connect(phy.connector("dev"))
-        wifi.connector("mac").connect(mac.connector("dev"))
-        wifi.connector("manager").connect(manager.connector("dev"))
-        
-        if ip:
-            self.add_ip_address(wifi, ip, prefix)
-
-        phy.enable_trace("YansWifiPhyPcapTrace")
-        return wifi, phy
-
-    def add_ns3_random_mobility(self, node, ns3_desc, x, y, z, speed, 
-            bounds_width, bounds_height):
-        position = "%f:%f:%f" % (x, y, z)
-        bounds = "0|%f|0|%f" % (bounds_width, bounds_height) 
-        speed = "Constant:%f" % speed
-        mobility = ns3_desc.create("ns3::RandomDirection2dMobilityModel")
-        mobility.set_attribute_value("Position", position)
-        mobility.set_attribute_value("Bounds", bounds)
-        mobility.set_attribute_value("Speed", speed)
-        mobility.set_attribute_value("Pause",  "Constant:1")
-        node.connector("mobility").connect(mobility.connector("node"))
-        return mobility
-
-    def add_ns3_constant_mobility(self, node, ns3_desc, x, y, z):
-        mobility = ns3_desc.create("ns3::ConstantPositionMobilityModel") 
-        position = "%f:%f:%f" % (x, y, z)
-        mobility.set_attribute_value("Position", position)
-        node.connector("mobility").connect(mobility.connector("node"))
-        return mobility
-
-    def add_ns3_wifi_channel(self, ns3_desc):
-        channel = ns3_desc.create("ns3::YansWifiChannel")
-        delay = ns3_desc.create("ns3::ConstantSpeedPropagationDelayModel")
-        loss  = ns3_desc.create("ns3::LogDistancePropagationLossModel")
-        channel.connector("delay").connect(delay.connector("chan"))
-        channel.connector("loss").connect(loss.connector("prev"))
-        return channel
-
-    def add_ip_address(self, iface, address, prefix = 24):
-        ip = iface.add_address()
-        ip.set_attribute_value("Address", address)
-        ip.set_attribute_value("Broadcast", True)
-        ip.set_attribute_value("NetPrefix", prefix)
-        return ip
-
-    def add_route(self, nodes, destination, netprefix, nexthop):
-        for node in nodes:
-            route = node.add_route()
-            route.set_attribute_value("Destination", destination)
-            route.set_attribute_value("NetPrefix", netprefix)
-            route.set_attribute_value("NextHop", nexthop)
-
-    def make_pl_router(self, pl, hostname, label, ip, inet = None):
-        pl1 = pl.create("Node")
-        pl1.set_attribute_value("hostname", hostname)
-        pl1.set_attribute_value("label", label)
-        pl1.set_attribute_value("emulation", True)
-        pl1if = pl.create("NodeInterface")
-        pl1if.set_attribute_value("label", label+"if")
-        pl1tap = pl.create("TapInterface")
-        pl1tap.enable_trace("packets") # for error output
-        pl1tap.set_attribute_value("label", label+"tap")
-        pl1tap.set_attribute_value("snat", False)
-        inet = inet or pl.create("Internet")
-        pl1.connector("devs").connect(pl1if.connector("node"))
-        pl1.connector("devs").connect(pl1tap.connector("node"))
-        pl1if.connector("inet").connect(inet.connector("devs"))
-        
-        pl1tapip = pl1tap.add_address()
-        pl1tapip.set_attribute_value("Address", ip)
-        pl1tapip.set_attribute_value("NetPrefix", 24)
-        pl1tapip.set_attribute_value("Broadcast", False)
-        
-        return pl1, pl1if, pl1tap, pl1tapip, inet
-    
-    def make_mesh(self, pl, exp, inet):
-        scale = 1.0
-        walkdistance = 1.0
-        walkspeed = 0.1
-    
-        # Router 1 & NS3 host in PL
-        pl1, pl1if, pl1tap, pl1tapip, inet = self.make_pl_router(pl, 
-            self.host1, "mesh_pl1", "192.168.2.2", inet)
-
-        # Add NS3 support in pl1
-        ns3 = self.make_ns_in_pl(pl, exp, pl1, pl1if, "tb-ns3-roads09-1")
-        
-        # Add WiFi channel
-        chan = self.add_ns3_wifi_channel(ns3)
-        
-        # Add APs
-        ap1 = self.add_ns3_node(ns3)
-        ap2 = self.add_ns3_node(ns3)
-        ap3 = self.add_ns3_node(ns3)
-        ap4 = self.add_ns3_node(ns3)
-        ap1wifi, ap1phy = self.add_ns3_wifi(ap1, ns3, False, "192.168.2.3", 26)
-        ap2wifi, ap2phy = self.add_ns3_wifi(ap2, ns3, True, "192.168.2.4", 26)
-        ap3wifi, ap3phy = self.add_ns3_wifi(ap3, ns3, False, "192.168.2.5", 26)
-        ap4wifi, ap4phy = self.add_ns3_wifi(ap4, ns3, False, "192.168.2.6", 26)
-        self.add_ns3_constant_mobility(ap1, ns3, -scale, -scale, 0.0)
-        self.add_ns3_constant_mobility(ap2, ns3, +scale, -scale, 0.0)
-        self.add_ns3_constant_mobility(ap3, ns3, -scale, +scale, 0.0)
-        self.add_ns3_constant_mobility(ap4, ns3, +scale, +scale, 0.0)
-        
-        # Add WiFi nodes
-        wnode1 = self.add_ns3_node(ns3)        
-        wnode2 = self.add_ns3_node(ns3)        
-        wnode3 = self.add_ns3_node(ns3)        
-        wnode4 = self.add_ns3_node(ns3)        
-        wnode5 = self.add_ns3_node(ns3)        
-        wnode1wifi, wnode1phy = self.add_ns3_wifi(wnode1, ns3, False, "192.168.2.7", 26)
-        wnode2wifi, wnode2phy = self.add_ns3_wifi(wnode2, ns3, False, "192.168.2.8", 26)
-        wnode3wifi, wnode3phy = self.add_ns3_wifi(wnode3, ns3, False, "192.168.2.9", 26)
-        wnode4wifi, wnode4phy = self.add_ns3_wifi(wnode4, ns3, False, "192.168.2.10", 26)
-        wnode5wifi, wnode5phy = self.add_ns3_wifi(wnode5, ns3, False, "192.168.2.11", 26)
-        self.add_ns3_random_mobility(wnode1, ns3, -2*scale, -2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode2, ns3, -2*scale, +scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode3, ns3, -scale, +2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode4, ns3, +scale, +2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode5, ns3, +2*scale, +2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        
-        # Connect all WiFi phys to the channel
-        ap1phy.connector("chan").connect(chan.connector("phys"))
-        ap2phy.connector("chan").connect(chan.connector("phys"))
-        ap3phy.connector("chan").connect(chan.connector("phys"))
-        ap4phy.connector("chan").connect(chan.connector("phys"))
-        wnode1phy.connector("chan").connect(chan.connector("phys"))
-        wnode2phy.connector("chan").connect(chan.connector("phys"))
-        wnode3phy.connector("chan").connect(chan.connector("phys"))
-        wnode4phy.connector("chan").connect(chan.connector("phys"))
-        wnode5phy.connector("chan").connect(chan.connector("phys"))
-        
-        # Add inet connection to AP
-        ap2fdnd = self.add_ns3_fdnd(ap2, ns3)
-        ap2fdndip = self.add_ip_address(ap2fdnd, "192.168.2.20")
-        ap2fdndip.set_attribute_value("NetPrefix", 32) # p2p
-        pl1tap.connector("fd->").connect(ap2fdnd.connector("->fd"))
-        pl1tap.set_attribute_value("pointopoint", "192.168.2.20")
-        r = ap2.add_route()
-        r.set_attribute_value("Destination", "192.168.2.2")
-        r.set_attribute_value("NetPrefix", 32)
-        r.set_attribute_value("NextHop", "192.168.2.20")
-        
-        # return mesh router
-        return (
-            pl1, pl1if, pl1tap, pl1tapip, 
-            (wnode1, wnode2, wnode3, wnode4, wnode5),
-            (wnode1wifi, wnode2wifi, wnode3wifi, wnode4wifi, wnode5wifi),
-            (ap1, ap2, ap3, ap4),
-            (ap1wifi, ap2wifi, ap3wifi, ap4wifi),
-            ns3,
-            inet,
-        )
-    
-    def make_wifi_hotspot(self, pl, exp, inet):
-        scale = 1.0
-        walkdistance = 1.0
-        walkspeed = 0.1
-    
-        # Router 1 & NS3 host in PL
-        pl1, pl1if, pl1tap, pl1tapip, inet = self.make_pl_router(pl, 
-            self.host2, "hs_pl1", "192.168.2.65", inet)
-
-        # Add NS3 support in pl1
-        ns3 = self.make_ns_in_pl(pl, exp, pl1, pl1if, "tb-ns3-roads09-2")
-        
-        # Add WiFi channel
-        chan = self.add_ns3_wifi_channel(ns3)
-        
-        # Add APs
-        ap1 = self.add_ns3_node(ns3)
-        ap1wifi, ap1phy = self.add_ns3_wifi(ap1, ns3, True, "192.168.2.66", 26)
-        self.add_ns3_constant_mobility(ap1, ns3, 0.0, 0.0, 0.0)
-        
-        # Add WiFi nodes
-        wnode1 = self.add_ns3_node(ns3)
-        wnode2 = self.add_ns3_node(ns3)
-        wnode3 = self.add_ns3_node(ns3)
-        wnode4 = self.add_ns3_node(ns3)
-        wnode1wifi, wnode1phy = self.add_ns3_wifi(wnode1, ns3, False, "192.168.2.67", 26)
-        wnode2wifi, wnode2phy = self.add_ns3_wifi(wnode2, ns3, False, "192.168.2.68", 26)
-        wnode3wifi, wnode3phy = self.add_ns3_wifi(wnode3, ns3, False, "192.168.2.69", 26)
-        wnode4wifi, wnode4phy = self.add_ns3_wifi(wnode4, ns3, False, "192.168.2.70", 26)
-        self.add_ns3_random_mobility(wnode1, ns3, +scale, -2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode2, ns3, -scale, -2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode3, ns3, -2*scale, +scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        self.add_ns3_random_mobility(wnode4, ns3, -2*scale, +2*scale, 0.0, 
-            walkspeed, walkdistance, walkdistance)
-        
-        # Connect all WiFi phys to the channel
-        ap1phy.connector("chan").connect(chan.connector("phys"))
-        wnode1phy.connector("chan").connect(chan.connector("phys"))
-        wnode2phy.connector("chan").connect(chan.connector("phys"))
-        wnode3phy.connector("chan").connect(chan.connector("phys"))
-        wnode4phy.connector("chan").connect(chan.connector("phys"))
-        
-        # Add inet connection to AP2
-        ap1fdnd = self.add_ns3_fdnd(ap1, ns3)
-        ap1fdndip = self.add_ip_address(ap1fdnd, "192.168.2.80")
-        ap1fdndip.set_attribute_value("NetPrefix", 32) # p2p
-        pl1tap.connector("fd->").connect(ap1fdnd.connector("->fd"))
-        pl1tap.set_attribute_value("pointopoint", "192.168.2.80")
-        r = ap1.add_route()
-        r.set_attribute_value("Destination", "192.168.2.65")
-        r.set_attribute_value("NetPrefix", 32)
-        r.set_attribute_value("NextHop", "192.168.2.80")
-        
-        # return mesh router
-        return (
-            pl1, pl1if, pl1tap, pl1tapip,
-            (wnode1, wnode2, wnode3, wnode4),
-            (wnode1wifi, wnode2wifi, wnode3wifi, wnode4wifi),
-            ap1, ap1wifi,
-            ns3,
-            inet,
-        )
-    
-    def run(self):
-        pl, exp = self.make_experiment_desc()
-    
-        pl1, pl1if, pl1tap, pl1tapip, \
-            mesh_nodes, mesh_node_ifs, \
-            mesh_aps, mesh_ap_ifs, \
-            mesh_ns, \
-            inet = self.make_mesh(pl, exp, None)
-        pl2, pl2if, pl2tap, pl2tapip, \
-            hs_nodes, hs_node_ifs, \
-            hs_ap, hs_apif, \
-            hs_ns, \
-            inet = self.make_wifi_hotspot(pl, exp, inet)
-        
-        # Connect the routers
-        pl1etap = pl.create("TapInterface")
-        pl1etap.enable_trace("packets") # for error output
-        pl1etap.set_attribute_value("label", "pl1etap")
-        pl1etapip = pl1etap.add_address()
-        pl1etapip.set_attribute_value("Address", "192.168.2.1")
-        pl1etapip.set_attribute_value("NetPrefix", 24)
-        pl1etapip.set_attribute_value("Broadcast", False)
-
-        pl2etap = pl.create("TapInterface")
-        pl2etap.enable_trace("packets") # for error output
-        pl2etap.set_attribute_value("label", "pl2etap")
-        pl2etapip = pl2etap.add_address()
-        pl2etapip.set_attribute_value("Address", "192.168.2.81")
-        pl2etapip.set_attribute_value("NetPrefix", 24)
-        pl2etapip.set_attribute_value("Broadcast", False)
-        
-        pl1etap.connector("node").connect(pl1.connector("devs"))
-        pl2etap.connector("node").connect(pl2.connector("devs"))
-        pl1etap.connector("udp").connect(pl2etap.connector("udp"))
-        pl1etap.set_attribute_value("pointopoint", "192.168.2.81")
-        pl2etap.set_attribute_value("pointopoint", "192.168.2.1")
-        
-        # Connect the networks
-        
-        # apn -> ap2 (n != 2)
-        for ap in mesh_aps[:1] + mesh_aps[2:]:
-            r = ap.add_route()
-            r.set_attribute_value("Destination", "192.168.2.64")
-            r.set_attribute_value("NetPrefix", 26)
-            r.set_attribute_value("NextHop", 
-                mesh_ap_ifs[1].addresses[0].get_attribute_value("Address") )
-
-        for wn in mesh_nodes:
-            apif = mesh_ap_ifs[ random.randint(0,len(mesh_aps)-1) ]
-            r = wn.add_route()
-            r.set_attribute_value("Destination", "192.168.2.64")
-            r.set_attribute_value("NetPrefix", 26)
-            r.set_attribute_value("NextHop", 
-                apif.addresses[0].get_attribute_value("Address"))
-
-        r = mesh_aps[1].add_route()
-        r.set_attribute_value("Destination", "192.168.2.64")
-        r.set_attribute_value("NetPrefix", 26)
-        r.set_attribute_value("NextHop", "192.168.2.2")
-        
-        r = pl1.add_route()
-        r.set_attribute_value("Destination", "192.168.2.64")
-        r.set_attribute_value("NetPrefix", 26)
-        r.set_attribute_value("NextHop", "192.168.2.81")
-
-        r = pl2.add_route()
-        r.set_attribute_value("Destination", "192.168.2.64")
-        r.set_attribute_value("NetPrefix", 26)
-        r.set_attribute_value("NextHop", "192.168.2.80")
-
-        for wn in hs_nodes:
-            r = wn.add_route()
-            r.set_attribute_value("Destination", "192.168.2.0")
-            r.set_attribute_value("NetPrefix", 26)
-            r.set_attribute_value("NextHop", "192.168.2.66")
-
-        r = hs_ap.add_route()
-        r.set_attribute_value("Destination", "192.168.2.0")
-        r.set_attribute_value("NetPrefix", 26)
-        r.set_attribute_value("NextHop", "192.168.2.65")
-        
-        r = pl2.add_route()
-        r.set_attribute_value("Destination", "192.168.2.0")
-        r.set_attribute_value("NetPrefix", 26)
-        r.set_attribute_value("NextHop", "192.168.2.1")
-
-        r = pl1.add_route()
-        r.set_attribute_value("Destination", "192.168.2.0")
-        r.set_attribute_value("NetPrefix", 26)
-        r.set_attribute_value("NextHop", "192.168.2.20")
-
-        # Add pinger app inside the mesh
-        hs_node_ifs[0].set_attribute_value("label", "hotspot_node_1if")
-        mesh_node_ifs[0].set_attribute_value("label", "mesh_node_1if")
-        ping = mesh_ns.create("ns3::V4Ping")
-        ping.set_attribute_value("Remote", "192.168.2.67") #"{#[hotspot_node_1if].addr[0].[Address]#}")
-        ping.set_attribute_value("StartTime", "0s")
-        ping.set_attribute_value("StopTime", "10s")
-        ping.connector("node").connect(mesh_aps[0].connector("apps"))
-
-        xml = exp.to_xml()
-        
-        print xml
-
-        try:
-            controller = ExperimentController(xml, self.root_dir)
-            controller.start()
-            
-            while not controller.is_finished(ping.guid):
-                time.sleep(0.5)
-            
-            taptrace = controller.trace(pl.guid, pl1tap.guid, "packets")
-                
-        finally:
-            controller.stop()
-            controller.shutdown()
-        
-        print "Pakcets at router:"
-        print taptrace
-
-    def clean(self):
-        shutil.rmtree(self.root_dir)
-
-if __name__ == '__main__':
-    example = Roads09Ns3PLExample()
-    example.run()
-    example.clean()
-
diff --git a/examples/tunnel_cross_testbed_experiment.py b/examples/tunnel_cross_testbed_experiment.py
new file mode 100644 (file)
index 0000000..774bd12
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import getpass
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+from nepi.util import proxy
+from nepi.util.constants import DeploymentConfiguration as DC
+import os
+import shutil
+import tempfile
+import time
+
+root_dir = tempfile.mkdtemp()
+netns_root_dir = os.path.join(root_dir, "netns")
+os.makedirs(netns_root_dir)
+user = getpass.getuser()
+slicename = os.environ["PL_SLICE"]
+plchost = "www.planet-lab.eu"
+port_base = 2000 + (os.getpid() % 1000) * 13
+pl_ssh_key = os.environ.get(
+    "PL_SSH_KEY",
+    "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
+pl_user = os.environ.get('PL_USER')
+pl_pwd = os.environ.get('PL_PASS')
+
+exp_desc = ExperimentDescription()
+
+pl_provider = FactoriesProvider("planetlab")
+pl_desc = exp_desc.add_testbed_description(pl_provider)
+pl_desc.set_attribute_value("homeDirectory", root_dir)
+pl_desc.set_attribute_value("slice", slicename)
+pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
+pl_desc.set_attribute_value("authUser", pl_user)
+pl_desc.set_attribute_value("authPass", pl_pwd)
+pl_desc.set_attribute_value("plcHost", plchost)
+pl_desc.set_attribute_value("tapPortBase", port_base)
+pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
+pl_desc.set_attribute_value("cleanProc", True)
+pl_desc.set_attribute_value("plLogLevel", "DEBUG")
+       
+pl_inet = pl_desc.create("Internet")
+
+pl_node = pl_desc.create("Node")
+pl_iface = pl_desc.create("NodeInterface")
+pl_iface.connector("inet").connect(pl_inet.connector("devs"))
+pl_node.connector("devs").connect(pl_iface.connector("node"))
+
+pl_tap = pl_desc.create("TunInterface")
+pl_tap.enable_trace("pcap")
+pl_tap.enable_trace("packets")
+pl_node.connector("devs").connect(pl_tap.connector("node"))
+
+ip1 = pl_tap.add_address()
+ip1.set_attribute_value("Address", "192.168.3.1")
+ip1.set_attribute_value("NetPrefix", 24)
+
+netns_provider = FactoriesProvider("netns")
+netns_desc = exp_desc.add_testbed_description(netns_provider)
+netns_desc.set_attribute_value("homeDirectory", root_dir)
+netns_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
+netns_desc.set_attribute_value(DC.ROOT_DIRECTORY, netns_root_dir)
+netns_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
+netns_desc.set_attribute_value(DC.USE_SUDO, True)
+
+netns_node = netns_desc.create("Node")
+netns_node.set_attribute_value("forward_X11", True)
+
+netns_tap = netns_desc.create("TunNodeInterface")
+netns_tap.set_attribute_value("up", True)
+netns_tap.set_attribute_value("mtu", 1448)
+netns_node.connector("devs").connect(netns_tap.connector("node"))
+netns_tunchannel = netns_desc.create("TunChannel")
+netns_tunchannel.connector("->fd").connect(netns_tap.connector("fd->"))
+
+pl_tap.connector("tcp").connect(netns_tunchannel.connector("tcp"))
+
+ip2 = netns_tap.add_address()
+ip2.set_attribute_value("Address", "192.168.3.2")
+ip2.set_attribute_value("NetPrefix", 30)
+
+app = netns_desc.create("Application")
+app.set_attribute_value("command", "xterm")
+app.set_attribute_value("user", user)
+app.connector("node").connect(netns_node.connector("apps"))
+
+xml = exp_desc.to_xml()
+
+controller = ExperimentController(xml, root_dir)
+controller.start()
+while not controller.is_finished(app.guid):
+    time.sleep(0.5)
+
+controller.stop()
+controller.shutdown()
+
diff --git a/examples/vlc_wireless_netns_ns3.py b/examples/vlc_wireless_netns_ns3.py
deleted file mode 100644 (file)
index 469c837..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from nepi.core.design import ExperimentDescription, FactoriesProvider
-from nepi.core.execute import ExperimentController
-from optparse import OptionParser, SUPPRESS_HELP
-from nepi.util import proxy
-import os
-import shutil
-import tempfile
-import test_util
-import time
-
-class VlcWirelessNetnsNs3Example(object):
-    def __init__(self):
-        usage = "usage: %prog -m movie -u user"
-        parser = OptionParser(usage=usage)
-        parser.add_option("-u", "--user", dest="user", help="Valid linux system user (not root).", type="str")
-        parser.add_option("-m", "--movie", dest="movie", help="Path to movie file to play", type="str")
-        (options, args) = parser.parse_args()
-        if not options.movie:
-            parser.error("Missing 'movie' option.")
-        if options.user == 'root':
-            parser.error("Missing or invalid 'user' option.")
-
-        self.user = options.user if options.user else os.getlogin()
-        self.movie =  options.movie
-        self.root_dir = tempfile.mkdtemp()
-
-    def add_netns_tap(self, node, netns_desc):
-        tap = netns_desc.create("TapNodeInterface")
-        tap.set_attribute_value("up", True)
-        node.connector("devs").connect(tap.connector("node"))
-        return tap
-
-    def add_ns3_fdnd(self, node, ns3_desc):
-        fdnd = ns3_desc.create("ns3::FdNetDevice")
-        node.connector("devs").connect(fdnd.connector("node"))
-        fdnd.enable_trace("FdPcapTrace")
-        return fdnd
-
-    def add_ns3_node(self, ns3_desc):
-        node = ns3_desc.create("ns3::Node")
-        ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
-        arp  = ns3_desc.create("ns3::ArpL3Protocol")
-        icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
-        udp = ns3_desc.create("ns3::UdpL4Protocol")
-        node.connector("protos").connect(ipv4.connector("node"))
-        node.connector("protos").connect(arp.connector("node"))
-        node.connector("protos").connect(icmp.connector("node"))
-        node.connector("protos").connect(udp.connector("node"))
-        return node
-
-    def add_ns3_wifi(self, node, ns3_desc, access_point = False):
-        wifi = ns3_desc.create("ns3::WifiNetDevice")
-        node.connector("devs").connect(wifi.connector("node"))
-
-        phy = ns3_desc.create("ns3::YansWifiPhy")
-        error = ns3_desc.create("ns3::NistErrorRateModel")
-        manager = ns3_desc.create("ns3::ArfWifiManager")
-        if access_point:
-            mac = ns3_desc.create("ns3::ApWifiMac")
-        else:
-            mac = ns3_desc.create("ns3::StaWifiMac")
-
-        phy.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        mac.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        phy.connector("err").connect(error.connector("phy"))
-        wifi.connector("phy").connect(phy.connector("dev"))
-        wifi.connector("mac").connect(mac.connector("dev"))
-        wifi.connector("manager").connect(manager.connector("dev"))
-
-        phy.enable_trace("YansWifiPhyPcapTrace")
-        return wifi, phy
-
-    def add_ns3_random_mobility(self, node, ns3_desc, x, y, z, speed, 
-            bounds_width, bounds_height):
-        position = "%d:%d:%d" % (x, y, z)
-        bounds = "0|%d|0|%d" % (bounds_width, bounds_height) 
-        speed = "Constant:%d" % speed
-        mobility = ns3_desc.create("ns3::RandomDirection2dMobilityModel")
-        mobility.set_attribute_value("Position", position)
-        mobility.set_attribute_value("Bounds", bounds)
-        mobility.set_attribute_value("Speed", speed)
-        mobility.set_attribute_value("Pause",  "Constant:1")
-        node.connector("mobility").connect(mobility.connector("node"))
-        return mobility
-
-    def add_ns3_constant_mobility(self, node, ns3_desc, x, y, z):
-        mobility = ns3_desc.create("ns3::ConstantPositionMobilityModel") 
-        position = "%d:%d:%d" % (x, y, z)
-        mobility.set_attribute_value("Position", position)
-        node.connector("mobility").connect(mobility.connector("node"))
-        return mobility
-
-    def add_ns3_wifi_channel(self, ns3_desc):
-        channel = ns3_desc.create("ns3::YansWifiChannel")
-        delay = ns3_desc.create("ns3::ConstantSpeedPropagationDelayModel")
-        loss  = ns3_desc.create("ns3::LogDistancePropagationLossModel")
-        channel.connector("delay").connect(delay.connector("chan"))
-        channel.connector("loss").connect(loss.connector("prev"))
-        return channel
-
-    def add_ip_address(self, iface, address):
-        ip = iface.add_address()
-        ip.set_attribute_value("Address", address)
-
-    def add_route(self, node, destination, netprefix, nexthop):
-        route = node.add_route()
-        route.set_attribute_value("Destination", destination)
-        route.set_attribute_value("NetPrefix", netprefix)
-        route.set_attribute_value("NextHop", nexthop)
-
-    def run(self):
-        bounds_width = bounds_height = 200
-        x = y = 100
-        speed = 7
-
-        exp_desc = ExperimentDescription()
-
-        ## NS3 Testbed instance description ##
-        testbed_id = "ns3"
-        ns3_provider = FactoriesProvider(testbed_id)
-        ns3_desc = exp_desc.add_testbed_description(ns3_provider)
-        ns3_desc.set_attribute_value("homeDirectory", self.root_dir)
-        ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
-        ns3_desc.set_attribute_value("ChecksumEnabled", True)
-        # create node 1
-        node1 = self.add_ns3_node(ns3_desc)
-        mobility1 = self.add_ns3_constant_mobility(node1, ns3_desc, x, y, 0)
-        wifi1, phy1 = self.add_ns3_wifi(node1, ns3_desc, access_point = False)
-        self.add_ip_address(wifi1, "10.0.1.1")
-        fdnd1 = self.add_ns3_fdnd(node1, ns3_desc)
-        self.add_ip_address(fdnd1, "10.0.0.1")
-        # create node 2
-        node2 = self.add_ns3_node(ns3_desc)
-        mobility2 = self.add_ns3_random_mobility(node2, ns3_desc, x, y, 0, 
-                speed, bounds_width, bounds_height)
-        wifi2, phy2 = self.add_ns3_wifi(node2, ns3_desc, access_point = True)
-        self.add_ip_address(wifi2, "10.0.1.2")
-        fdnd2 = self.add_ns3_fdnd(node2, ns3_desc)
-        self.add_ip_address(fdnd2, "10.0.2.1")
-        # interconnect nodes with a wifi channel
-        wifichan = self.add_ns3_wifi_channel(ns3_desc)
-        phy1.connector("chan").connect(wifichan.connector("phys"))
-        phy2.connector("chan").connect(wifichan.connector("phys"))
-
-        ## NETNS testbed description 1 ##
-        testbed_id = "netns"
-        netns_provider = FactoriesProvider(testbed_id)
-        netns_desc1 = exp_desc.add_testbed_description(netns_provider)
-        netns_desc1.set_attribute_value("homeDirectory", self.root_dir)
-        #netns_desc1.set_attribute_value("enableDebug", True)
-        # create node 3
-        node3 = netns_desc1.create("Node")
-        node3.set_attribute_value("forward_X11", True)
-        tap1 = self.add_netns_tap(node3, netns_desc1)
-        self.add_ip_address(tap1, "10.0.0.2")
-        # create vlc server
-        # DEBUG!! target = "{#[vlc_client].addr[0].[Address]#}"
-        target = "10.0.2.2" 
-        command = "vlc -I dummy %s --sout '#rtp{dst=%s,port=5004,mux=ts}' vlc://quit" \
-                % (self.movie, target)
-        vlc_server = netns_desc1.create("Application")
-        vlc_server.set_attribute_value("command", command)
-        vlc_server.set_attribute_value("user", self.user)
-        vlc_server.connector("node").connect(node3.connector("apps"))
-
-        #command = "xterm"
-        #xterm1 = netns_desc1.create("Application")
-        #xterm1.set_attribute_value("command", command)
-        #xterm1.set_attribute_value("user", self.user)
-        #xterm1.connector("node").connect(node3.connector("apps"))
-
-        ## NETNS testbed description 2 ##
-        netns_desc2 = exp_desc.add_testbed_description(netns_provider)
-        netns_desc2.set_attribute_value("homeDirectory", self.root_dir)
-        #netns_desc2.set_attribute_value("enableDebug", True)
-        # create node 4
-        node4 = netns_desc2.create("Node")
-        node4.set_attribute_value("forward_X11", True)
-        node4.set_attribute_value("label", "vlc_client")
-        tap2 = self.add_netns_tap(node4, netns_desc2)
-        self.add_ip_address(tap2, "10.0.2.2")
-        # create vlc client
-        vlc_client = netns_desc2.create("Application")
-        command = "vlc rtp://%s:5004/test.ts" % target
-        vlc_client.set_attribute_value("command", command)
-        vlc_client.set_attribute_value("user", self.user)
-        vlc_client.connector("node").connect(node4.connector("apps"))
-
-        #command = "xterm"
-        #xterm2 = netns_desc2.create("Application")
-        #xterm2.set_attribute_value("command", command)
-        #xterm2.set_attribute_value("user", self.user)
-        #xterm2.connector("node").connect(node4.connector("apps"))
-
-        ## testbed_interconnection
-        fdnd1.connector("->fd").connect(tap1.connector("fd->"))
-        fdnd2.connector("->fd").connect(tap2.connector("fd->"))
-      
-        self.add_route(node4, "10.0.0.0", 24, "10.0.2.1")
-        self.add_route(node4, "10.0.1.0", 24, "10.0.2.1")
-        self.add_route(node3, "10.0.2.0", 24, "10.0.0.1")
-        self.add_route(node3, "10.0.1.0", 24, "10.0.0.1")
-
-        self.add_route(node2, "10.0.0.0", 24, "10.0.1.1")
-        self.add_route(node1, "10.0.2.0", 24, "10.0.1.2")
-
-        xml = exp_desc.to_xml()
-        controller = ExperimentController(xml, self.root_dir)
-        controller.start()
-        while not controller.is_finished(vlc_server.guid) and \
-                not controller.is_finished(vlc_client.guid):
-            time.sleep(0.5)
-        controller.stop()
-        controller.shutdown()
-
-    def clean(self):
-        shutil.rmtree(self.root_dir)
-
-if __name__ == '__main__':
-    example = VlcWirelessNetnsNs3Example()
-    example.run()
-    example.clean()
-
diff --git a/examples/wimax_ns3.py b/examples/wimax_ns3.py
deleted file mode 100644 (file)
index c6680cd..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from nepi.core.design import ExperimentDescription, FactoriesProvider
-from nepi.core.execute import ExperimentController
-from optparse import OptionParser, SUPPRESS_HELP
-from nepi.util import proxy
-import os
-import shutil
-import tempfile
-import test_util
-import time
-
-class Roads09Example(object):
-    def __init__(self):
-        self.root_dir = tempfile.mkdtemp()
-
-    def add_ns3_node(self, ns3_desc):
-        node = ns3_desc.create("ns3::Node")
-        ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
-        arp  = ns3_desc.create("ns3::ArpL3Protocol")
-        icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
-        udp = ns3_desc.create("ns3::UdpL4Protocol")
-        node.connector("protos").connect(ipv4.connector("node"))
-        node.connector("protos").connect(arp.connector("node"))
-        node.connector("protos").connect(icmp.connector("node"))
-        node.connector("protos").connect(udp.connector("node"))
-        return node
-
-    def add_ns3_wimax_bs(self, ns3_desc, node, channel):
-        bs = ns3_desc.create("ns3::BaseStationNetDevice")
-        node.connector("devs").connect(bs.connector("node"))
-        bs.connector("chan").connect(channel.connector("devs"))
-        phy = ns3_desc.create("ns3::SimpleOfdmWimaxPhy")
-        bs.connector("phy").connect(phy.connector("dev"))
-        uplink = ns3_desc.create("ns3::UplinkSchedulerSimple")
-        bs.connector("uplnk").connect(uplink.connector("dev"))
-        bssched = ns3_desc.create("ns3::BSSchedulerSimple")
-        bs.connector("dwnlnk").connect(bssched.connector("dev"))
-        bs.enable_trace("WimaxPcapTrace")
-        bs.enable_trace("WimaxAsciiTrace")
-        return bs
-
-    def add_ns3_wimax_ss(self, ns3_desc, node, channel):
-        ss = ns3_desc.create("ns3::SubscriberStationNetDevice")
-        node.connector("devs").connect(ss.connector("node"))
-        ss.connector("chan").connect(channel.connector("devs"))
-        phy = ns3_desc.create("ns3::SimpleOfdmWimaxPhy")
-        ss.connector("phy").connect(phy.connector("dev"))
-        ss.enable_trace("WimaxPcapTrace")
-        ss.enable_trace("WimaxAsciiTrace")
-        return ss
-
-    def add_ns3_service_flow(self, ns3_desc, ss, src_address, src_mask,
-            dst_address, dst_mask, src_portlow, src_porthigh, dst_portlow,
-            dst_porthigh, protocol, priority, direction, scheduling_type):
-        classifier = ns3_desc.create("ns3::IpcsClassifierRecord")
-        classifier.set_attribute_value("SrcAddress", src_address)
-        classifier.set_attribute_value("SrcMask", src_mask)
-        classifier.set_attribute_value("DstAddress", dst_address)
-        classifier.set_attribute_value("DstMask", dst_mask)
-        classifier.set_attribute_value("SrcPortLow", src_portlow)
-        classifier.set_attribute_value("SrcPortHigh",src_porthigh)
-        classifier.set_attribute_value("DstPortLow", dst_portlow)
-        classifier.set_attribute_value("DstPortHigh", dst_porthigh)
-        classifier.set_attribute_value("Protocol", protocol)
-        classifier.set_attribute_value("Priority", priority)
-        sflow = ns3_desc.create("ns3::ServiceFlow")
-        sflow.set_attribute_value("Direction", direction)
-        sflow.set_attribute_value("SchedulingType", scheduling_type)
-        sflow.connector("classif").connect(classifier.connector("sflow"))
-        ss.connector("sflows").connect(sflow.connector("dev"))
-
-    def add_ip_address(self, iface, address):
-        ip = iface.add_address()
-        ip.set_attribute_value("Address", address)
-
-    def run(self):
-        exp_desc = ExperimentDescription()
-
-        testbed_id = "ns3"
-        ns3_provider = FactoriesProvider(testbed_id)
-        ns3_desc = exp_desc.add_testbed_description(ns3_provider)
-        ns3_desc.set_attribute_value("homeDirectory", self.root_dir)
-        ns3_desc.set_attribute_value("StopTime", "7.1s")
-
-        node1 = self.add_ns3_node(ns3_desc)
-        node2 = self.add_ns3_node(ns3_desc)
-        node3 = self.add_ns3_node(ns3_desc)
-
-        channel = ns3_desc.create("ns3::SimpleOfdmWimaxChannel")
-
-        ss1 = self.add_ns3_wimax_ss(ns3_desc, node1, channel)
-        ss2 = self.add_ns3_wimax_ss(ns3_desc, node2, channel)
-        bs = self.add_ns3_wimax_bs(ns3_desc, node3, channel)
-
-        self.add_ns3_service_flow(ns3_desc, ss1, "0.0.0.0", "0.0.0.0",
-                "10.1.1.1", "255.255.255.255", 0, 65000, 100, 100, 
-                "UdpL4Protocol", 1, "SF_DIRECTION_DOWN", "SF_TYPE_RTPS")
-        self.add_ns3_service_flow(ns3_desc, ss2, "10.1.1.2", "255.255.255.255",
-                "0.0.0.0", "0.0.0.0", 0, 65000, 100, 100, "UdpL4Protocol",
-                1, "SF_DIRECTION_UP", "SF_TYPE_RTPS")
-
-        self.add_ip_address(ss1, "10.1.1.1")
-        self.add_ip_address(ss2, "10.1.1.2")
-        self.add_ip_address(bs, "10.1.1.3")
-
-        udp_server = ns3_desc.create("ns3::UdpServer")
-        udp_server.set_attribute_value("Port", 100)
-        udp_server.set_attribute_value("StartTime", "6s")
-        udp_server.set_attribute_value("StopTime", "7s")
-        udp_server.connector("node").connect(node1.connector("apps"))
-
-        udp_client = ns3_desc.create("ns3::UdpClient")
-        udp_client.set_attribute_value("RemotePort", 100)
-        udp_client.set_attribute_value("RemoteAddress", "10.1.1.1")
-        udp_client.set_attribute_value("MaxPackets", 1200)
-        udp_client.set_attribute_value("Interval", "0.5s")
-        udp_client.set_attribute_value("PacketSize", 1024)
-        udp_client.set_attribute_value("StartTime", "6s")
-        udp_client.set_attribute_value("StopTime", "7s")
-        udp_client.connector("node").connect(node2.connector("apps"))
-
-        xml = exp_desc.to_xml()
-        controller = ExperimentController(xml, self.root_dir)
-        controller.start()
-        while not (controller.is_finished(udp_server.guid) and controller.is_finished(udp_client.guid)):
-            time.sleep(0.5)
-        time.sleep(0.1)
-        controller.stop()
-        controller.shutdown()
-
-    def clean(self):
-        print self.root_dir
-        #shutil.rmtree(self.root_dir)
-        pass
-
-if __name__ == '__main__':
-    example = Roads09Example()
-    example.run()
-    example.clean()
-
diff --git a/examples/wimax_overlay.py b/examples/wimax_overlay.py
deleted file mode 100644 (file)
index 5b5e3c9..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from nepi.core.design import ExperimentDescription, FactoriesProvider
-from nepi.core.execute import ExperimentController
-from optparse import OptionParser, SUPPRESS_HELP
-from nepi.util.constants import DeploymentConfiguration as DC
-import os
-import shutil
-import tempfile
-import time
-
-class WimaxOverlayExample(object):
-    def __init__(self):
-        #usage = "usage: %prog -m movie -u user"
-        #parser = OptionParser(usage=usage)
-        #parser.add_option("-u", "--user", dest="user", help="Valid linux system user (not root).", type="str")
-        #parser.add_option("-m", "--movie", dest="movie", help="Path to movie file to play", type="str")
-        #(options, args) = parser.parse_args()
-        #if not options.movie:
-        #    parser.error("Missing 'movie' option.")
-        #if options.user == 'root':
-        #    parser.error("Missing or invalid 'user' option.")
-
-        #self.user = options.user if options.user else os.getlogin()
-        self.user = os.getlogin()
-        #self.movie =  options.movie
-        self.root_dir = tempfile.mkdtemp()
-
-    def add_ns3_node(self, ns3_desc):
-        node = ns3_desc.create("ns3::Node")
-        ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
-        arp  = ns3_desc.create("ns3::ArpL3Protocol")
-        icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
-        udp = ns3_desc.create("ns3::UdpL4Protocol")
-        tcp = ns3_desc.create("ns3::TcpL4Protocol")
-        node.connector("protos").connect(ipv4.connector("node"))
-        node.connector("protos").connect(arp.connector("node"))
-        node.connector("protos").connect(icmp.connector("node"))
-        node.connector("protos").connect(udp.connector("node"))
-        node.connector("protos").connect(tcp.connector("node"))
-        return node
-
-    def add_ns3_wimax_bs(self, ns3_desc, node, channel):
-        bs = ns3_desc.create("ns3::BaseStationNetDevice")
-        node.connector("devs").connect(bs.connector("node"))
-        bs.connector("chan").connect(channel.connector("devs"))
-        phy = ns3_desc.create("ns3::SimpleOfdmWimaxPhy")
-        bs.connector("phy").connect(phy.connector("dev"))
-        uplink = ns3_desc.create("ns3::UplinkSchedulerSimple")
-        bs.connector("uplnk").connect(uplink.connector("dev"))
-        bssched = ns3_desc.create("ns3::BSSchedulerSimple")
-        bs.connector("dwnlnk").connect(bssched.connector("dev"))
-        bs.enable_trace("WimaxPcapTrace")
-        bs.enable_trace("WimaxAsciiTrace")
-        return bs
-
-    def add_ns3_wimax_ss(self, ns3_desc, node, channel):
-        ss = ns3_desc.create("ns3::SubscriberStationNetDevice")
-        node.connector("devs").connect(ss.connector("node"))
-        ss.connector("chan").connect(channel.connector("devs"))
-        phy = ns3_desc.create("ns3::SimpleOfdmWimaxPhy")
-        ss.connector("phy").connect(phy.connector("dev"))
-        ss.enable_trace("WimaxPcapTrace")
-        ss.enable_trace("WimaxAsciiTrace")
-        return ss
-
-    def add_ns3_p2p(self, ns3_desc, node, channel):
-        iface = ns3_desc.create("ns3::PointToPointNetDevice")
-        queue = ns3_desc.create("ns3::DropTailQueue")
-        node.connector("devs").connect(iface.connector("node"))
-        iface.connector("queue").connect(queue.connector("dev"))
-        trace = iface.enable_trace("P2PAsciiTrace")
-        iface.connector("chan").connect(channel.connector("dev2"))
-        return iface
-
-    def add_ns3_service_flow(self, ns3_desc, ss, src_address, src_mask,
-            dst_address, dst_mask, src_portlow, src_porthigh, dst_portlow,
-            dst_porthigh, protocol, priority, direction, scheduling_type):
-        classifier = ns3_desc.create("ns3::IpcsClassifierRecord")
-        classifier.set_attribute_value("SrcAddress", src_address)
-        classifier.set_attribute_value("SrcMask", src_mask)
-        classifier.set_attribute_value("DstAddress", dst_address)
-        classifier.set_attribute_value("DstMask", dst_mask)
-        classifier.set_attribute_value("SrcPortLow", src_portlow)
-        classifier.set_attribute_value("SrcPortHigh",src_porthigh)
-        classifier.set_attribute_value("DstPortLow", dst_portlow)
-        classifier.set_attribute_value("DstPortHigh", dst_porthigh)
-        classifier.set_attribute_value("Protocol", protocol)
-        classifier.set_attribute_value("Priority", priority)
-        sflow = ns3_desc.create("ns3::ServiceFlow")
-        sflow.set_attribute_value("Direction", direction)
-        sflow.set_attribute_value("SchedulingType", scheduling_type)
-        sflow.connector("classif").connect(classifier.connector("sflow"))
-        ss.connector("sflows").connect(sflow.connector("dev"))
-
-    def add_netns_tap(self, netns_desc, node):
-        tap = netns_desc.create("TapNodeInterface")
-        tap.set_attribute_value("up", True)
-        node.connector("devs").connect(tap.connector("node"))
-        return tap
-
-    def add_ns3_fdnd(self, ns3_desc, node):
-        fdnd = ns3_desc.create("ns3::FdNetDevice")
-        node.connector("devs").connect(fdnd.connector("node"))
-        fdnd.enable_trace("FdPcapTrace")
-        return fdnd
-
-    def add_ip_address(self, iface, address, netprefix):
-        ip = iface.add_address()
-        ip.set_attribute_value("Address", address)
-        ip.set_attribute_value("NetPrefix", netprefix)
-
-    def add_route(self, node, destination, netprefix, nexthop):
-        route = node.add_route()
-        route.set_attribute_value("Destination", destination)
-        route.set_attribute_value("NetPrefix", netprefix)
-        route.set_attribute_value("NextHop", nexthop)
-
-    def run(self):
-        base_addr = "192.168.4.%d"
-        exp_desc = ExperimentDescription()
-
-        # NS3
-        ns3_provider = FactoriesProvider("ns3")
-        ns3_desc = exp_desc.add_testbed_description(ns3_provider)
-        ns3_desc.set_attribute_value("homeDirectory", self.root_dir)
-        ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
-        ns3_desc.set_attribute_value("ChecksumEnabled", True)
-
-        ## WIMAX network 32/27
-        node_bs = self.add_ns3_node(ns3_desc)
-        node_ss1 = self.add_ns3_node(ns3_desc)
-        node_ss2 = self.add_ns3_node(ns3_desc)
-        node_ss3 = self.add_ns3_node(ns3_desc)
-        node_ss4 = self.add_ns3_node(ns3_desc)
-        node_ss5 = self.add_ns3_node(ns3_desc)
-        node_ss6 = self.add_ns3_node(ns3_desc)
-
-        wimax_channel = ns3_desc.create("ns3::SimpleOfdmWimaxChannel")
-
-        bs = self.add_ns3_wimax_bs(ns3_desc, node_bs, wimax_channel)
-        ss1 = self.add_ns3_wimax_ss(ns3_desc, node_ss1, wimax_channel)
-        ss2 = self.add_ns3_wimax_ss(ns3_desc, node_ss2, wimax_channel)
-        ss3 = self.add_ns3_wimax_ss(ns3_desc, node_ss3, wimax_channel)
-        ss4 = self.add_ns3_wimax_ss(ns3_desc, node_ss4, wimax_channel)
-        ss5 = self.add_ns3_wimax_ss(ns3_desc, node_ss5, wimax_channel)
-        ss6 = self.add_ns3_wimax_ss(ns3_desc, node_ss6, wimax_channel)
-
-        self.add_ip_address(bs, (base_addr%33), 27)
-        self.add_ip_address(ss1, (base_addr%34), 27)
-        self.add_ip_address(ss2, (base_addr%35), 27)
-        self.add_ip_address(ss3, (base_addr%36), 27)
-        self.add_ip_address(ss4, (base_addr%37), 27)
-        self.add_ip_address(ss5, (base_addr%38), 27)
-        self.add_ip_address(ss6, (base_addr%39), 27)
-
-        #self.add_ns3_service_flow(ns3_desc, ss1, "0.0.0.0", "0.0.0.0",
-        #        "10.1.1.1", "255.255.255.255", 0, 65000, 100, 100, 
-        #       "UdpL4Protocol", 1, "SF_DIRECTION_DOWN", "SF_TYPE_RTPS")
-        #self.add_ns3_service_flow(ns3_desc, ss2, "10.1.1.2", "255.255.255.255",
-        #        "0.0.0.0", "0.0.0.0", 0, 65000, 100, 100, "UdpL4Protocol",
-        #        1, "SF_DIRECTION_UP", "SF_TYPE_RTPS")
-
-        self.add_ns3_service_flow(ns3_desc, ss1, "0.0.0.0", "0.0.0.0",
-                "192.168.4.35", "255.255.255.225", 0, 65000, 11, 11, "Icmpv4L4Protocol",
-                1, "SF_DIRECTION_DOWN", "SF_TYPE_RTPS")
-
-        self.add_ns3_service_flow(ns3_desc, ss2, "192.168.4.34", "255.255.255.255",
-                "0.0.0.0", "0.0.0.0", 0, 65000, 11, 11, "Icmpv4L4Protocol",
-                1, "SF_DIRECTION_UP", "SF_TYPE_RTPS")
-
-        ## Point-to-Point wimax/fdnd 224/30
-        node_fdnd = self.add_ns3_node(ns3_desc)
-        p2p_channel = ns3_desc.create("ns3::PointToPointChannel")
-        
-        p2p1 = self.add_ns3_p2p(ns3_desc, node_ss1, p2p_channel)
-        p2p2 = self.add_ns3_p2p(ns3_desc, node_fdnd, p2p_channel)
-
-        self.add_ip_address(p2p1, (base_addr%225), 30)
-        self.add_ip_address(p2p2, (base_addr%226), 30)
-
-        # NETNS
-        netns_provider = FactoriesProvider("netns")
-        netns_desc = exp_desc.add_testbed_description(netns_provider)
-        netns_desc.set_attribute_value("homeDirectory", self.root_dir)
-        netns_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
-        netns_root_dir = os.path.join(self.root_dir, "netns_instance")
-        os.mkdir(netns_root_dir)
-        netns_desc.set_attribute_value(DC.ROOT_DIRECTORY, netns_root_dir)
-        netns_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        netns_desc.set_attribute_value(DC.USE_SUDO, True)
-
-        node_netns = netns_desc.create("Node")
-        node_netns.set_attribute_value("forward_X11", True)
-        tap = self.add_netns_tap(netns_desc, node_netns)
-
-        command = "xterm" 
-        app = netns_desc.create("Application")
-        app.set_attribute_value("command", command)
-        app.set_attribute_value("user", self.user)
-        app.connector("node").connect(node_netns.connector("apps"))
-
-        ## Point-to-Point NS3::fdnd/NETNS::tap 228/30
-        fdnd = self.add_ns3_fdnd(ns3_desc, node_fdnd)
-
-        fdnd.connector("->fd").connect(tap.connector("fd->"))
-        self.add_ip_address(fdnd, (base_addr%229), 30)
-        self.add_ip_address(tap, (base_addr%230), 30)
-
-        # ROUTES
-        self.add_route(node_netns, (base_addr%32), 27, (base_addr%229))
-        self.add_route(node_netns, (base_addr%224), 30, (base_addr%229))
-        
-        self.add_route(node_fdnd, (base_addr%32), 27, (base_addr%225))
-        self.add_route(node_ss1, (base_addr%228), 30, (base_addr%226))
-
-        self.add_route(node_ss2, (base_addr%224), 30, (base_addr%34))
-        self.add_route(node_ss2, (base_addr%228), 30, (base_addr%34))
-        self.add_route(node_bs, (base_addr%224), 30, (base_addr%34))
-        self.add_route(node_bs, (base_addr%228), 30, (base_addr%34))
-
-
-        xml = exp_desc.to_xml()
-        controller = ExperimentController(xml, self.root_dir)
-        controller.start()
-        while not controller.is_finished(app.guid):
-            time.sleep(0.5)
-        time.sleep(0.1)
-        controller.stop()
-        controller.shutdown()
-
-    def clean(self):
-        #shutil.rmtree(self.root_dir)
-        print self.root_dir
-        pass
-
-if __name__ == '__main__':
-    example = WimaxOverlayExample()
-    example.run()
-    example.clean()
-
diff --git a/examples/wireless_overlay.py b/examples/wireless_overlay.py
deleted file mode 100644 (file)
index d735f56..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from nepi.core.design import ExperimentDescription, FactoriesProvider
-from nepi.core.execute import ExperimentController
-from optparse import OptionParser, SUPPRESS_HELP
-from nepi.util import proxy
-from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
-import test_util
-import os
-import shutil
-import tempfile
-import itertools
-import time
-import math
-
-"""
-
-   ___________________________________________________________
-  |   NETNS                                                   |
-  |                                                           |
-  |                    __________                             | 
-  |                   |netns_node|  VLC_SERVER                |
-  |                   |__________|                            |
-  |                                                           |
-  |                       1/30                                |
-  |                    -----------                            |
-  |_________________________|_________________________________|
-                            |  
-                            |  0/30
-   _________________________|_________________________________
-  |    PL1                  |                                 |  
-  |                   ------------                            |
-  |                       2/30                                |
-  |                                                           |
-  |                       5/30                                |
-  |                  -------------                            |
-  |_________________________|_________________________________|
-                            | 
-                            |   4/30
-   _________________________|_________________________________
-  |    NS-3                 |                                 |
-  |                     --------                              |  
-  |                       6/30                                |
-  |                      ______                               |
-  |                     |  AP  |                              |
-  |                     |______|                              |
-  |                       33/27                               |
-  |                     --------                              |
-  |                       ((*))                               |
-  |                                                           |
-  |                                                           |
-  |     ((*))       ((*))       ((*))     ((*))               |         
-  |    -------     --------    -------   -------              |          
-  |     34/27       35/27      36/27      37/27               |          
-  |    +-----+     +-----+    +-----+    +-----+              |
-  |    |sta0 |     |sta1 |    |sta2 |    |sta3 |              |
-  |    +-----+     +-----+    +-----+    +-----+              |
-  |     66/30       70/30      74/30      78/30               |
-  |    -------     -------    -------    -------              |
-  |_______|___________|__________|__________|_________________|
-          |           |          |          |
-    ______|____   ____|____   ___|____   ___|____
-   | PL2  |    | |PL3 |    | |PL4|    | |PL5|    | 
-   |      |    | |    |    | |   |    | |   |    |
-   | -------   | | ------- | | ------ | |------- |  
-   |  65/30    | |  69/30  | | 73/30  | | 77/30  |                                 
-   |___________| |_________| |________| |________|
-
-"""
-
-class WirelessOverlay(object):
-    def __init__(self):
-        usage = "usage: %prog -n number_sta -m movie -u user"
-        parser = OptionParser(usage=usage)
-        parser.add_option("-u", "--user", dest="user", help="Valid linux system user (not root).", type="str")
-        parser.add_option("-m", "--movie", dest="movie", help="Path to movie file to play", type="str")
-        parser.add_option("-n", "--nsta", dest="nsta", help="Number of wifi stations", type="int")
-        parser.add_option("-a", "--base_addr", dest="base_addr", help="Base address segment for the experiment", type="str")
-        parser.add_option("-s", "--slicename", dest="slicename", help="PlanetLab slice", type="str")
-        (options, args) = parser.parse_args()
-        if not options.movie:
-            parser.error("Missing 'movie' option.")
-        if options.user == 'root':
-            parser.error("Missing or invalid 'user' option.")
-        if options.user == 'root':
-            parser.error("Missing or invalid 'user' option.")
-        if options.nsta and options.nsta > 8:
-            parser.error("Try a number of stations under 9.")
-
-        self.user = options.user if options.user else os.getlogin()
-        self.movie = options.movie
-        self.nsta = options.nsta if options.nsta else 3
-        self.slicename = options.slicename if options.slicename else "inria_nepi3"
-        base = options.base_addr if options.base_addr else "192.168.4"
-        self.base_addr = base + ".%d"
-        self.root_dir = tempfile.mkdtemp()
-
-    def add_ip_address(self, iface, address, netprefix):
-        ip = iface.add_address()
-        ip.set_attribute_value("Address", address)
-        ip.set_attribute_value("NetPrefix", netprefix)
-
-    def add_route(self, node, destination, netprefix, nexthop):
-        route = node.add_route()
-        route.set_attribute_value("Destination", destination)
-        route.set_attribute_value("NetPrefix", netprefix)
-        route.set_attribute_value("NextHop", nexthop)
-
-    def add_ns3_fdnd(self, ns3_desc, node):
-        fdnd = ns3_desc.create("ns3::FdNetDevice")
-        node.connector("devs").connect(fdnd.connector("node"))
-        #fdnd.enable_trace("FdPcapTrace")
-        return fdnd
-
-    def add_ns3_node(self, ns3_desc):
-        node = ns3_desc.create("ns3::Node")
-        ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
-        arp  = ns3_desc.create("ns3::ArpL3Protocol")
-        icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
-        udp = ns3_desc.create("ns3::UdpL4Protocol")
-        node.connector("protos").connect(ipv4.connector("node"))
-        node.connector("protos").connect(arp.connector("node"))
-        node.connector("protos").connect(icmp.connector("node"))
-        node.connector("protos").connect(udp.connector("node"))
-        return node
-
-    def add_ns3_wifi(self, ns3_desc, node, access_point = False):
-        wifi = ns3_desc.create("ns3::WifiNetDevice")
-        node.connector("devs").connect(wifi.connector("node"))
-
-        phy = ns3_desc.create("ns3::YansWifiPhy")
-        error = ns3_desc.create("ns3::NistErrorRateModel")
-        manager = ns3_desc.create("ns3::ArfWifiManager")
-        if access_point:
-            mac = ns3_desc.create("ns3::ApWifiMac")
-        else:
-            mac = ns3_desc.create("ns3::StaWifiMac")
-
-        phy.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        mac.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
-        phy.connector("err").connect(error.connector("phy"))
-        wifi.connector("phy").connect(phy.connector("dev"))
-        wifi.connector("mac").connect(mac.connector("dev"))
-        wifi.connector("manager").connect(manager.connector("dev"))
-
-        #phy.enable_trace("YansWifiPhyPcapTrace")
-        return wifi, phy
-
-    def add_ns3_constant_mobility(self, ns3_desc, node, x, y, z):
-        mobility = ns3_desc.create("ns3::ConstantPositionMobilityModel") 
-        position = "%d:%d:%d" % (x, y, z)
-        mobility.set_attribute_value("Position", position)
-        node.connector("mobility").connect(mobility.connector("node"))
-        return mobility
-
-    def add_ns3_wifi_channel(self, ns3_desc):
-        channel = ns3_desc.create("ns3::YansWifiChannel")
-        delay = ns3_desc.create("ns3::ConstantSpeedPropagationDelayModel")
-        loss  = ns3_desc.create("ns3::LogDistancePropagationLossModel")
-        channel.connector("delay").connect(delay.connector("chan"))
-        channel.connector("loss").connect(loss.connector("prev"))
-        return channel
-
-    def add_pl_testbed(self, exp_desc):
-        plchost = "nepiplc.pl.sophia.inria.fr"
-        port_base = 2000 + (os.getpid() % 1000) * 13
-        pl_ssh_key = os.environ.get(
-            "PL_SSH_KEY",
-            "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
-        pl_user, pl_pwd = test_util.pl_auth()
-
-        pl_provider = FactoriesProvider("planetlab")
-        pl_desc = exp_desc.add_testbed_description(pl_provider)
-        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
-        pl_desc.set_attribute_value("slice", self.slicename)
-        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
-        pl_desc.set_attribute_value("authUser", pl_user)
-        pl_desc.set_attribute_value("authPass", pl_pwd)
-        pl_desc.set_attribute_value("plcHost", plchost)
-        pl_desc.set_attribute_value("tapPortBase", port_base)
-        pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc.set_attribute_value("dedicatedSlice", True)
-        pl_desc.set_attribute_value("plLogLevel", "DEBUG")
-        return pl_desc
-
-    def add_pl_node(self, pl_desc, inet, label_prefix):
-        node = pl_desc.create("Node")
-        node.set_attribute_value("label", label_prefix)
-        iface = pl_desc.create("NodeInterface")
-        iface.set_attribute_value("label", label_prefix+"iface")
-        iface.connector("inet").connect(inet.connector("devs"))
-        node.connector("devs").connect(iface.connector("node"))
-        forwarder = pl_desc.create("MulticastForwarder")
-        forwarder.enable_trace("stderr")
-        node.connector("apps").connect(forwarder.connector("node"))
-        return node, iface
-
-    def add_ns3_in_pl(self, exp_desc, pl_desc, pl_node, pl_iface, root):
-        # Add NS3 support in node
-        plnepi = pl_desc.create("NepiDependency")
-        plns3 = pl_desc.create("NS3Dependency")
-        plnepi.connector("node").connect(pl_node.connector("deps"))
-        plns3.connector("node").connect(pl_node.connector("deps"))
-
-        # Create NS3 testbed running in pl_node
-        ns3_provider = FactoriesProvider("ns3")
-        ns3_desc = exp_desc.add_testbed_description(ns3_provider)
-        ns3_desc.set_attribute_value("rootDirectory", root)
-        ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
-        ns3_desc.set_attribute_value("ChecksumEnabled", True)
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_HOST, "{#[%s].addr[0].[Address]#}" % (
-            pl_iface.get_attribute_value("label"),))
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_USER, 
-            pl_desc.get_attribute_value("slice"))
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_KEY, 
-            pl_desc.get_attribute_value("sliceSSHKey"))
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
-        ns3_desc.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP,
-            "{#[%s].[%s]#}" % (
-                pl_node.get_attribute_value("label"),
-                ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP,))
-        ns3_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        return ns3_desc
-
-    def add_netns_testbed(self, exp_desc):
-        netns_provider = FactoriesProvider("netns")
-        netns_desc = exp_desc.add_testbed_description(netns_provider)
-        netns_desc.set_attribute_value("homeDirectory", self.root_dir)
-        netns_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
-        netns_root_dir = os.path.join(self.root_dir, "netns")
-        os.mkdir(netns_root_dir)
-        netns_desc.set_attribute_value(DC.ROOT_DIRECTORY, netns_root_dir)
-        netns_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        netns_desc.set_attribute_value(DC.USE_SUDO, True)
-        return netns_desc
-
-    def add_netns_node(self, netns_desc):
-        node = netns_desc.create("Node")
-        node.set_attribute_value("forward_X11", True)
-        return node
-
-    def add_pl_ns3_connection(self, pl_desc, pl_node, pl_addr,
-            ns3_desc, ns3_node, ns3_addr):
-        pl_tap = pl_desc.create("TapInterface")
-        pl_tap.set_attribute_value("tun_cipher", "PLAIN") 
-        self.add_ip_address(pl_tap, pl_addr, 30)
-        pl_node.connector("devs").connect(pl_tap.connector("node"))
-        ns3_fdnd = ns3_desc.create("ns3::FdNetDevice")
-        ns3_node.connector("devs").connect(ns3_fdnd.connector("node"))
-        self.add_ip_address(ns3_fdnd, ns3_addr, 30)
-        pl_tap.connector("fd->").connect(ns3_fdnd.connector("->fd"))
-
-    def add_pl_ns3_tunchan_connection(self, pl_desc, pl_node, pl_addr,
-            ns3_desc, ns3_node, ns3_addr):
-        pl_tap = pl_desc.create("TunInterface")
-        self.add_ip_address(pl_tap, pl_addr, 30)
-        pl_node.connector("devs").connect(pl_tap.connector("node"))
-        ns3_fdnd = ns3_desc.create("ns3::FdNetDevice")
-        ns3_fdnd.enable_trace("FdPcapTrace")
-        self.add_ip_address(ns3_fdnd, ns3_addr, 30)
-        ns3_node.connector("devs").connect(ns3_fdnd.connector("node"))
-        ns3_tc = ns3_desc.create("ns3::Nepi::TunChannel")
-        ns3_tc.connector("fd->").connect(ns3_fdnd.connector("->fd"))
-        pl_tap.connector("tcp").connect(ns3_tc.connector("tcp"))
-
-    def add_pl_netns_connection(self, pl_desc, pl_node, pl_addr,
-            netns_desc, netns_node, netns_addr):
-        pl_tap = pl_desc.create("TunInterface")
-        #pl_tap.set_attribute_value("tun_cipher", "PLAIN") 
-        pl_tap.set_attribute_value("multicast", True) 
-        #pl_tap.enable_trace("pcap")
-        #pl_tap.enable_trace("packets")
-        self.add_ip_address(pl_tap, pl_addr, 30)
-        pl_node.connector("devs").connect(pl_tap.connector("node"))
-        netns_tap = netns_desc.create("TunNodeInterface")
-        netns_tap.set_attribute_value("up", True)
-        netns_tap.set_attribute_value("mtu", 1448)
-        self.add_ip_address(netns_tap, netns_addr, 30)
-        netns_node.connector("devs").connect(netns_tap.connector("node"))
-        netns_tunchannel = netns_desc.create("TunChannel")
-        #netns_tunchannel.set_attribute_value("tun_cipher", "PLAIN") 
-        netns_tunchannel.connector("->fd").connect(netns_tap.connector("fd->"))
-        pl_tap.connector("tcp").connect(netns_tunchannel.connector("tcp"))
-
-    def run(self):
-        exp_desc = ExperimentDescription()
-
-        ## PL ##
-        pl_desc = self.add_pl_testbed(exp_desc)
-        pl_inet = pl_desc.create("Internet")
-        pl_node1, pl_iface1 = self.add_pl_node(pl_desc, pl_inet, 
-                "node1_pl")
-
-        ## NETNS ##
-        netns_desc = self.add_netns_testbed(exp_desc)
-        netns_node = self.add_netns_node(netns_desc)
-
-        ## NS3 ##
-        ns3_desc = self.add_ns3_in_pl(exp_desc, pl_desc, pl_node1, pl_iface1, "ns3")
-        wifi_chan = self.add_ns3_wifi_channel(ns3_desc)
-        
-        # AP node
-        ap_node = self.add_ns3_node(ns3_desc)
-        self.add_ns3_constant_mobility(ns3_desc, ap_node, 0, 0, 0)
-        ap_wifi, ap_phy = self.add_ns3_wifi(ns3_desc, ap_node, access_point = True)
-        self.add_ip_address(ap_wifi, (self.base_addr%33), 27)
-        ap_phy.connector("chan").connect(wifi_chan.connector("phys"))
-
-        # wifi network 32/27
-        r = 50
-        # STA nodes
-        for i in xrange(0, self.nsta):
-            stai = self.add_ns3_node(ns3_desc)
-            angi = (360/self.nsta)*i
-            xi = r*math.cos(angi)
-            yi = r*math.sin(angi)
-            self.add_ns3_constant_mobility(ns3_desc, stai, xi, yi, 0)
-            wifi, phy= self.add_ns3_wifi(ns3_desc, stai, access_point = False)
-            wifi_addr = self.base_addr%(34 + i)
-            self.add_ip_address(wifi, wifi_addr, 27)
-            phy.connector("chan").connect(wifi_chan.connector("phys"))
-
-            self.add_route(stai, (self.base_addr%0), 30, (self.base_addr%33))
-            self.add_route(stai, (self.base_addr%4), 30, (self.base_addr%33))
-
-            net = 64 + i*4
-            pl_nodei, pl_ifacei = self.add_pl_node(pl_desc, pl_inet, 
-                    "node2%d_pl"%i)
-
-            pl_addr = (self.base_addr%(net+1))
-            ns3_addr = (self.base_addr%(net+2))
-            self.add_pl_ns3_tunchan_connection(pl_desc, pl_nodei, pl_addr,
-                ns3_desc, stai, ns3_addr)
-            self.add_route(pl_nodei, (self.base_addr%32), 27, ns3_addr)
-            self.add_route(pl_nodei, (self.base_addr%0), 30, ns3_addr)
-            self.add_route(pl_nodei, (self.base_addr%4), 30, ns3_addr)
-
-            network = (self.base_addr%net)
-            self.add_route(netns_node, network, 30, (self.base_addr%2))
-            self.add_route(pl_node1, network, 30, (self.base_addr%6))
-            self.add_route(ap_node, network, 30, wifi_addr)
-        
-        # connection PL1/NETNS
-        pl_addr = (self.base_addr%2)
-        netns_addr = (self.base_addr%1)
-        self.add_pl_netns_connection(pl_desc, pl_node1, pl_addr,
-            netns_desc, netns_node, netns_addr)
-        
-        # connection PL1/NS3
-        pl_addr = (self.base_addr%5)
-        ns3_addr = (self.base_addr%6)
-        self.add_pl_ns3_connection(pl_desc, pl_node1, pl_addr,
-            ns3_desc, ap_node, ns3_addr)
-        
-        # APPLICATIONS
-        command = "xterm" 
-        app = netns_desc.create("Application")
-        app.set_attribute_value("command", command)
-        app.set_attribute_value("user", self.user)
-        app.connector("node").connect(netns_node.connector("apps"))
-
-        # applications
-        #target = "{#[%s].addr[0].[Address]#}" % label
-        servers = []
-        clients = []
-        net = 0
-        target = self.base_addr%2
-        local = self.base_addr%1
-        port = 5065
-        command = "sleep 2; vlc -I dummy %s --miface-addr=%s --sout '#udp{dst=%s:%d}' vlc://quit" \
-            % (local,self.movie, target, port)
-        vlc_server = netns_desc.create("Application")
-        vlc_server.set_attribute_value("command", command)
-        vlc_server.set_attribute_value("user", self.user)
-        vlc_server.connector("node").connect(netns_node.connector("apps"))
-        servers.append(vlc_server.guid)
-
-        command = "sudo dbus-uuidgen --ensure; vlc -vvv -I dummy udp://@%s:%d --sout '#std{access=file,mux=ts,dst=big_buck_bunny_stream.ts}' "  % (target, port)
-        vlc_client = pl_desc.create("Application")
-        vlc_client.set_attribute_value("buildDepends", "vlc")
-        vlc_client.set_attribute_value("rpmFusion", True)
-        vlc_client.set_attribute_value("command", command)
-        vlc_client.enable_trace("stdout")
-        vlc_client.enable_trace("stderr")
-        vlc_client.connector("node").connect(pl_node1.connector("apps"))
-        clients.append(vlc_client.guid)
-
-        # ROUTES
-        self.add_route(netns_node, (self.base_addr%32), 27, (self.base_addr%2))
-        self.add_route(netns_node, (self.base_addr%4), 30, (self.base_addr%2))
-        
-        self.add_route(pl_node1, (self.base_addr%32), 27, (self.base_addr%6))
-
-        self.add_route(ap_node, (self.base_addr%0), 30, (self.base_addr%5))
-        
-        xml = exp_desc.to_xml()
-        controller = ExperimentController(xml, self.root_dir)
-        controller.start()
-        while not controller.is_finished(app.guid):
-            time.sleep(0.5)
-        time.sleep(0.1)
-        controller.stop()
-        controller.shutdown()
-
-        """
-        xml = exp_desc.to_xml()
-        controller = ExperimentController(xml, self.root_dir)
-        controller.start()
-        stop = False
-        while not stop:
-            time.sleep(0.5)
-            stop = True
-            for guid in clients:
-                if not controller.is_finished(guid):
-                    stop = False
-        time.sleep(0.1)
-        controller.stop()
-        controller.shutdown()
-        """
-
-    def clean(self):
-        shutil.rmtree(self.root_dir)
-
-if __name__ == '__main__':
-    example = WirelessOverlay()
-    example.run()
-    example.clean()
-
index 9e4719a..22499d9 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -1,13 +1,14 @@
 #!/usr/bin/env python
 # vim: set fileencoding=utf-8
-from distutils.core import setup, Extension, Command
+from distutils.core import setup
+import sys
 
 setup(
         name        = "nepi",
         version     = "0.2",
         description = "High-level abstraction for running network experiments",
         author      = "Mathieu Lacage, Alina Quereilhac, Martín Ferrari and Claudio Freire",
-        url         = "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/nepi/",
+        url         = "http://nepi.pl.sophia.inria.fr/code/nepi",
         license     = "GPLv2",
         platforms   = "Linux",
         packages    = [
index 3de13cf..063aeac 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 class Attribute(object):
index ded9eda..0d1888f 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 """
index 11b9d7b..e630012 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 """
@@ -56,6 +55,11 @@ class Connector(object):
         self._connections.append(connector)
         connector._connections.append(self)
 
+    def get_connected_box(self, idx = 0):
+        if len(self._connections) == 0:
+            return None
+        return self._connections[idx].box
+
     def disconnect(self, connector):
         if connector not in self._connections or\
                 self not in connector._connections:
index e08e20f..9f034cb 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import Attribute, AttributesMap
index eee07f0..50243e4 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import AttributesMap, Attribute
index 05d36f4..0dbf39e 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import Attribute, AttributesMap
index 4ee3110..ade1ccc 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.core import execute
index a30e0a9..d3ef5dd 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_ID
index 119891c..a173c62 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 TESTBED_ID = "netns"
index 020b97f..577c39e 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
@@ -121,6 +120,8 @@ class TestbedController(testbed_impl.TestbedController):
             for trace_id, (trace, filename) in traces.iteritems():
                 if hasattr(trace, "close"):
                     trace.close()
+                if hasattr(trace, "signal"):
+                    trace.signal()
         for guid, element in self._elements.iteritems():
             if isinstance(element, self.TunChannel):
                 element.cleanup()
index 9364293..5d1e838 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 29cb993..45a2de9 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 41ac5ac..1441bef 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from factories_metadata import wifi_standards, l4_protocols, \
@@ -2555,4 +2554,11 @@ attributes = dict({
         "flags" : Attribute.ExecImmutable | Attribute.Metadata,
         "validation_function" : validation.is_enum,
         }),
+    "Up" : dict({
+        "name" : "Up", 
+        "help" : "Flag to enable or disable interface",
+        "type" : Attribute.BOOL,
+        "value" : True,
+        "validation_function" : validation.is_integer,
+        }),
 })
index f68b31c..f93e372 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID
index 7a1f4c5..27fb726 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 TESTBED_ID = "ns3"
index 0635f26..5777f83 100644 (file)
@@ -1,6 +1,6 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+from util import  _get_ipv4_protocol_guid, _get_node_guid, _get_dev_number
 from nepi.core import testbed_impl
 from nepi.core.attributes import Attribute
 from constants import TESTBED_ID, TESTBED_VERSION
@@ -109,8 +109,22 @@ class TestbedController(testbed_impl.TestbedController):
         if factory_id in self.LOCAL_FACTORIES:
             setattr(element, name, value)
         elif not factory.box_attributes.is_attribute_metadata(name):
-            ns3_value = self._to_ns3_value(guid, name, value)
-            self._set_attribute(name, ns3_value, element)
+            if name == "Up":
+                ipv4_guid =  _get_ipv4_protocol_guid(self, guid)
+                if not ipv4_guid in self._elements:
+                    return
+                ipv4 = self._elements[ipv4_guid]
+                if value == False:
+                    nint = ipv4.GetNInterfaces()
+                    for i in xrange(0, nint):
+                        ipv4.SetDown(i)
+                else:
+                    nint = ipv4.GetNInterfaces()
+                    for i in xrange(0, nint):
+                        ipv4.SetUp(i)
+            else:
+                ns3_value = self._to_ns3_value(guid, name, value)
+                self._set_attribute(name, ns3_value, element)
 
     def get(self, guid, name, time = TIME_NOW):
         value = super(TestbedController, self).get(guid, name, time)
@@ -123,12 +137,25 @@ class TestbedController(testbed_impl.TestbedController):
                 return getattr(element, name)
             else:
                 return value
+        else: 
+            if name == "Up":
+                ipv4_guid =  _get_ipv4_protocol_guid(self, guid)
+                if not ipv4_guid in self._elements:
+                    return True
+                ipv4 = self._elements[ipv4_guid]
+                nint = ipv4.GetNInterfaces()
+                value = True
+                for i in xrange(0, nint):
+                    value = ipv4.IsUp(i)
+                    if not value: break
+                return value
+
         if factory.box_attributes.is_attribute_metadata(name):
             return value
 
         TypeId = self.ns3.TypeId()
         typeid = TypeId.LookupByName(factory_id)
-        info = TypeId.AttributeInfo()
+        info = TypeId.AttributeInformation()
         if not typeid or not typeid.LookupAttributeByName(name, info):
             raise AttributeError("Invalid attribute %s for element type %d" % \
                 (name, guid))
@@ -137,6 +164,7 @@ class TestbedController(testbed_impl.TestbedController):
         self._get_attribute(name, ns3_value, element)
         value = ns3_value.SerializeToString(checker)
         attr_type = factory.box_attributes.get_attribute_type(name)
+
         if attr_type == Attribute.INTEGER:
             return int(value)
         if attr_type == Attribute.DOUBLE:
@@ -191,7 +219,7 @@ class TestbedController(testbed_impl.TestbedController):
 
     def _schedule_event(self, condition, func, *args):
         """Schedules event on running experiment"""
-        def execute_event(condition, has_event_occurred, func, *args):
+        def execute_event(contextId, condition, has_event_occurred, func, *args):
             # exec func
             try:
                 func(*args)
@@ -263,7 +291,7 @@ class TestbedController(testbed_impl.TestbedController):
         factory_id = self._create[guid]
         TypeId = self.ns3.TypeId()
         typeid = TypeId.LookupByName(factory_id)
-        info = TypeId.AttributeInfo()
+        info = TypeId.AttributeInformation()
         if not typeid.LookupAttributeByName(name, info):
             raise RuntimeError("Attribute %s doesn't belong to element %s" \
                    % (name, factory_id))
@@ -308,7 +336,7 @@ class TestbedController(testbed_impl.TestbedController):
         TypeId = self.ns3.TypeId()
         typeid = TypeId.LookupByName(factory_id)
         for name, value in params.iteritems():
-            info = self.ns3.TypeId.AttributeInfo()
+            info = self.ns3.TypeId.AttributeInformation()
             found = typeid.LookupAttributeByName(name, info)
             if found and \
                 (info.flags & TypeId.ATTR_CONSTRUCT == TypeId.ATTR_CONSTRUCT):
index c2a2bd2..7132e31 100644 (file)
@@ -1,6 +1,6 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+from util import  _get_ipv4_protocol_guid, _get_node_guid, _get_dev_number
 from nepi.util import tags
 from nepi.util.constants import AF_INET, ApplicationStatus as AS, \
         FactoryCategories as FC
@@ -42,39 +42,6 @@ service_flow_scheduling_type = dict ({
     "SF_TYPE_ALL": 255
 })
 
-def _get_ipv4_protocol_guid(testbed_instance, node_guid):
-    # search for the Ipv4L3Protocol asociated with the device
-    protos_guids = testbed_instance.get_connected(node_guid, "protos", "node")
-    if len(protos_guids) == 0:
-        raise RuntimeError("No protocols where found for the node %d" % node_guid)
-    ipv4_guid = None
-    for proto_guid in protos_guids:
-        proto_factory_id = testbed_instance._create[proto_guid]
-        if proto_factory_id == "ns3::Ipv4L3Protocol":
-            ipv4_guid = proto_guid
-            break
-    if not ipv4_guid:
-        raise RuntimeError("No Ipv4L3Protocol associated to node %d. Can't add Ipv4 addresses" % node_guid)
-    return ipv4_guid
-
-def _get_node_guid(testbed_instance, guid):
-    # search for the node asociated with the device
-    node_guids = testbed_instance.get_connected(guid, "node", "devs")
-    if len(node_guids) == 0:
-        raise RuntimeError("Can't instantiate interface %d outside node" % guid)
-    node_guid = node_guids[0]
-    return node_guid
-
-def _get_dev_number(testbed_instance, guid):
-    node_guid = _get_node_guid(testbed_instance, guid)
-    dev_guids = testbed_instance.get_connected(node_guid, "devs", "node")
-    interface_number = 0
-    for guid_ in dev_guids:
-        if guid_ == guid:
-            break
-        interface_number += 1
-    return interface_number
-
 def _follow_trace(testbed_instance, guid, trace_id, filename):
     testbed_instance.follow_trace(guid, trace_id, filename)
     filepath = testbed_instance.trace_filepath(guid, trace_id)
@@ -896,6 +863,7 @@ factories_info = dict({
         "configure_function": configure_node,
         "help": "",
         "connector_types": ["devs", "apps", "protos", "mobility"],
+        "box_attributes": ["Up"],
         "tags": [tags.NODE, tags.ALLOW_ROUTES],
     }),
      "ns3::GridPositionAllocator": dict({
index 94fb9fb..1766e6a 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index ae9e700..3b154e4 100644 (file)
@@ -13,7 +13,7 @@ from ns.nix_vector_routing import *
 from ns.olsr import *
 from ns.aodv import *
 from ns.dsdv import *
-from ns.click import *
+#from ns.click import *
 from ns.mobility import *
 from ns.wifi import *
 from ns.netanim import *
@@ -28,6 +28,6 @@ from ns.mpi import *
 from ns.topology_read import *
 from ns.energy import *
 from ns.tools import *
-from ns.visualizer import *
+#from ns.visualizer import *
 from ns.point_to_point_layout import *
 from ns.fd_net_device import *
index d9a4df5..e8859a8 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 traces = dict({
diff --git a/src/nepi/testbeds/ns3/util.py b/src/nepi/testbeds/ns3/util.py
new file mode 100644 (file)
index 0000000..a5ee731
--- /dev/null
@@ -0,0 +1,33 @@
+def _get_ipv4_protocol_guid(testbed_instance, node_guid):
+    # search for the Ipv4L3Protocol asociated with the device
+    protos_guids = testbed_instance.get_connected(node_guid, "protos", "node")
+    if len(protos_guids) == 0:
+        raise RuntimeError("No protocols where found for the node %d" % node_guid)
+    ipv4_guid = None
+    for proto_guid in protos_guids:
+        proto_factory_id = testbed_instance._create[proto_guid]
+        if proto_factory_id == "ns3::Ipv4L3Protocol":
+            ipv4_guid = proto_guid
+            break
+    if not ipv4_guid:
+        raise RuntimeError("No Ipv4L3Protocol associated to node %d. Can't add Ipv4 addresses" % node_guid)
+    return ipv4_guid
+
+def _get_node_guid(testbed_instance, guid):
+    # search for the node asociated with the device
+    node_guids = testbed_instance.get_connected(guid, "node", "devs")
+    if len(node_guids) == 0:
+        raise RuntimeError("Can't instantiate interface %d outside node" % guid)
+    node_guid = node_guids[0]
+    return node_guid
+
+def _get_dev_number(testbed_instance, guid):
+    node_guid = _get_node_guid(testbed_instance, guid)
+    dev_guids = testbed_instance.get_connected(node_guid, "devs", "node")
+    interface_number = 0
+    for guid_ in dev_guids:
+        if guid_ == guid:
+            break
+        interface_number += 1
+    return interface_number
+
index 80831f6..baf8911 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 # TODO: Allow netrefs!
index 1ea99bd..f3e1ac0 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index e883439..a192707 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID
@@ -20,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.
@@ -207,10 +208,13 @@ class Dependency(object):
             raise RuntimeError, "Failed to set up application %s: %s %s" % (self.home_path, e.args[0], e.args[1],)
         
         if self.stdin:
+            stdin = self.stdin
+            if not os.path.isfile(stdin):
+                stdin = cStringIO.StringIO(self.stdin)
+
             # Write program input
             try:
-                self._popen_scp(
-                    cStringIO.StringIO(self.stdin),
+                self._popen_scp(stdin,
                     '%s@%s:%s' % (self.node.slicename, self.node.hostname, 
                         os.path.join(self.home_path, 'stdin') ),
                     )
@@ -565,7 +569,7 @@ class Dependency(object):
     def _do_install(self):
         if self.install:
             self._logger.info("Installing %s at %s", self, self.node.hostname)
-            
+           
             # Install application
             try:
                 self._popen_ssh_command(
@@ -898,13 +902,15 @@ class NS3Dependency(Dependency):
     def __init__(self, api = None):
         super(NS3Dependency, self).__init__(api)
         
-        self.buildDepends = 'make waf gcc gcc-c++ gccxml unzip'
+        self.buildDepends = 'make waf gcc gcc-c++ gccxml unzip bzr'
         
         # We have to download the sources, untar, build...
-        pybindgen_source_url = "http://yans.pl.sophia.inria.fr/trac/nepi/raw-attachment/wiki/WikiStart/pybindgen-r794.tar.gz"
         pygccxml_source_url = "http://leaseweb.dl.sourceforge.net/project/pygccxml/pygccxml/pygccxml-1.0/pygccxml-1.0.0.zip"
-        ns3_source_url = "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/ns-3.11-nepi/archive/tip.tar.gz"
-        passfd_source_url = "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/python-passfd/archive/tip.tar.gz"
+        ns3_source_url = "http://nepi.pl.sophia.inria.fr/code/nepi-ns3.13/archive/tip.tar.gz"
+        passfd_source_url = "http://nepi.pl.sophia.inria.fr/code/python-passfd/archive/tip.tar.gz"
+        
+        pybindgen_version = "797"
+
         self.build =(
             " ( "
             "  cd .. && "
@@ -918,26 +924,23 @@ class NS3Dependency(Dependency):
                 # Not working, rebuild
                      # Archive SHA1 sums to check
                      "echo '7158877faff2254e6c094bf18e6b4283cac19137  pygccxml-1.0.0.zip' > archive_sums.txt && "
-                     "echo 'a18c2ccffd0df517bc37e2f3a2475092517c43f2  pybindgen-src.tar.gz' >> archive_sums.txt && "
                      " ( " # check existing files
                      " sha1sum -c archive_sums.txt && "
                      " test -f passfd-src.tar.gz && "
                      " test -f ns3-src.tar.gz "
                      " ) || ( " # nope? re-download
-                     " rm -f pybindgen-src.zip pygccxml-1.0.0.zip passfd-src.tar.gz ns3-src.tar.gz && "
-                     " wget -q -c -O pybindgen-src.tar.gz %(pybindgen_source_url)s && " # continue, to exploit the case when it has already been dl'ed
+                     " rm -rf pybindgen pygccxml-1.0.0.zip passfd-src.tar.gz ns3-src.tar.gz && "
+                     " bzr checkout lp:pybindgen -r %(pybindgen_version)s && " # continue, to exploit the case when it has already been dl'ed
                      " wget -q -c -O pygccxml-1.0.0.zip %(pygccxml_source_url)s && " 
                      " wget -q -c -O passfd-src.tar.gz %(passfd_source_url)s && "
                      " wget -q -c -O ns3-src.tar.gz %(ns3_source_url)s && "  
                      " sha1sum -c archive_sums.txt " # Check SHA1 sums when applicable
                      " ) && "
                      "unzip -n pygccxml-1.0.0.zip && "
-                     "mkdir -p pybindgen-src && "
                      "mkdir -p ns3-src && "
                      "mkdir -p passfd-src && "
                      "tar xzf ns3-src.tar.gz --strip-components=1 -C ns3-src && "
                      "tar xzf passfd-src.tar.gz --strip-components=1 -C passfd-src && "
-                     "tar xzf pybindgen-src.tar.gz --strip-components=1 -C pybindgen-src && "
                      "rm -rf target && "    # mv doesn't like unclean targets
                      "mkdir -p target && "
                      "cd pygccxml-1.0.0 && "
@@ -945,7 +948,7 @@ class NS3Dependency(Dependency):
                      "python setup.py build && "
                      "python setup.py install --install-lib ${BUILD}/target && "
                      "python setup.py clean && "
-                     "cd ../pybindgen-src && "
+                     "cd ../pybindgen && "
                      "export PYTHONPATH=$PYTHONPATH:${BUILD}/target && "
                      "./waf configure --prefix=${BUILD}/target -d release && "
                      "./waf && "
@@ -962,12 +965,12 @@ class NS3Dependency(Dependency):
                      "./waf &&"
                      "./waf install && "
                      "rm -f ${BUILD}/target/lib/*.so && "
-                     "cp -a ${BUILD}/ns3-src/build/release/libns3*.so ${BUILD}/target/lib && "
-                     "cp -a ${BUILD}/ns3-src/build/release/bindings/python/ns ${BUILD}/target/lib &&"
+                     "cp -a ${BUILD}/ns3-src/build/libns3*.so ${BUILD}/target/lib && "
+                     "cp -a ${BUILD}/ns3-src/build/bindings/python/ns ${BUILD}/target/lib &&"
                      "./waf clean "
              " )"
                      % dict(
-                        pybindgen_source_url = server.shell_escape(pybindgen_source_url),
+                        pybindgen_version = server.shell_escape(pybindgen_version),
                         pygccxml_source_url = server.shell_escape(pygccxml_source_url),
                         ns3_source_url = server.shell_escape(ns3_source_url),
                         passfd_source_url = server.shell_escape(passfd_source_url),
@@ -1091,3 +1094,167 @@ class YumDependency(Dependency):
                            r')', 
                            re.I)
         return badre.search(out) or badre.search(err) or self.node.check_bad_host(out,err)
+
+
+class CCNxDaemon(Application):
+    """
+    An application also has dependencies, but also a command to be ran and monitored.
+    
+    It adds the output of that command as traces.
+    """
+    
+    def __init__(self, api=None):
+        super(CCNxDaemon,self).__init__(api)
+        
+        # Attributes
+        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"
+        self.buildDepends = 'make gcc development-tools openssl-devel expat-devel libpcap-devel libxml2-devel'
+
+        self.ccnx_0_5_1_build = (
+            " ( "
+            "  cd .. && "
+            "  test -d ccnx-0.5.1-src/build/bin "
+            " ) || ( "
+                # Not working, rebuild
+                "("
+                     " mkdir -p ccnx-0.5.1-src && "
+                     " wget -q -c -O ccnx-0.5.1-src.tar.gz %(ccnx_source_url)s &&"
+                     " tar xf ccnx-0.5.1-src.tar.gz --strip-components=1 -C ccnx-0.5.1-src "
+                ") && "
+                     "cd ccnx-0.5.1-src && "
+                     "mkdir -p build/include &&"
+                     "mkdir -p build/lib &&"
+                     "mkdir -p build/bin &&"
+                     "I=$PWD/build && "
+                     "INSTALL_BASE=$I ./configure &&"
+                     "make && make install"
+             " )") % dict(
+                     ccnx_source_url = server.shell_escape(self.ccnx_0_5_1_sources),
+                )
+
+        self.ccnx_0_5_1_install = (
+            " ( "
+            "  test -d ${BUILD}/ccnx-0.5.1-src/build/bin && "
+            "  cp -r ${BUILD}/ccnx-0.5.1-src/build/bin ${SOURCES}"
+            " )"
+        )
+
+        self.ccnx_0_6_0_build = (
+            " ( "
+            "  cd .. && "
+            "  test -d ccnx-0.6.0-src/build/bin "
+            " ) || ( "
+                # Not working, rebuild
+                "("
+                     " mkdir -p ccnx-0.6.0-src && "
+                     " wget -q -c -O ccnx-0.6.0-src.tar.gz %(ccnx_source_url)s &&"
+                     " tar xf ccnx-0.6.0-src.tar.gz --strip-components=1 -C ccnx-0.6.0-src "
+                ") && "
+                     "cd ccnx-0.6.0-src && "
+                     "./configure && make"
+             " )") % dict(
+                     ccnx_source_url = server.shell_escape(self.ccnx_0_6_0_sources),
+                )
+
+        self.ccnx_0_6_0_install = (
+            " ( "
+            "  test -d ${BUILD}/ccnx-0.6.0-src/bin && "
+            "  cp -r ${BUILD}/ccnx-0.6.0-src/bin ${SOURCES}"
+            " )"
+        )
+
+        self.env['PATH'] = "$PATH:${SOURCES}/bin"
+
+    def setup(self):
+        # setting ccn sources
+        if not self.build:
+            if self.ccnxVersion == 'ccnx-0.6.0':
+                self.build = self.ccnx_0_6_0_build
+            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':
+                self.install = self.ccnx_0_6_0_install
+            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
+        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, 
+                routes)
+
+            routescmd = " ; ".join(routes)
+            self.command += " ; "
+            self.command += routescmd
+
+        # Start will be invoked in prestart step
+        super(CCNxDaemon, self).start()
+            
+    def kill(self):
+        self._logger.info("Killing %s", self)
+
+        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)
+
+        try:
+            self._popen_scp(
+                command,
+                '%s@%s:%s' % (self.node.slicename, self.node.hostname, 
+                    os.path.join(self.home_path, "kill.sh"))
+                )
+        except RuntimeError, e:
+            raise RuntimeError, "Failed to kill ccndxdaemon: %s %s" \
+                    % (e.args[0], e.args[1],)
+        
+
+        script = "bash ./kill.sh"
+        (out,err),proc = rspawn.remote_spawn(
+            script,
+            pidfile = 'kill-pid',
+            home = self.home_path,
+            stdin = '/dev/null',
+            stdout = 'killlog',
+            stderr = rspawn.STDOUT,
+            
+            host = self.node.hostname,
+            port = None,
+            user = self.node.slicename,
+            agent = None,
+            ident_key = self.node.ident_path,
+            server_key = self.node.server_key,
+            hostip = self.node.hostip,
+            )
+        
+        if proc.wait():
+            raise RuntimeError, "Failed to kill cnnxdaemon: %s %s" % (out,err,)
+        
+        super(CCNxDaemon, self).kill()
index ee2c706..e749e93 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 TESTBED_ID = "planetlab"
index da5f2f8..467d9fe 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
@@ -49,7 +48,12 @@ class TestbedController(testbed_impl.TestbedController):
         self._just_provisioned = set()
         
         self._load_blacklist()
-        
+
+        self._slice_id = None
+        self._plcapi = None
+        self._sliceapi = None
+        self._vsys_vnet = None
+
         self._logger = logging.getLogger('nepi.testbeds.planetlab')
         
         self.recovering = False
@@ -59,41 +63,39 @@ class TestbedController(testbed_impl.TestbedController):
         return self._home_directory
 
     @property
-    def plapi(self):
-        if not hasattr(self, '_plapi'):
+    def plcapi(self):
+        if not self._plcapi:
             import plcapi
-
-            if self.authUser:
-                self._plapi = plcapi.PLCAPI(
-                    username = self.authUser,
-                    password = self.authString,
-                    hostname = self.plcHost,
-                    urlpattern = self.plcUrl
+            self._plcapi = plcapi.plcapi(
+                    self.authUser,
+                    self.authString,
+                    self.plcHost,
+                    self.plcUrl
                     )
+        return self._plcapi
+
+    @property
+    def sliceapi(self):
+        if not self._sliceapi:
+            if not self.sfa:
+                self._sliceapi = self.plcapi
             else:
-                # anonymous access - may not be enough for much
-                self._plapi = plcapi.PLCAPI()
-        return self._plapi
+                from nepi.util import sfiapi
+                self._sliceapi = sfiapi.sfiapi(self.slice_id)
+        return self._sliceapi
 
     @property
     def slice_id(self):
-        if not hasattr(self, '_slice_id'):
-            slices = self.plapi.GetSlices(self.slicename, fields=('slice_id',))
-            if slices:
-                self._slice_id = slices[0]['slice_id']
-            else:
-                # If it wasn't found, don't remember this failure, keep trying
-                return None
+        if not self._slice_id:
+            self._slice_id = self.sliceapi.GetSliceId(self.slicename)
         return self._slice_id
     
     @property
     def vsys_vnet(self):
-        if not hasattr(self, '_vsys_vnet'):
-            self._vsys_vnet = plutil.getVnet(
-                self.plapi,
-                self.slicename)
+        if not self._vsys_vnet:
+            self._vsys_vnet = self.sliceapi.GetSliceVnetSysTag(self.slicename)
         return self._vsys_vnet
-    
+
     def _load_blacklist(self):
         blpath = environ.homepath('plblacklist')
         
@@ -105,9 +107,7 @@ class TestbedController(testbed_impl.TestbedController):
             
         try:
             self._blacklist = set(
-                map(int,
-                    map(str.strip, bl.readlines())
-                )
+                map(str.strip, bl.readlines())
             )
         finally:
             bl.close()
@@ -143,9 +143,16 @@ class TestbedController(testbed_impl.TestbedController):
             get_attribute_value("tapPortBase")
         self.p2pDeployment = self._attributes.\
             get_attribute_value("p2pDeployment")
-        self.dedicatedSlice = self._attributes.\
-            get_attribute_value("dedicatedSlice")
-        
+        self.cleanProc = self._attributes.\
+            get_attribute_value("cleanProc")
+        self.cleanHome = self._attributes.\
+            get_attribute_value("cleanHome")
+        self.sfa = self._attributes.\
+            get_attribute_value("sfa")
+        if self.sfa:
+            self._slice_id = self._attributes.\
+            get_attribute_value("sliceHrn")
+
         if not self.slicename:
             raise RuntimeError, "Slice not set"
         if not self.authUser:
@@ -204,7 +211,7 @@ class TestbedController(testbed_impl.TestbedController):
         reserved = set(self._blacklist)
         for guid, node in self._elements.iteritems():
             if isinstance(node, self._node.Node) and node._node_id is not None:
-                reserved.add(node._node_id)
+                reserved.add(node.hostname)
         
         # Initial algo:
         #   look for perfectly defined nodes
@@ -217,32 +224,36 @@ class TestbedController(testbed_impl.TestbedController):
                 filter_slice_id = self.slice_id)
             
             node_id = None
+            candidate_hosts = set(candidates.keys() if candidates else [])
             reserve_lock.acquire()
             try:
-                candidates -= reserved
-                if len(candidates) == 1:
-                    node_id = iter(candidates).next()
-                    reserved.add(node_id)
-                elif not candidates:
+                candidate_hosts -= reserved
+                if len(candidate_hosts) == 1:
+                    hostname = iter(candidate_hosts).next()
+                    node_id = candidates[hostname]
+                    reserved.add(hostname)
+                elif not candidate_hosts:
                     # Try again including unassigned nodes
                     reserve_lock.release()
                     try:
                         candidates = node.find_candidates()
                     finally:
                         reserve_lock.acquire()
-                    candidates -= reserved
-                    if len(candidates) > 1:
+                    candidate_hosts = set(candidates.keys() if candidates else [])
+                    candidate_hosts -= reserved
+                    if len(candidate_hosts) > 1:
                         return
-                    if len(candidates) == 1:
-                        node_id = iter(candidates).next()
+                    if len(candidate_hosts) == 1:
+                        hostname = iter(candidate_hosts).next()
+                        node_id = candidates[hostname]
                         to_provision.add(node_id)
-                        reserved.add(node_id)
+                        reserved.add(hostname)
                     elif not candidates:
-                        raise RuntimeError, "Cannot assign resources for node %s, no candidates sith %s" % (guid,
+                        raise RuntimeError, "Cannot assign resources for node %s, no candidates with %s" % (guid,
                             node.make_filter_description())
             finally:
                 reserve_lock.release()
-            
+           
             if node_id is not None:
                 node.assign_node_id(node_id)
         
@@ -262,14 +273,16 @@ class TestbedController(testbed_impl.TestbedController):
             # If we have only one candidate, simply use it
             candidates = node.find_candidates(
                 filter_slice_id = filter_slice_id)
-            candidates -= reserved
-            reqs.append(candidates)
+            for r in reserved:
+                if candidates.has_key(r):
+                    del candidates[r]
+            reqs.append(candidates.values())
             nodes.append(node)
         for guid, node in self._elements.iteritems():
             if isinstance(node, self._node.Node) and node._node_id is None:
                 runner.put(genreqs, node, self.slice_id)
         runner.sync()
-        
+       
         if nodes and reqs:
             if recover:
                 raise RuntimeError, "Impossible to recover: unassigned host for Nodes %r" % (nodes,)
@@ -302,9 +315,9 @@ class TestbedController(testbed_impl.TestbedController):
     def do_provisioning(self):
         if self._to_provision:
             # Add new nodes to the slice
-            cur_nodes = self.plapi.GetSlices(self.slicename, ['node_ids'])[0]['node_ids']
+            cur_nodes = self.sliceapi.GetSliceNodes(self.slice_id)
             new_nodes = list(set(cur_nodes) | self._to_provision)
-            self.plapi.UpdateSlice(self.slicename, nodes=new_nodes)
+            self.sliceapi.AddSliceNodes(self.slice_id, nodes=new_nodes)
 
         # cleanup
         self._just_provisioned = self._to_provision
@@ -356,7 +369,7 @@ class TestbedController(testbed_impl.TestbedController):
                 if isinstance(node, self._node.Node):
                     if not node.is_alive():
                         self._logger.warn("Blacklisting %s for unresponsiveness", node.hostname)
-                        self._blacklist.add(node._node_id)
+                        self._blacklist.add(node.hostname)
                         node.unassign_node()
             
             try:
@@ -520,6 +533,12 @@ class TestbedController(testbed_impl.TestbedController):
         # TODO: take on account schedule time for the task
         element = self._elements[guid]
         if element:
+            if name == "up":
+                if value == True:
+                    element.if_up()
+                else:
+                    element.if_down()
+
             try:
                 setattr(element, name, value)
             except:
@@ -667,6 +686,7 @@ class TestbedController(testbed_impl.TestbedController):
                     Parallel(metadata.NS3DEPENDENCY),
                     Parallel(metadata.DEPENDENCY),
                     Parallel(metadata.APPLICATION),
+                    Parallel(metadata.CCNXDAEMON),
                 ])
 
             # Tunnels are not harmed by configuration after
@@ -695,8 +715,10 @@ class TestbedController(testbed_impl.TestbedController):
         finally:
             self.recovering = True
     
-    def _make_generic(self, parameters, kind):
-        app = kind(self.plapi)
+    def _make_generic(self, parameters, kind, **kwargs):
+        args = dict({'api': self.plcapi})
+        args.update(kwargs)
+        app = kind(**args)
         app.testbed = weakref.ref(self)
 
         # Note: there is 1-to-1 correspondence between attribute names
@@ -715,8 +737,10 @@ class TestbedController(testbed_impl.TestbedController):
         return app
 
     def _make_node(self, parameters):
-        node = self._make_generic(parameters, self._node.Node)
-        node.enable_cleanup = self.dedicatedSlice
+        args = dict({'sliceapi': self.sliceapi})
+        node = self._make_generic(parameters, self._node.Node, **args)
+        node.enable_proc_cleanup = self.cleanProc
+        node.enable_home_cleanup = self.cleanHome
         return node
 
     def _make_node_iface(self, parameters):
@@ -734,8 +758,10 @@ class TestbedController(testbed_impl.TestbedController):
     def _make_internet(self, parameters):
         return self._make_generic(parameters, self._interfaces.Internet)
 
-    def _make_application(self, parameters):
-        return self._make_generic(parameters, self._app.Application)
+    def _make_application(self, parameters, clazz = None):
+        if not clazz:
+            clazz = self._app.Application
+        return self._make_generic(parameters, clazz)
 
     def _make_dependency(self, parameters):
         return self._make_generic(parameters, self._app.Dependency)
index e3668ec..60295e2 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID
@@ -61,9 +60,16 @@ class NodeIface(object):
         
         if self.node is None or self.node._node_id is None:
             raise RuntimeError, "Cannot pick interface without an assigned node"
-        
+      
+        # HACK: SFA doesnt give the node_id!!
+        if not isinstance(self.node._node_id, int):
+            node_data = self._api.GetNodes(filters={'hostname':self.node.hostname}, fields=('node_id',))[0]
+            node_id = node_data['node_id']
+        else:
+            node_id = self.node._node_id
+
         avail = self._api.GetInterfaces(
-            node_id=self.node._node_id, 
+            node_id=node_id, 
             is_primary=self.primary,
             fields=('interface_id','mac','netmask','ip') )
         
@@ -193,6 +199,14 @@ class TunIface(object):
         if self.peer_proto_impl:
             return self.peer_proto_impl.if_name
 
+    def if_up(self):
+        if self.peer_proto_impl:
+            return self.peer_proto_impl.if_up()
+
+    def if_down(self):
+        if self.peer_proto_impl:
+            return self.peer_proto_impl.if_down()
+
     def routes_here(self, route):
         """
         Returns True if the route should be attached to this interface
index cd01367..5e07320 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import time
@@ -23,6 +22,7 @@ NODEIFACE = "NodeInterface"
 TUNIFACE = "TunInterface"
 TAPIFACE = "TapInterface"
 APPLICATION = "Application"
+CCNXDAEMON = "CCNxDaemon"
 DEPENDENCY = "Dependency"
 NEPIDEPENDENCY = "NepiDependency"
 NS3DEPENDENCY = "NS3Dependency"
@@ -203,7 +203,7 @@ def connect_dep(testbed_instance, node_guid, app_guid, node=None, app=None):
     if app.depends:
         node.required_packages.update(set(
             app.depends.split() ))
-    
+   
     if app.add_to_path:
         if app.home_path and app.home_path not in node.pythonpath:
             node.pythonpath.append(app.home_path)
@@ -324,6 +324,16 @@ def create_application(testbed_instance, guid):
     
     testbed_instance.elements[guid] = element
 
+def create_ccnxdaemon(testbed_instance, guid):
+    parameters = testbed_instance._get_parameters(guid)
+    element = testbed_instance._make_application(parameters,
+            clazz  = testbed_instance._app.CCNxDaemon )
+    
+    # Just inject configuration stuff
+    element.home_path = "nepi-ccnd-%s" % (guid,)
+    
+    testbed_instance.elements[guid] = element
+
 def create_dependency(testbed_instance, guid):
     parameters = testbed_instance._get_parameters(guid)
     element = testbed_instance._make_dependency(parameters)
@@ -390,6 +400,15 @@ def create_netpipe(testbed_instance, guid):
 
 ### Start/Stop functions ###
 
+def prestart_ccnxdaemon(testbed_instance, guid):
+    # ccnx daemon needs to start before the rest of the
+    # ccn applications
+    start_application(testbed_instance, guid)
+
+def stop_ccndaemon(testbed_instance, guid):
+    app = testbed_instance.elements[guid]
+    app.kill()
+
 def start_application(testbed_instance, guid):
     parameters = testbed_instance._get_parameters(guid)
     traces = testbed_instance._get_traces(guid)
@@ -697,7 +716,7 @@ connections = [
     }),
     dict({
         "from": (TESTBED_ID, NODE, "apps"),
-        "to":   (TESTBED_ID, (APPLICATION, MULTICASTANNOUNCER), "node"),
+        "to":   (TESTBED_ID, (APPLICATION, CCNXDAEMON, MULTICASTANNOUNCER), "node"),
         "init_code": connect_dep,
         "can_cross": False
     }),
@@ -1023,7 +1042,19 @@ attributes = dict({
                 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
                 "validation_function": validation.is_number,
             }),
-            
+     "timeframe": dict({
+                "name": "timeframe",
+                "help": "Past time period in which to check information about the node. Values are year,month, week, latest", 
+                "type": Attribute.ENUM, 
+                "value": "week",
+                "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
+                "allowed": ["latest",
+                            "week",
+                            "month",
+                            "year"],
+                "validation_function": validation.is_enum,
+            }),
+           
     "up": dict({
                 "name": "up",
                 "help": "Link up",
@@ -1107,7 +1138,14 @@ attributes = dict({
                 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
                 "validation_function": validation.is_string
             }),
-    "sudo": dict({
+    "ccnroutes": dict({
+                "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,
+                "validation_function": validation.is_string
+            }),
+     "sudo": dict({
                 "name": "sudo",
                 "help": "Run with root privileges",
                 "type": Attribute.BOOL,
@@ -1153,6 +1191,26 @@ attributes = dict({
                 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
                 "validation_function": validation.is_string
             }),
+    "ccnxversion": dict({      
+                "name": "ccnxVersion",
+                "help": "Version of ccnx source code to install in the node.",
+                "type": Attribute.ENUM, 
+                "value": "ccnx-0.6.0",
+                "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
+                "allowed": ["ccnx-0.6.0",
+                            "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. "
@@ -1314,14 +1372,15 @@ create_order = [
     INTERNET, NODE, NODEIFACE, CLASSQUEUEFILTER, TOSQUEUEFILTER, 
     MULTICASTANNOUNCER, MULTICASTFORWARDER, MULTICASTROUTER, 
     TUNFILTER, TAPIFACE, TUNIFACE, NETPIPE, 
-    NEPIDEPENDENCY, NS3DEPENDENCY, DEPENDENCY, APPLICATION ]
+    NEPIDEPENDENCY, NS3DEPENDENCY, DEPENDENCY, CCNXDAEMON, APPLICATION ]
 
 configure_order = [ 
     INTERNET, Parallel(NODE), 
     NODEIFACE, 
     Parallel(MULTICASTANNOUNCER), Parallel(MULTICASTFORWARDER), Parallel(MULTICASTROUTER), 
     Parallel(TAPIFACE), Parallel(TUNIFACE), NETPIPE, 
-    Parallel(NEPIDEPENDENCY), Parallel(NS3DEPENDENCY), Parallel(DEPENDENCY), Parallel(APPLICATION) ]
+    Parallel(NEPIDEPENDENCY), Parallel(NS3DEPENDENCY), Parallel(DEPENDENCY), Parallel(CCNXDAEMON),
+    Parallel(APPLICATION)]
 
 # Start (and prestart) node after ifaces, because the node needs the ifaces in order to set up routes
 start_order = [ INTERNET, 
@@ -1329,11 +1388,13 @@ start_order = [ INTERNET,
     Parallel(TAPIFACE), Parallel(TUNIFACE), 
     Parallel(NODE), NETPIPE, 
     Parallel(MULTICASTANNOUNCER), Parallel(MULTICASTFORWARDER), Parallel(MULTICASTROUTER), 
-    Parallel(NEPIDEPENDENCY), Parallel(NS3DEPENDENCY), Parallel(DEPENDENCY), Parallel(APPLICATION) ]
+    Parallel(NEPIDEPENDENCY), Parallel(NS3DEPENDENCY), Parallel(DEPENDENCY), Parallel(CCNXDAEMON),
+    Parallel(APPLICATION)]
 
 # cleanup order
 shutdown_order = [ 
     Parallel(APPLICATION), 
+    Parallel (CCNXDAEMON),
     Parallel(MULTICASTROUTER), Parallel(MULTICASTFORWARDER), Parallel(MULTICASTANNOUNCER), 
     Parallel(TAPIFACE), Parallel(TUNIFACE), Parallel(NETPIPE), 
     Parallel(NEPIDEPENDENCY), Parallel(NS3DEPENDENCY), Parallel(DEPENDENCY), 
@@ -1360,6 +1421,7 @@ factories_info = dict({
                 "max_load",
                 "min_cpu",
                 "max_cpu",
+                "timeframe",
                 
                 # NEPI-in-NEPI attributes
                 ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP,
@@ -1527,6 +1589,21 @@ factories_info = dict({
             "traces": ["stdout", "stderr", "buildlog", "output"],
             "tags": [tags.APPLICATION],
         }),
+
+    CCNXDAEMON: dict({
+            "help": "CCNx daemon",
+            "category": FC.CATEGORY_APPLICATIONS,
+            "create_function": create_ccnxdaemon,
+            "prestart_function": prestart_ccnxdaemon,
+            "status_function": status_application,
+            "stop_function": stop_application,
+            "configure_function": configure_application,
+            "box_attributes": ["ccnroutes", "build", "ccnlocalport",
+                "install", "ccnxversion", "sources"],
+            "connector_types": ["node"],
+            "traces": ["stdout", "stderr", "buildlog", "output"],
+            "tags": [tags.APPLICATION],
+        }),
     DEPENDENCY: dict({
             "help": "Requirement for package or application to be installed on some node",
             "category": FC.CATEGORY_APPLICATIONS,
@@ -1622,6 +1699,20 @@ factories_info = dict({
 })
 
 testbed_attributes = dict({
+        "slice_hrn": dict({
+            "name": "sliceHrn",
+            "help": "The hierarchical Resource Name (HRN) for the PlanetLab slice.",
+            "type": Attribute.STRING,
+            "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable | Attribute.NoDefaultValue,
+            "validation_function": validation.is_string
+        }),
+        "sfa": dict({
+            "name": "sfa",
+            "help": "Activates the use of SFA for node reservation.",
+            "type": Attribute.BOOL,
+            "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable | Attribute.NoDefaultValue,
+            "validation_function": validation.is_bool
+        }),
         "slice": dict({
             "name": "slice",
             "help": "The name of the PlanetLab slice to use",
@@ -1690,7 +1781,7 @@ testbed_attributes = dict({
         "pl_log_level": dict({      
             "name": "plLogLevel",
             "help": "Verbosity of logging of planetlab events.",
-            "value": "ERROR",
+            "value": "INFO",
             "type": Attribute.ENUM, 
             "allowed": ["DEBUG",
                         "INFO",
@@ -1707,16 +1798,26 @@ testbed_attributes = dict({
             "range": (2000,30000),
             "validation_function": validation.is_integer_range(2000,30000)
         }),
-        "dedicated_slice": dict({
-            "name": "dedicatedSlice",
+        "clean_proc": dict({
+            "name": "cleanProc",
             "help": "Set to True if the slice will be dedicated to this experiment. "
-                    "NEPI will perform node and slice cleanup, making sure slices are "
+                    "NEPI will perform node and slice process cleanup, making sure slices are "
                     "in a clean, repeatable state before running the experiment.",
             "type": Attribute.BOOL,
             "value": False,
             "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
             "validation_function": validation.is_bool
         }),
+        "clean_home": dict({
+            "name": "cleanHome",
+            "help": "Set to True all preexistent directories in the home "
+                    "directory of each sliver will be removed before the "
+                    "start of the experiment.",
+            "type": Attribute.BOOL,
+            "value": False,
+            "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
+            "validation_function": validation.is_bool
+        }),
     })
 
 supported_recovery_policies = [
index e6869bb..7394e67 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID
index 1d4d5ca..c4cb016 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID
@@ -89,10 +88,11 @@ class Node(object):
     minLoad = _castproperty(float, '_minLoad')
     maxLoad = _castproperty(float, '_maxLoad')
     
-    def __init__(self, api=None):
+    def __init__(self, api=None, sliceapi=None):
         if not api:
             api = plcapi.PLCAPI()
         self._api = api
+        self._sliceapi = sliceapi or api
         
         # Attributes
         self.hostname = None
@@ -113,7 +113,7 @@ class Node(object):
         self.maxLoad = None
         self.min_num_external_ifaces = None
         self.max_num_external_ifaces = None
-        self.timeframe = 'm'
+        self._timeframe = 'w'
         
         # Applications and routes add requirements to connected nodes
         self.required_packages = set()
@@ -130,7 +130,8 @@ class Node(object):
         self.ident_path = None
         self.server_key = None
         self.home_path = None
-        self.enable_cleanup = False
+        self.enable_proc_cleanup = False
+        self.enable_home_cleanup = False
         
         # Those are filled when an actual node is allocated
         self._node_id = None
@@ -139,6 +140,27 @@ class Node(object):
 
         # Logging
         self._logger = logging.getLogger('nepi.testbeds.planetlab')
+
+    def set_timeframe(self, timeframe):
+        if timeframe == "latest":
+            self._timeframe = ""
+        elif timeframe == "month":
+            self._timeframe = "m"
+        elif timeframe == "year":
+            self._timeframe = "y"
+        else:
+            self._timeframe = "w"
+
+    def get_timeframe(self):
+        if self._timeframe == "":
+            return "latest"
+        if self._timeframe == "m":
+            return "month"
+        if self._timeframe == "y":
+            return "year"
+        return "week"
+
+    timeframe = property(get_timeframe, set_timeframe)
     
     def _nepi_testbed_environment_setup_get(self):
         command = cStringIO.StringIO()
@@ -153,8 +175,10 @@ class Node(object):
                 for envval in envvals:
                     command.write(' ; export %s=%s' % (envkey, envval))
         return command.getvalue()
+
     def _nepi_testbed_environment_setup_set(self, value):
         pass
+
     _nepi_testbed_environment_setup = property(
         _nepi_testbed_environment_setup_get,
         _nepi_testbed_environment_setup_set)
@@ -178,7 +202,7 @@ class Node(object):
         self._logger.info("Finding candidates for %s", self.make_filter_description())
         
         fields = ('node_id',)
-        replacements = {'timeframe':self.timeframe}
+        replacements = {'timeframe':self._timeframe}
         
         # get initial candidates (no tag filters)
         basefilters = self.build_filters({}, self.BASEFILTERS)
@@ -198,8 +222,8 @@ class Node(object):
             extra['peer'] = self.site
             
         candidates = set(map(operator.itemgetter('node_id'), 
-            self._api.GetNodes(filters=basefilters, fields=fields, **extra)))
-        
+            self._sliceapi.GetNodes(filters=basefilters, fields=fields, **extra)))
+
         # filter by tag, one tag at a time
         applicable = self.applicable_filters
         for tagfilter in self.TAGFILTERS.iteritems():
@@ -209,22 +233,22 @@ class Node(object):
             if attr in applicable:
                 tagfilter = rootfilters.copy()
                 tagfilter['tagname'] = tagname % replacements
-                tagfilter[expr % replacements] = getattr(self,attr)
+                tagfilter[expr % replacements] = str(getattr(self,attr))
                 tagfilter['node_id'] = list(candidates)
-                
+              
                 candidates &= set(map(operator.itemgetter('node_id'),
-                    self._api.GetNodeTags(filters=tagfilter, fields=fields)))
-        
+                    self._sliceapi.GetNodeTags(filters=tagfilter, fields=fields)))
+
         # filter by vsys tags - special case since it doesn't follow
         # the usual semantics
         if self.required_vsys:
             newcandidates = collections.defaultdict(set)
             
-            vsys_tags = self._api.GetNodeTags(
+            vsys_tags = self._sliceapi.GetNodeTags(
                 tagname='vsys', 
                 node_id = list(candidates), 
                 fields = ['node_id','value'])
-            
+
             vsys_tags = map(
                 operator.itemgetter(['node_id','value']),
                 vsys_tags)
@@ -246,7 +270,7 @@ class Node(object):
             filters = basefilters.copy()
             filters['node_id'] = list(candidates)
             ifaces = dict(map(operator.itemgetter('node_id','interface_ids'),
-                self._api.GetNodes(filters=basefilters, fields=('node_id','interface_ids')) ))
+                self._sliceapi.GetNodes(filters=basefilters, fields=('node_id','interface_ids')) ))
             
             # filter candidates by interface count
             if self.min_num_external_ifaces is not None and self.max_num_external_ifaces is not None:
@@ -260,14 +284,16 @@ class Node(object):
                     len(ifaces.get(node_id,())) <= self.max_num_external_ifaces )
             
             candidates = set(filter(predicate, candidates))
-        
+       
         # make sure hostnames are resolvable
+        hostnames = dict() 
         if candidates:
             self._logger.info("  Found %s candidates. Checking for reachability...", len(candidates))
-            
+           
             hostnames = dict(map(operator.itemgetter('node_id','hostname'),
-                self._api.GetNodes(list(candidates), ['node_id','hostname'])
+                self._sliceapi.GetNodes(list(candidates), ['node_id','hostname'])
             ))
+
             def resolvable(node_id):
                 try:
                     addr = socket.gethostbyname(hostnames[node_id])
@@ -278,8 +304,14 @@ class Node(object):
                 maxthreads = 16))
 
             self._logger.info("  Found %s reachable candidates.", len(candidates))
-            
-        return candidates
+
+            for h in hostnames.keys():
+                if h not in candidates:
+                    del hostnames[h]
+
+            hostnames = dict((v,k) for k, v in hostnames.iteritems())
+
+        return hostnames
     
     def make_filter_description(self):
         """
@@ -337,20 +369,20 @@ class Node(object):
     def rate_nodes(self, nodes):
         rates = collections.defaultdict(int)
         tags = collections.defaultdict(dict)
-        replacements = {'timeframe':self.timeframe}
+        replacements = {'timeframe':self._timeframe}
         tagnames = [ tagname % replacements 
                      for tagname, weight, default in self.RATE_FACTORS ]
-        
-        taginfo = self._api.GetNodeTags(
+       
+        taginfo = self._sliceapi.GetNodeTags(
             node_id=list(nodes), 
             tagname=tagnames,
             fields=('node_id','tagname','value'))
-        
+
         unpack = operator.itemgetter('node_id','tagname','value')
         for value in taginfo:
             node, tagname, value = unpack(value)
             if value and value.lower() != 'n/a':
-                tags[tagname][int(node)] = float(value)
+                tags[tagname][node] = float(value)
         
         for tagname, weight, default in self.RATE_FACTORS:
             taginfo = tags[tagname % replacements].get
@@ -362,10 +394,7 @@ class Node(object):
     def fetch_node_info(self):
         orig_attrs = {}
         
-        self._api.StartMulticall()
-        info = self._api.GetNodes(self._node_id)
-        tags = self._api.GetNodeTags(node_id=self._node_id, fields=('tagname','value'))
-        info, tags = self._api.FinishMulticall()
+        info, tags = self._sliceapi.GetNodeInfo(self._node_id)
         info = info[0]
         
         tags = dict( (t['tagname'],t['value'])
@@ -375,9 +404,10 @@ class Node(object):
         orig_attrs['max_num_external_ifaces'] = self.max_num_external_ifaces
         self.min_num_external_ifaces = None
         self.max_num_external_ifaces = None
-        self.timeframe = 'm'
+        if not self._timeframe: self._timeframe = 'w'
         
-        replacements = {'timeframe':self.timeframe}
+        replacements = {'timeframe':self._timeframe}
+
         for attr, tag in self.BASEFILTERS.iteritems():
             if tag in info:
                 value = info[tag]
@@ -396,7 +426,7 @@ class Node(object):
         
         if 'peer_id' in info:
             orig_attrs['site'] = self.site
-            self.site = self._api.peer_map[info['peer_id']]
+            self.site = self._sliceapi.peer_map[info['peer_id']]
         
         if 'interface_ids' in info:
             self.min_num_external_ifaces = \
@@ -491,9 +521,11 @@ class Node(object):
                     raise UnresponsiveNodeError, "Unresponsive host %s" % (self.hostname,)
         
         # Ensure the node is clean (no apps running that could interfere with operations)
-        if self.enable_cleanup:
-            self.do_cleanup()
-    
+        if self.enable_proc_cleanup:
+            self.do_proc_cleanup()
+        if self.enable_home_cleanup:
+            self.do_home_cleanup()
+   
     def wait_dependencies(self, pidprobe=1, probe=0.5, pidmax=10, probemax=10):
         # Wait for the p2p installer
         if self._yum_dependencies and not self._installed:
@@ -528,21 +560,23 @@ class Node(object):
             return False
     
     def destroy(self):
-        if self.enable_cleanup:
-            self.do_cleanup()
+        if self.enable_proc_cleanup:
+            self.do_proc_cleanup()
+        if self.enable_home_cleanup:
+            self.do_home_cleanup()
     
     def blacklist(self):
         if self._node_id:
             self._logger.warn("Blacklisting malfunctioning node %s", self.hostname)
             import util
-            util.appendBlacklist(self._node_id)
+            util.appendBlacklist(self.hostname)
     
-    def do_cleanup(self):
+    def do_proc_cleanup(self):
         if self.testbed().recovering:
             # WOW - not now
             return
             
-        self._logger.info("Cleaning up %s", self.hostname)
+        self._logger.info("Cleaning up processes on %s", self.hostname)
         
         cmds = [
             "sudo -S killall python tcpdump || /bin/true ; "
@@ -571,7 +605,36 @@ class Node(object):
                 retry = 3
                 )
             proc.wait()
-    
+     
+    def do_home_cleanup(self):
+        if self.testbed().recovering:
+            # WOW - not now
+            return
+            
+        self._logger.info("Cleaning up home on %s", self.hostname)
+        
+        cmds = [
+            "find . -maxdepth 1 ! -name '.bash*' ! -name '.' -execdir rm -rf {} + "
+        ]
+
+        for cmd in cmds:
+            (out,err),proc = server.popen_ssh_command(
+                # Some apps need two kills
+                cmd % {
+                    'slicename' : self.slicename ,
+                },
+                host = self.hostname,
+                port = None,
+                user = self.slicename,
+                agent = None,
+                ident_key = self.ident_path,
+                server_key = self.server_key,
+                tty = True, # so that ps -N -T works as advertised...
+                timeout = 60,
+                retry = 3
+                )
+            proc.wait()
+   
     def prepare_dependencies(self):
         # Configure p2p yum dependency installer
         if self.required_packages and not self._installed:
index c4aa111..00a06a8 100644 (file)
@@ -16,6 +16,7 @@ def _retry(fn):
     return rv
 
 class PLCAPI(object):
+
     _expected_methods = set(
         ['AddNodeTag', 'AddConfFile', 'DeletePersonTag', 'AddNodeType', 'DeleteBootState', 'SliceListNames', 'DeleteKey', 
          'SliceGetTicket', 'SliceUsersList', 'SliceUpdate', 'GetNodeGroups', 'SliceCreate', 'GetNetworkMethods', 'GetNodeFlavour', 
@@ -261,7 +262,6 @@ class PLCAPI(object):
             filters = kw.pop('filters',{})
             filters.update(kw)
             return _retry(self.mcapi.GetSliceTags)(self.auth, filters, *fieldstuple)
-        
     
     def GetInterfaces(self, interfaceIdOrIp=None, fields=None, **kw):
         if fields is not None:
@@ -289,7 +289,6 @@ class PLCAPI(object):
         
     def UpdateSlice(self, sliceIdOrName, **kw):
         return _retry(self.mcapi.UpdateSlice)(self.auth, sliceIdOrName, kw)
-        
 
     def StartMulticall(self):
         self.threadlocal.mc = xmlrpclib.MultiCall(self.mcapi)
@@ -298,3 +297,50 @@ class PLCAPI(object):
         mc = self.threadlocal.mc
         del self.threadlocal.mc
         return _retry(mc)()
+
+    def GetSliceNodes(self, slicename):
+        return self.GetSlices(slicename, ['node_ids'])[0]['node_ids']
+
+    def AddSliceNodes(self, slicename,  nodes = None):
+        self.UpdateSlice(slicename, nodes = nodes)
+
+    def GetNodeInfo(self, node_id):
+        self.StartMulticall()
+        info = self.GetNodes(node_id)
+        tags = self.GetNodeTags(node_id=node_id, fields=('tagname','value'))
+        info, tags = self.FinishMulticall()
+        return info, tags
+
+    def GetSliceId(self, slicename):
+        slice_id = None
+        slices = self.GetSlices(slicename, fields=('slice_id',))
+        if slices:
+            slice_id = slices[0]['slice_id']
+        # If it wasn't found, don't remember this failure, keep trying
+        return slice_id
+
+    def GetSliceVnetSysTag(self, slicename):
+        slicetags = self.GetSliceTags(
+            name = slicename,
+            tagname = 'vsys_vnet',
+            fields=('value',))
+        if slicetags:
+            return slicetags[0]['value']
+        else:
+            return None
+def plcapi(auth_user, auth_string, plc_host, plc_url):
+    api = None
+    if auth_user:
+        api = PLCAPI(
+            username = auth_user,
+            password = auth_string,
+            hostname = plc_host,
+            urlpattern = plc_url
+        )
+    else:
+        # anonymous access - may not be enough for much
+        api = PLCAPI()
+    return api
+
+
index 915f88c..23add87 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import itertools
index df864af..0812d7c 100644 (file)
@@ -514,6 +514,7 @@ def pl_vif_stop(tun_path, tun_name):
 
 def tun_fwd(tun, remote, reconnect = None, accept_local = None, accept_remote = None, slowlocal = True, bwlimit = None):
     global TERMINATE
+    global SUSPEND
     
     tunqueue = options.vif_txqueuelen or 1000
     tunkqueue = 500
@@ -526,6 +527,7 @@ def tun_fwd(tun, remote, reconnect = None, accept_local = None, accept_remote =
         cipher_key = options.cipher_key,
         udp = options.protocol == 'udp',
         TERMINATE = TERMINATE,
+        SUSPEND = SUSPEND,
         stderr = None,
         reconnect = reconnect,
         tunqueue = tunqueue,
@@ -668,6 +670,20 @@ def _finalize(sig,frame):
     TERMINATE.append(None)
 signal.signal(signal.SIGTERM, _finalize)
 
+# SIGUSR1 suspends forwading, SIGUSR2 resumes forwarding
+SUSPEND = []
+def _suspend(sig,frame):
+    global SUSPEND
+    if not SUSPEND:
+        SUSPEND.append(None)
+signal.signal(signal.SIGUSR1, _suspend)
+
+def _resume(sig,frame):
+    global SUSPEND
+    if SUSPEND:
+        SUSPEND.remove(None)
+signal.signal(signal.SIGUSR2, _resume)
+
 try:
     tcpdump = None
     reconnect = None
index 84972a6..3fd1a7f 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import weakref
@@ -36,6 +35,10 @@ class TunProtoBase(object):
         self._ppid = None
         self._if_name = None
 
+        self._pointopoint = None
+        self._netprefix = None
+        self._address = None
+
         # Logging
         self._logger = logging.getLogger('nepi.testbeds.planetlab')
     
@@ -163,8 +166,8 @@ class TunProtoBase(object):
           )
         % {
             'home' : server.shell_escape(self.home_path),
-            'passfd_url' : "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/python-passfd/archive/2a6472c64c87.tar.gz",
-            'iovec_url' : "http://yans.pl.sophia.inria.fr/code/hgwebdir.cgi/python-iovec/archive/tip.tar.gz",
+            'passfd_url' : "http://nepi.pl.sophia.inria.fr/code/python-passfd/archive/tip.tar.gz",
+            'iovec_url' : "http://nepi.pl.sophia.inria.fr/code/python-iovec/archive/tip.tar.gz",
         } )
         (out,err),proc = server.popen_ssh_command(
             cmd,
@@ -194,18 +197,18 @@ class TunProtoBase(object):
         
         local_port = self.port
         local_cap  = local.capture
-        local_addr = local.address
-        local_mask = local.netprefix
+        self._address = local_addr = local.address
+        self._netprefix = local_mask = local.netprefix
         local_snat = local.snat
         local_txq  = local.txqueuelen
-        local_p2p  = local.pointopoint
+        self._pointopoint = local_p2p  = local.pointopoint
         local_cipher=local.tun_cipher
         local_mcast= local.multicast
         local_bwlim= local.bwlimit
         local_mcastfwd = local.multicast_forwarder
         
         if not local_p2p and hasattr(peer, 'address'):
-            local_p2p = peer.address
+            self._pointopoint = local_p2p = peer.address
 
         if check_proto != peer_proto:
             raise RuntimeError, "Peering protocol mismatch: %s != %s" % (check_proto, peer_proto)
@@ -553,7 +556,46 @@ class TunProtoBase(object):
                         timeout = 60,
                         err_on_timeout = False
                         )
-                    proc.wait()    
+                    proc.wait()
+
+    def if_down(self):
+        # TODO!!! need to set the vif down with vsys/vif_down.in ... which 
+        # doesn't currently work.
+        local = self.local()
+        
+        if local:
+            (out,err),proc = server.eintr_retry(server.popen_ssh_command)(
+                "sudo -S bash -c 'kill -s USR1 %d'" % (self._pid,),
+                host = local.node.hostname,
+                port = None,
+                user = local.node.slicename,
+                agent = None,
+                ident_key = local.node.ident_path,
+                server_key = local.node.server_key,
+                timeout = 60,
+                err_on_timeout = False
+                )
+            proc.wait()
+
+    def if_up(self):
+        # TODO!!! need to set the vif up with vsys/vif_up.in ... which 
+        # doesn't currently work.
+        local = self.local()
+        
+        if local:
+            (out,err),proc = server.eintr_retry(server.popen_ssh_command)(
+                "sudo -S bash -c 'kill -s USR2 %d'" % (self._pid,),
+                host = local.node.hostname,
+                port = None,
+                user = local.node.slicename,
+                agent = None,
+                ident_key = local.node.ident_path,
+                server_key = local.node.server_key,
+                timeout = 60,
+                err_on_timeout = False
+                )
+            proc.wait()    
+
     _TRACEMAP = {
         # tracename : (remotename, localname)
         'packets' : ('capture','capture'),
index 41b32aa..30fcf9d 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
@@ -63,14 +62,7 @@ def appendBlacklist(node_ids):
         bl.close()
 
 def getVnet(api, slicename):
-    slicetags = api.GetSliceTags(
-        name = slicename,
-        tagname = 'vsys_vnet',
-        fields=('value',))
-    if slicetags:
-        return slicetags[0]['value']
-    else:
-        return None
+    return api.GetSliceVsysNetTag(slicename)
 
 def getNodes(api, num, **constraints):
     # Now do the backtracking search for a suitable solution
index b765134..08c5f39 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 AF_INET = 0
index 743cd88..0f2e455 100644 (file)
@@ -1,4 +1,3 @@
-# vim:ts=4:sw=4:et:ai:sts=4
 
 import os, subprocess, os.path
 
index 2a09ba2..04f93fe 100644 (file)
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# vim:ts=4:sw=4:et:ai:sts=4
 
 class GraphicalInfo(object):
     """ This class allows to describe the position and dimensions of a 
index 3198e25..7f5ea3c 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 class GuidGenerator(object):
index 436979f..2bfa0c9 100644 (file)
@@ -1,5 +1,5 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
+
 import struct
 import random
 import socket
index bd0616c..95baad7 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import threading
index 39bb637..a1a8a59 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import Attribute
index 3e28869..6da07db 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import sys
diff --git a/src/nepi/util/parser/sfa.py b/src/nepi/util/parser/sfa.py
new file mode 100644 (file)
index 0000000..bb83508
--- /dev/null
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+
+from xml.dom import minidom
+
+import sys
+
+def xmlencode(s):
+    if isinstance(s, str):
+        rv = s.decode("latin1")
+    elif not isinstance(s, unicode):
+        rv = unicode(s)
+    else:
+        rv = s
+    return rv.replace(u'\x00',u'&#0000;')
+
+def xmldecode(s):
+    return s.replace(u'&#0000',u'\x00').encode("utf8")
+
+def get_child_text(tag, name):
+    tags = tag.getElementsByTagName(name)
+    if not tags:
+        return ""
+    return get_text(tags[0])
+
+def get_name(tag):
+    return xmldecode(tag.tagName)
+
+def get_text(tag):
+    text = ''.join(t.nodeValue for t in tag.childNodes if t.nodeType == t.TEXT_NODE)
+    return xmldecode(text)
+
+def set_text(doc, tag, text):
+    ttag = doc.createTextNode(text)
+    tag.appendChild(ttag)
+
+def get_attribute(p_tag, name):
+    return xmldecode(p_tag.getAttribute(name))
+
+def has_sliver(node_tag):
+    sliver_tag = node_tag.getElementsByTagName("sliver")
+    return len(sliver_tag) > 0 
+
+class SFAResourcesParser(object):
+    def resources_from_xml(self, xml):
+        data = dict()
+        doc = minidom.parseString(xml)
+        rspec_tag = doc.getElementsByTagName("RSpec")[0]
+        network_tags = rspec_tag.getElementsByTagName("network")
+        for network_tag in network_tags:
+            if network_tag.nodeType == doc.ELEMENT_NODE:
+                node_data = self.nodes_from_xml(doc, network_tag)
+                data.update(node_data)
+        return data
+
+    def slice_info_from_xml(self, xml):
+        nodes_data = dict()
+        doc = minidom.parseString(xml)
+        rspec_tag = doc.getElementsByTagName("RSpec")[0]
+        network_tags = rspec_tag.getElementsByTagName("network")
+        for network_tag in network_tags:
+            if network_tag.nodeType == doc.ELEMENT_NODE:
+                node_data = self.nodes_from_xml(doc, network_tag, in_sliver = True)
+                nodes_data.update(node_data)
+        nodes_data = set(nodes_data.keys())
+        tags_data = self.slice_tags_from_xml(doc, rspec_tag)
+        return tags_data, nodes_data
+
+    def nodes_from_xml(self, doc, network_tag, in_sliver = False):
+        nodes_data = dict()
+        network_name = get_attribute(network_tag, 'name')
+        node_tags = network_tag.getElementsByTagName('node')
+        for node_tag in node_tags:
+            if node_tag.nodeType == doc.ELEMENT_NODE:
+                if in_sliver and not has_sliver(node_tag):
+                    continue
+                node_data = dict()
+                node_data['network_name'] = network_name
+                node_name = get_attribute(node_tag, 'component_name')
+                nodes_data[node_name] = node_data
+                for name in ['component_id', 'component_manager_id',
+                        'boot_state', 'component_name', 'site_id']:
+                    node_data[name] = get_attribute(node_tag, name)
+                location_tag = node_tag.getElementsByTagName('location')
+                if location_tag:
+                    for name in ['longitud' , 'latitude']:
+                        node_data[name] = get_attribute(location_tag[0], name)
+                for name in ['hostname', 'pldistro', 'arch', 'fcdistro',
+                        'stype', 'reliabilityw', 'loadm', 'cpuy', 'cpum', 
+                        'slicesm', 'slicesw', 'cpuw', 'loady', 'memy',
+                        'memw', 'reliabilityy', 'reliability', 'reliabilitym', 
+                        'responsey', 'bww', 'memem', 'bwm', 'slicey', 'responsem', 
+                        'response', 'loadw', 'country', 'load', 'mem', 'slices',
+                        'region', 'asnumber', 'bw', 'hrn', 'city', 'responsew', 
+                        'bwy', 'cpu']:
+                    node_data[name] = get_child_text(node_tag, name)
+                iface_tags =  node_tag.getElementsByTagName('interface')
+                ifaces_data = dict()
+                iface_ids = list()
+                for iface_tag in iface_tags: 
+                    if iface_tag.nodeType == doc.ELEMENT_NODE:
+                        for name in ['component_id', 'ipv4']:
+                            value = get_attribute(iface_tag, name)
+                            ifaces_data[name] = value
+                            if name == 'component_id':
+                                iface_ids.append(value)
+                node_data['interfaces'] = ifaces_data
+                node_data['interface_ids'] = iface_ids
+        return nodes_data
+
+    def slice_tags_from_xml(self, doc, rspec_tag):
+        tags_data = dict()
+        sliver_tag = rspec_tag.getElementsByTagName('sliver_defaults')
+        if len(sliver_tag) == 0:
+            return tags_data
+        for child_tag in sliver_tag[0].childNodes:
+            if child_tag.nodeType == doc.ELEMENT_NODE:
+                name = get_name(child_tag)
+                value = get_text(child_tag)
+                tags_data[name] = value
+        return tags_data
+
+    def create_slice_xml(self, node_data, slice_tags):
+        doc = minidom.Document()
+        rspec_tag = doc.createElement("RSpec")
+        doc.appendChild(rspec_tag)
+        rspec_tag.setAttribute("type", "SFA")
+        slice_defaults_tag = self.slice_defaults_xml(doc, slice_tags)
+        
+        networks = dict()
+        for k, data in node_data.iteritems():
+            network_name = data["network_name"]
+            if network_name not in networks:
+                networks[network_name] = dict()
+            networks[network_name][k] = data
+
+        for n, netdata in networks.iteritems():
+            network_tag = doc.createElement("testbeds")
+            network_tag.setAttribute("name", n)
+            rspec_tag.appendChild(network_tag)
+            for k, data in netdata.iteritems():
+                node_tag = doc.createElement("node")
+                node_tag.setAttribute("component_manager_id", data["component_manager_id"])
+                node_tag.setAttribute("component_id", data["component_id"])
+                node_tag.setAttribute("component_name", data["component_name"])
+                node_tag.setAttribute("boot_state", data["boot_state"])
+                node_tag.setAttribute("site_id", data["site_id"])
+                hostname_tag = doc.createElement("hostname")
+                set_text(doc, hostname_tag, data["hostname"])
+                node_tag.appendChild(hostname_tag)
+                sliver_tag = doc.createElement("sliver")
+                node_tag.appendChild(sliver_tag)
+                network_tag.appendChild(node_tag)
+            network_tag.appendChild(slice_defaults_tag)
+        return doc.toxml()
+
+    def slice_defaults_xml(self, doc, slice_tags):
+        slice_defaults_tag = doc.createElement("sliver_defaults")
+        for name, value in slice_tags.iteritems():
+            tag = doc.createElement(name)
+            set_text(doc, tag, value)
+            slice_defaults_tag.appendChild(tag)
+        return slice_defaults_tag
+
+"""
+if __name__ == "__main__":
+    path = sys.argv[1]
+    fd = open(path, 'r')
+    xml = fd.read()
+    fd.close()
+    p = SFAResourcesParser()
+    tags, nodes = p.slice_info_from_xml(xml)
+    print tags, nodes
+"""
index 282fd92..9545a5c 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import base64
index 6f69577..c53cc4e 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.util.constants import DeploymentConfiguration as DC
@@ -42,6 +41,8 @@ else:
 
 SHELL_SAFE = re.compile('^[-a-zA-Z0-9_=+:.,/]*$')
 
+hostbyname_cache = dict()
+
 def openssh_has_persist():
     global OPENSSH_HAS_PERSIST
     if OPENSSH_HAS_PERSIST is None:
@@ -570,9 +571,14 @@ def _make_server_key_args(server_key, host, port, args):
         host = '%s:%s' % (host,port)
     # Create a temporary server key file
     tmp_known_hosts = tempfile.NamedTemporaryFile()
-    
+   
+    hostbyname = hostbyname_cache.get(host)
+    if not hostbyname:
+        hostbyname = socket.gethostbyname(host)
+        hostbyname_cache[host] = hostbyname
+
     # Add the intended host key
-    tmp_known_hosts.write('%s,%s %s\n' % (host, socket.gethostbyname(host), server_key))
+    tmp_known_hosts.write('%s,%s %s\n' % (host, hostbyname, server_key))
     
     # If we're not in strict mode, add user-configured keys
     if os.environ.get('NEPI_STRICT_AUTH_MODE',"").lower() not in ('1','true','on'):
diff --git a/src/nepi/util/sfiapi.py b/src/nepi/util/sfiapi.py
new file mode 100644 (file)
index 0000000..d82b28c
--- /dev/null
@@ -0,0 +1,162 @@
+# -*- coding: utf-8 -*-
+
+
+import logging
+
+from nepi.util.parser import sfa
+
+###
+# TODO: This API is a mega hack to adapt the sfa interface to the plc interface.
+#       The right way to implement this would be to make node.py invoke generic 
+#       methods and to adapt the sfa and plc APIs to provide the reuired 
+#       data.
+
+class SFIAPI(object):
+    def __init__(self, slice_id):
+        self._slice_tags = dict()
+        self._slice_nodes = set()
+        self._all_nodes = dict()
+        self._slice_id = slice_id
+
+        self._logger = logging.getLogger('nepi.utils.sfiapi')
+        
+        self.FetchSliceInfo()
+
+    def FetchSliceInfo(self):
+        p = sfa.SFAResourcesParser()
+        import commands
+        xml = commands.getoutput("sfi.py resources")
+        try:
+            self._all_nodes = p.resources_from_xml(xml)
+            xml = commands.getoutput("sfi.py resources %s" % self._slice_id)
+            self._slice_tags, self._slice_nodes = p.slice_info_from_xml(xml)
+        except:
+            self._logger.error("Error in SFA responds: %s", xml)
+            raise
+    
+    def GetSliceNodes(self, slicename):
+        return list(self._slice_nodes)
+
+    def GetNodeInfo(self, node_id):
+        # TODO: thread-unsafe!! sanitize!
+        info = self.GetNodes(node_id)
+        tags = self.GetNodeTags(node_id=node_id, fields=('tagname','value'))
+        return info, tags
+
+    def GetSliceId(self, slicename):
+        return self._slice_id
+
+    def GetSliceVnetSysTag(self, slicename):
+        return self._slice_tags.get('vsys_net')
+
+    def GetNodeTags(self, node_id=None, fields=None, **kw):
+        nodes = self._all_nodes
+        if node_id is not None:
+            node_ids = node_id
+            if not isinstance(node_id, list):
+                node_ids = [node_ids]
+            nodes = self._FilterByNodeId(nodes, node_ids)
+        else:
+            filters = kw.pop('filters',{})
+            if '|slice_ids' in filters:
+                nodes = self._FilterByNodeId(nodes, self._slice_nodes)
+                del filters['|slice_ids']
+            nodes = self._FilterByFilters(nodes, filters)
+        tagnames = kw.pop('tagname',[])
+        return self._GetTagInfo(nodes, tagnames, fields)
+
+    def GetNodes(self, nodeIdOrName=None, fields=[], **kw):
+        #TODO: filter - peer
+        nodes = self._all_nodes
+        if nodeIdOrName is not None:
+            node_ids = nodeIdOrName
+            if not isinstance(nodeIdOrName, list):
+                node_ids = [node_ids]
+            nodes = self._FilterByNodeId(nodes, node_ids)
+        else:
+            filters = kw.pop('filters',{})
+            if '|slice_ids' in filters:
+                nodes = self._FilterByNodeId(nodes, self._slice_nodes)
+                del filters['|slice_ids']
+            # TODO: Remove this!! need to allow filter '>last_contact' !!!
+            for f in ['>last_contact', 'node_type', 'run_level']:
+                if f in filters:
+                    del filters[f]
+            nodes = self._FilterByFilters(nodes, filters)
+        return self._GetNodeFieldsInfo(nodes, fields)
+    
+    def _FilterByNodeId(self, nodes, node_ids):
+        return dict((k, nodes[k]) for k in node_ids if k in nodes)
+
+    def _FilterByFilters(self, nodes, filters):
+        def has_all_tags(node_id):
+            data = nodes[node_id]
+            for name, value in filters.iteritems():
+                if name == 'value' or name == 'tagname':
+                    tagname = filters['tagname']
+                    tagval = filters['value']
+                    if data[tagname] != tagval:
+                        return False
+                elif name == 'node_id':
+                    node_ids = list(value)
+                    if node_id not in node_ids:
+                        return False
+                else:
+                    #if  (name == '>last_contact' and data['lastcontact'] > value) or \
+                    if (not name in data or data[name] != value):
+                        return False
+            return True
+        return dict((k, value) for k, value in nodes.iteritems() if has_all_tags(k))
+
+    def _GetNodeFieldsInfo(self, nodes, fields):
+        result = list()
+        for k, data in nodes.iteritems():
+            if not fields:
+                result.append(data)
+                continue
+            r_data = dict()
+            for f in fields:
+                if f == "node_id":
+                    value = k
+                else:
+                    value = data[f]
+                r_data[f] = value
+            result.append(r_data)
+        return result
+
+    def _GetTagInfo(self, nodes, tagnames, fields):
+        result = list()
+        for k, data in nodes.iteritems():
+            for name, value in data.iteritems():
+                r_data = dict()
+                if tagnames and name not in tagnames:
+                    continue
+                for f in fields:
+                    if f == "node_id":
+                        val = k
+                    if f == "tagname":
+                        val = name
+                    if f == "value":
+                        val = value
+                    r_data[f] = val
+                result.append(r_data)
+        return result
+
+    def AddSliceNodes(self, slicename, nodes=None):
+        import os, commands, tempfile
+        nodes = set(nodes)
+        nodes.update(self._slice_nodes)
+        nodes_data = dict((k, self._all_nodes[k]) for k in nodes)
+        p = sfa.SFAResourcesParser()
+        xml = p.create_slice_xml(nodes_data, self._slice_tags)
+        fh, fname = tempfile.mkstemp()
+        os.write(fh, xml)
+        os.close(fh)
+        out = commands.getoutput("sfi.py create %s %s" % (self._slice_id, fname))
+        os.remove(fname)
+        #print out
+
+def sfiapi(slice_id):
+    api = SFIAPI(slice_id)
+    return api
+
index 5e72440..4cd4c38 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 MOBILE = "mobile"
index 735d08c..78176d6 100644 (file)
@@ -26,6 +26,7 @@ tagtype = {
     '8864' : 'PPPoE',
     '86dd' : 'ipv6',
 }
+
 def etherProto(packet, len=len):
     if len(packet) > 14:
         if packet[12] == "\x81" and packet[13] == "\x00":
@@ -36,6 +37,7 @@ def etherProto(packet, len=len):
             return packet[12:14]
     # default: ip
     return "\x08\x00"
+
 def formatPacket(packet, ether_mode):
     if ether_mode:
         stripped_packet = etherStrip(packet)
@@ -194,9 +196,13 @@ def nonblock(fd):
         # Just ignore
         return False
 
-def tun_fwd(tun, remote, with_pi, ether_mode, cipher_key, udp, TERMINATE, stderr=sys.stderr, reconnect=None, rwrite=None, rread=None, tunqueue=1000, tunkqueue=1000,
-        cipher='AES', accept_local=None, accept_remote=None, slowlocal=True, queueclass=None, bwlimit=None,
-        len=len, max=max, min=min, buffer=buffer, OSError=OSError, select=select.select, selecterror=select.error, os=os, socket=socket,
+def tun_fwd(tun, remote, with_pi, ether_mode, cipher_key, udp, TERMINATE, SUSPEND,
+        stderr = sys.stderr, reconnect = None, rwrite = None, rread = None,
+        tunqueue = 1000, tunkqueue = 1000, cipher = 'AES', accept_local = None, 
+        accept_remote = None, slowlocal = True, queueclass = None, 
+        bwlimit = None, len = len, max = max, min = min, buffer = buffer,
+        OSError = OSError, select = select.select, selecterror = select.error, 
+        os = os, socket = socket,
         retrycodes=(os.errno.EWOULDBLOCK, os.errno.EAGAIN, os.errno.EINTR) ):
     crypto_mode = False
     crypter = None
@@ -343,6 +349,11 @@ def tun_fwd(tun, remote, with_pi, ether_mode, cipher_key, udp, TERMINATE, stderr
     
     
     while not TERMINATE:
+        # The SUSPEND flag has been set. This means we need to wait on
+        # the SUSPEND condition until it is released.
+        while SUSPEND and not TERMINATE:
+            time.sleep(0.5)
+
         wset = []
         if packetReady(bkbuf):
             wset.append(tun)
@@ -368,7 +379,12 @@ def tun_fwd(tun, remote, with_pi, ether_mode, cipher_key, udp, TERMINATE, stderr
                 continue
             else:
                 traceback.print_exc(file=sys.stderr)
-                raise
+                # If the SUSPEND flag has been set, then the TUN will be in a bad
+                # state and the select error should be ignores.
+                if SUSPEND:
+                    continue
+                else:
+                    raise
 
         # check for errors
         if errs:
index ec74181..4123a64 100644 (file)
@@ -74,6 +74,7 @@ class TunChannel(object):
         # some state
         self.prepared = False
         self._terminate = [] # terminate signaller
+        self._suspend = [] # suspend signaller
         self._exc = [] # exception store, to relay exceptions from the forwarder thread
         self._connected = threading.Event()
         self._forwarder_thread = None
@@ -124,6 +125,14 @@ class TunChannel(object):
                 self._terminate.append(None)
             self._forwarder_thread.join()
 
+    def suspend(self):
+        if not self._suspend:
+            self._suspend.append(None)
+
+    def resume(self):
+        if self._suspend:
+            self._suspend.remove(None)
+
     def _launch(self):
         # Launch forwarder thread with a weak reference
         # to self, so that we don't create any strong cycles
@@ -178,6 +187,7 @@ class TunChannel(object):
             raise RuntimeError, "Misconfigured TUN: %s" % (self,)
         
         TERMINATE = self._terminate
+        SUSPEND = self._suspend
         cipher_key = self.tun_key
         tun = self.tun_socket
         udp = local_proto == 'udp'
@@ -209,6 +219,7 @@ class TunChannel(object):
             cipher_key = cipher_key, 
             udp = udp, 
             TERMINATE = TERMINATE,
+            SUSPEND = SUSPEND,
             stderr = stderr,
             cipher = local_cipher
         )
@@ -247,7 +258,7 @@ def preconfigure_tunchannel(testbed_instance, guid):
     public_addr = os.popen(
         "/sbin/ifconfig "
         "| grep $(ip route | grep default | awk '{print $3}' "
-                "| awk -F. '{print $1\"[.]\"$2}') "
+                "| awk -F. '{print $1\"[.]\"$2}' | head -1) "
         "| head -1 | awk '{print $2}' "
         "| awk -F : '{print $2}'").read().rstrip()
     element.tun_addr = public_addr
index 69ee73b..f94c248 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import ipaddr
index b8f04f1..800643d 100755 (executable)
@@ -9,6 +9,7 @@ import unittest
 
 class DesignTestCase(unittest.TestCase):
     def setUp(self):
+        # hack to add the mock testbed on the correct module path
         sys.modules["nepi.testbeds.mock.metadata"] = mock.metadata
 
     def test_design(self):
index de8de1b..5e42a33 100755 (executable)
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+import getpass
 from nepi.util import tags
 from nepi.util.constants import ApplicationStatus as AS
-import getpass
 import mock
 import mock.metadata 
 import sys
index d627a4e..df4f211 100755 (executable)
@@ -1,10 +1,10 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+import getpass
 from nepi.core.design import ExperimentDescription, FactoriesProvider
 from nepi.util import proxy
 from nepi.util.constants import DeploymentConfiguration as DC
-import getpass
 import mock
 import mock.metadata
 import mock2
index 1ea99bd..f3e1ac0 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 7640c66..54fe6da 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 TESTBED_ID = "mock"
index db7b01c..fc6f64a 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 370af4d..35b7e44 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 1ea99bd..f3e1ac0 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index e1f9775..dae7bed 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 TESTBED_ID = "mock2"
index db7b01c..fc6f64a 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 7c294be..a258a4a 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from constants import TESTBED_ID, TESTBED_VERSION
index 3373b8e..fbecdfc 100644 (file)
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 import nepi.util.environ
 import ctypes
 import imp
index 4f3758f..b545e6f 100755 (executable)
@@ -10,9 +10,10 @@ import uuid
 
 class NetnsDesignTestCase(unittest.TestCase):
     def test_design_if(self):
-        exp_desc = ExperimentDescription()
         testbed_id = "netns"
+        exp_desc = ExperimentDescription()
         provider = FactoriesProvider(testbed_id)
+        
         tstbd_desc = exp_desc.add_testbed_description(provider)
         tstbd_desc.set_attribute_value("enableDebug", True)
         node1 = tstbd_desc.create("Node")
@@ -34,6 +35,7 @@ class NetnsDesignTestCase(unittest.TestCase):
         app = tstbd_desc.create("Application")
         app.set_attribute_value("command", "ping -qc10 10.0.0.2")
         app.connector("node").connect(node1.connector("apps"))
+        
         xml = exp_desc.to_xml()
         exp_desc2 = ExperimentDescription()
         exp_desc2.from_xml(xml)
index 7eaf332..5e361f1 100755 (executable)
@@ -48,6 +48,7 @@ class NetnsExecuteTestCase(unittest.TestCase):
         instance.do_configure()
         instance.do_prestart()
         instance.start()
+
         while instance.status(7) != AS.STATUS_FINISHED:
             time.sleep(0.5)
         ping_result = instance.trace(7, "stdout")
@@ -90,6 +91,7 @@ class NetnsExecuteTestCase(unittest.TestCase):
         instance.do_configure()
         instance.do_prestart()
         instance.start()
+
         while instance.status(6) != AS.STATUS_FINISHED:
             time.sleep(0.5)
         ping_result = instance.trace(6, "stdout")
@@ -107,6 +109,7 @@ class NetnsExecuteTestCase(unittest.TestCase):
         user = getpass.getuser()
         instance = netns.TestbedController()
         instance.defer_configure("homeDirectory", self.root_dir)
+        #instance.defer_configure("enableDebug", True)
         instance.defer_create(2, "Node")
         instance.defer_create(3, "Node")
         instance.defer_create(4, "Node")
@@ -151,6 +154,7 @@ class NetnsExecuteTestCase(unittest.TestCase):
         instance.do_configure()
         instance.do_prestart()
         instance.start()
+
         while instance.status(11) != AS.STATUS_FINISHED:
             time.sleep(0.5)
         ping_result = instance.trace(11, "stdout")
@@ -194,8 +198,10 @@ class NetnsExecuteTestCase(unittest.TestCase):
         instance.do_configure()
         instance.do_prestart()
         instance.start()
+
         while instance.status(6) != AS.STATUS_FINISHED:
             time.sleep(0.5)
+        
         pcap_result = instance.trace(2, "pcap")
         self.assertEquals(len(pcap_result), 1024)
         instance.stop()
index ae56375..6da9567 100755 (executable)
@@ -19,10 +19,11 @@ class NetnsIntegrationTestCase(unittest.TestCase):
 
     def _test_switched(self, controller_access_config = None,
             testbed_access_config = None):
-        exp_desc = ExperimentDescription()
         testbed_id = "netns"
+        exp_desc = ExperimentDescription()
         user = getpass.getuser()
         netns_provider = FactoriesProvider(testbed_id)
+        
         netns_desc = exp_desc.add_testbed_description(netns_provider)
         netns_desc.set_attribute_value("homeDirectory", self.root_dir)
         #netns_desc.set_attribute_value("enableDebug", True)
index de507b7..8d034cd 100755 (executable)
@@ -10,8 +10,8 @@ import uuid
 
 class Ns3DesignTestCase(unittest.TestCase):
     def test_design_if(self):
-        exp_desc = ExperimentDescription()
         testbed_id = "ns3"
+        exp_desc = ExperimentDescription()
         provider = FactoriesProvider(testbed_id)
         tstbd_desc = exp_desc.add_testbed_description(provider)
 
index 5eec42b..9a6e236 100755 (executable)
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 from nepi.util.constants import ApplicationStatus as AS
 from nepi.testbeds import ns3
@@ -70,11 +69,12 @@ class Ns3ExecuteTestCase(unittest.TestCase):
         instance.do_configure()
         instance.do_prestart()
         instance.start()
+
         while instance.status(17) != AS.STATUS_FINISHED:
             time.sleep(0.1)
         ping_result = instance.trace(14, "P2PAsciiTrace")
         ping_rtt = instance.trace(17, "Rtt")
-        comp_result = "- 9.021 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 ttl 64 id 9 protocol 1 offset 0 flags [none] length: 84 10.0.0.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=9)"
+        comp_result = "- 9.021 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 DSCP Default ECN Not-ECT ttl 64 id 9 protocol 1 offset (bytes) 0 flags [none] length: 84 10.0.0.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=9)"
         comp_rtt_result = """+41992186.0ns\t+41992186.0ns
 +1041992186.0ns\t+41992186.0ns
 +2041992186.0ns\t+41992186.0ns
@@ -84,7 +84,9 @@ class Ns3ExecuteTestCase(unittest.TestCase):
 +6041992186.0ns\t+41992186.0ns
 +7041992186.0ns\t+41992186.0ns
 +8041992186.0ns\t+41992186.0ns
-+9041992186.0ns\t+41992186.0ns"""
++9041992186.0ns\t+41992186.0ns
+"""
+
         self.assertNotEqual(ping_result.find(comp_result), -1)
         self.assertEqual(ping_rtt.strip(), comp_rtt_result.strip())
         instance.stop()
index 854e02c..f193af8 100755 (executable)
@@ -105,10 +105,12 @@ class Ns3ExecuteTestCase(unittest.TestCase):
         instance.do_configure()
         instance.do_prestart()
         instance.start()
+
         while instance.status(27) != AS.STATUS_FINISHED:
             time.sleep(0.1)
         ping_result = instance.trace(24, "P2PAsciiTrace")
-        comp_result = "- 9.04199 /NodeList/2/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 ttl 64 id 9 protocol 1 offset 0 flags [none] length: 84 10.0.1.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=9)"
+        comp_result = "- 9.04199 /NodeList/2/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 DSCP Default ECN Not-ECT ttl 64 id 9 protocol 1 offset (bytes) 0 flags [none] length: 84 10.0.1.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=9)"
+
         self.assertNotEqual(ping_result.find(comp_result), -1)
         instance.stop()
         instance.shutdown()
index 248b9ae..e2c24c7 100755 (executable)
@@ -20,8 +20,8 @@ class Ns3IntegrationTestCase(unittest.TestCase):
 
     def _test_fd_net_device(self, daemonize_testbed,
             controller_access_configuration):
-        exp_desc = ExperimentDescription()
         testbed_id = "ns3"
+        exp_desc = ExperimentDescription()
         ns3_provider = FactoriesProvider(testbed_id)
         ns3_desc1 = exp_desc.add_testbed_description(ns3_provider)
         root_dir1 = os.path.join(self.root_dir, "1")
@@ -178,7 +178,9 @@ r [-+0-9.e]+ /NodeList/0/DeviceList/0/\$ns3::FdNetDevice/Rx Payload \(size=98\)
             while not controller.is_finished(app.guid):
                 time.sleep(0.5)
             ping_result = controller.trace(iface2.guid, "P2PAsciiTrace")
-            comp_result = "- 19.021 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 ttl 64 id 19 protocol 1 offset 0 flags [none] length: 84 10.0.0.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=19)"
+
+            comp_result = "- 19.021 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader (Point-to-Point Protocol: IP (0x0021)) ns3::Ipv4Header (tos 0x0 DSCP Default ECN Not-ECT ttl 64 id 19 protocol 1 offset (bytes) 0 flags [none] length: 84 10.0.0.2 > 10.0.0.1) ns3::Icmpv4Header (type=0, code=0) ns3::Icmpv4Echo (identifier=0, sequence=19)"
+            
             if ping_result.find(comp_result) == -1:
                 self.fail("Unexpected trace: %s" % (ping_result,))
         finally:
index 7caee34..24777ca 100755 (executable)
@@ -6,8 +6,8 @@ import unittest
 
 class PlanetlabDesignTestCase(unittest.TestCase):
     def make_test_design(self):
-        exp_desc = ExperimentDescription()
         testbed_id = "planetlab"
+        exp_desc = ExperimentDescription()
         provider = FactoriesProvider(testbed_id)
         tstbd_desc = exp_desc.add_testbed_description(provider)
         tstbd_desc.set_attribute_value("slice", "inria_nepi")
index 90aa062..557425f 100755 (executable)
@@ -5,13 +5,13 @@ import getpass
 from nepi.util.constants import ApplicationStatus as AS
 from nepi.testbeds import planetlab
 import os
+import re
 import shutil
+import sys
 import tempfile
+import test_util
 import time
 import unittest
-import re
-import test_util
-import sys
 
 class PlanetLabExecuteTestCase(unittest.TestCase):
     testbed_id = "planetlab"
@@ -74,7 +74,7 @@ class PlanetLabExecuteTestCase(unittest.TestCase):
         instance.defer_configure("plcHost", plchost)
         instance.defer_configure("tapPortBase", self.port_base)
         instance.defer_configure("p2pDeployment", False) # it's interactive, we don't want it in tests
-        instance.defer_configure("dedicatedSlice", True)
+        instance.defer_configure("cleanProc", True)
         
         # Hack, but we need vsys_vnet
         instance.do_setup()
index d59e959..71d9e2b 100755 (executable)
@@ -2,23 +2,24 @@
 # -*- coding: utf-8 -*-
 
 import getpass
+import logging
 from nepi.core.design import ExperimentDescription, FactoriesProvider
 from nepi.core.execute import ExperimentController
 from nepi.util import proxy
 from nepi.util.constants import DeploymentConfiguration as DC
 import os
+import re
 import shutil
+import sys
 import tempfile
 import test_util
 import time
 import unittest
-import re
-import sys
-import logging
 
 class PlanetLabIntegrationTestCase(unittest.TestCase):
     testbed_id = "planetlab"
     slicename = "inria_nepi"
+    slicehrn = "nepi.inria.nepi"
     plchost = "nepiplc.pl.sophia.inria.fr"
     
     host1 = "nepi1.pl.sophia.inria.fr"
@@ -40,7 +41,7 @@ class PlanetLabIntegrationTestCase(unittest.TestCase):
             time.sleep(0.1)
             shutil.rmtree(self.root_dir)
 
-    def make_experiment_desc(self):
+    def make_experiment_desc(self, use_sfa = False):
         testbed_id = self.testbed_id
         slicename = self.slicename
         plchost = self.plchost
@@ -60,13 +61,17 @@ class PlanetLabIntegrationTestCase(unittest.TestCase):
         pl_desc.set_attribute_value("plcHost", plchost)
         pl_desc.set_attribute_value("tapPortBase", self.port_base)
         pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc.set_attribute_value("dedicatedSlice", True)
-        #pl_desc.set_attribute_value("plLogLevel", "DEBUG")
+        pl_desc.set_attribute_value("cleanProc", True)
+        pl_desc.set_attribute_value("plLogLevel", "DEBUG")
+        if use_sfa:
+            pl_desc.set_attribute_value("sfa", True)
+            pl_desc.set_attribute_value("sliceHrn", self.slicehrn)
         
         return pl_desc, exp_desc
     
-    def _test_simple(self, daemonize_testbed, controller_access_configuration, environ = None):
-        pl, exp = self.make_experiment_desc()
+    def _test_simple(self, daemonize_testbed, controller_access_configuration,
+            environ = None, use_sfa = False):
+        pl, exp = self.make_experiment_desc(use_sfa)
         
         node1 = pl.create("Node")
         node2 = pl.create("Node")
@@ -128,11 +133,8 @@ class PlanetLabIntegrationTestCase(unittest.TestCase):
                 import traceback
                 traceback.print_exc()
 
-    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
-    @test_util.skipUnless(os.environ.get('NEPI_FULL_TESTS','').lower() in ('1','yes','true','on'),
-        "Test is interactive, requires NEPI_FULL_TESTS=yes")
-    def test_spanning_deployment(self):
-        pl, exp = self.make_experiment_desc()
+    def _test_spanning_deployment(self, use_sfa = False):
+        pl, exp = self.make_experiment_desc(use_sfa)
 
         pl.set_attribute_value("p2pDeployment", True) # we do want it here - even if interactive
         
@@ -207,49 +209,9 @@ FIONREAD = 0x[0-9a-fA-F]{8}.*
                 import traceback
                 traceback.print_exc()
 
-    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
-    def test_simple(self):
-        self._test_simple(
-            daemonize_testbed = False,
-            controller_access_configuration = None)
-
-    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
-    def test_simple_daemonized(self):
-        access_config = proxy.AccessConfiguration({
-            DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
-            DC.ROOT_DIRECTORY : self.root_dir,
-            DC.LOG_LEVEL : DC.DEBUG_LEVEL,
-        })
-
-        self._test_simple(
-            daemonize_testbed = False,
-            controller_access_configuration = access_config)
-
-    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
-    def test_z_simple_ssh(self): # _z_ cause we want it last - it messes up the process :(
-        # Recreate environment
-        environ = ' ; '.join( map("export %s=%r".__mod__, os.environ.iteritems()) )
-
-        env = test_util.test_environment()
-
-        access_config = proxy.AccessConfiguration({
-            DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
-            DC.ROOT_DIRECTORY : self.root_dir,
-            DC.LOG_LEVEL : DC.DEBUG_LEVEL,
-            DC.DEPLOYMENT_COMMUNICATION : DC.ACCESS_SSH,
-            DC.DEPLOYMENT_PORT : env.port,
-            DC.USE_AGENT : True,
-            DC.DEPLOYMENT_ENVIRONMENT_SETUP : environ,
-        })
-
-        self._test_simple(
-            daemonize_testbed = False,
-            controller_access_configuration = access_config,
-            environ = environ)
-
-
-    def _test_recover(self, daemonize_testbed, controller_access_configuration, environ = None):
-        pl, exp = self.make_experiment_desc()
+    def _test_recover(self, daemonize_testbed, controller_access_configuration, 
+            environ = None, use_sfa = False):
+        pl, exp = self.make_experiment_desc(use_sfa)
         
         pl.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
         
@@ -345,12 +307,91 @@ FIONREAD = 0x[0-9a-fA-F]{8}.*
                     import traceback
                     traceback.print_exc()
 
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_simple(self):
+        self._test_simple(
+            daemonize_testbed = False,
+            controller_access_configuration = None)
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_simple_sfa(self):
+        self._test_simple(
+            daemonize_testbed = False,
+            controller_access_configuration = None,
+            use_sfa = True)
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    @test_util.skipUnless(os.environ.get('NEPI_FULL_TESTS','').lower() in ('1','yes','true','on'),
+        "Test is interactive, requires NEPI_FULL_TESTS=yes")
+    def test_spanning_deployment(self):
+        self._test_spanning_deployment()
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    @test_util.skipUnless(os.environ.get('NEPI_FULL_TESTS','').lower() in ('1','yes','true','on'),
+        "Test is interactive, requires NEPI_FULL_TESTS=yes")
+    def test_spanning_deployment_sfa(self):
+        self._test_spanning_deployment(use_sfa = True)
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_simple_daemonized(self):
+        access_config = proxy.AccessConfiguration({
+            DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
+            DC.ROOT_DIRECTORY : self.root_dir,
+            DC.LOG_LEVEL : DC.DEBUG_LEVEL,
+        })
+
+        self._test_simple(
+            daemonize_testbed = False,
+            controller_access_configuration = access_config)
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_simple_daemonized_sfa(self):
+        access_config = proxy.AccessConfiguration({
+            DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
+            DC.ROOT_DIRECTORY : self.root_dir,
+            DC.LOG_LEVEL : DC.DEBUG_LEVEL,
+        })
+
+        self._test_simple(
+            daemonize_testbed = False,
+            controller_access_configuration = access_config,
+            use_sfa = True)
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_z_simple_ssh(self): # _z_ cause we want it last - it messes up the process :(
+        # Recreate environment
+        environ = ' ; '.join( map("export %s=%r".__mod__, os.environ.iteritems()) )
+
+        env = test_util.test_environment()
+
+        access_config = proxy.AccessConfiguration({
+            DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
+            DC.ROOT_DIRECTORY : self.root_dir,
+            DC.LOG_LEVEL : DC.DEBUG_LEVEL,
+            DC.DEPLOYMENT_COMMUNICATION : DC.ACCESS_SSH,
+            DC.DEPLOYMENT_PORT : env.port,
+            DC.USE_AGENT : True,
+            DC.DEPLOYMENT_ENVIRONMENT_SETUP : environ,
+        })
+
+        self._test_simple(
+            daemonize_testbed = False,
+            controller_access_configuration = access_config,
+            environ = environ)
+
     @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
     def test_recover(self):
         self._test_recover(
             daemonize_testbed = False,
             controller_access_configuration = None)
 
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_recover_sfa(self):
+        self._test_recover(
+            daemonize_testbed = False,
+            controller_access_configuration = None,
+            use_sfa = True)
+
     @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
     def test_recover_daemonized(self):
         access_config = proxy.AccessConfiguration({
@@ -362,7 +403,20 @@ FIONREAD = 0x[0-9a-fA-F]{8}.*
         self._test_recover(
             daemonize_testbed = False,
             controller_access_configuration = access_config)
-        
+
+    @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+    def test_recover_daemonized_sfa(self):
+        access_config = proxy.AccessConfiguration({
+            DC.DEPLOYMENT_MODE : DC.MODE_DAEMON,
+            DC.ROOT_DIRECTORY : self.root_dir,
+            DC.LOG_LEVEL : DC.DEBUG_LEVEL,
+        })
+
+        self._test_recover(
+            daemonize_testbed = False,
+            controller_access_configuration = access_config,
+            use_sfa = True)
+
 
 if __name__ == '__main__':
     unittest.main()
index a5e8216..30143d0 100755 (executable)
@@ -7,12 +7,12 @@ from nepi.core.execute import ExperimentController
 from nepi.util import proxy
 from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
 import os
+import re
 import shutil
 import tempfile
 import test_util
 import time
 import unittest
-import re
 
 class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
     testbed_id = "planetlab"
@@ -68,7 +68,7 @@ class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
         pl_desc.set_attribute_value("plcHost", plchost1)
         pl_desc.set_attribute_value("tapPortBase", self.port_base)
         pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc.set_attribute_value("dedicatedSlice", True)
+        pl_desc.set_attribute_value("cleanProc", True)
 
         pl_desc2 = exp_desc.add_testbed_description(pl_provider)
         pl_desc2.set_attribute_value("homeDirectory", self.root_dir+"v2")
@@ -79,7 +79,7 @@ class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
         pl_desc2.set_attribute_value("plcHost", plchost2)
         pl_desc2.set_attribute_value("tapPortBase", self.port_base+500)
         pl_desc2.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc2.set_attribute_value("dedicatedSlice", True)
+        pl_desc2.set_attribute_value("cleanProc", True)
         
         return pl_desc, pl_desc2, exp_desc
     
index 6ed0aee..e8ed2da 100755 (executable)
@@ -7,12 +7,12 @@ from nepi.core.execute import ExperimentController
 from nepi.util import proxy
 from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
 import os
+import re
 import shutil
 import tempfile
 import test_util
 import time
 import unittest
-import re
 
 class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
     testbed_id = "planetlab"
@@ -70,8 +70,8 @@ class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
         pl_desc.set_attribute_value("plcHost", plchost1)
         pl_desc.set_attribute_value("tapPortBase", self.port_base)
         pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc.set_attribute_value("dedicatedSlice", True)
-        #pl_desc.set_attribute_value("plLogLevel", "DEBUG")
+        pl_desc.set_attribute_value("cleanProc", True)
+        pl_desc.set_attribute_value("plLogLevel", "DEBUG")
 
         pl_desc2 = exp_desc.add_testbed_description(pl_provider)
         pl_desc2.set_attribute_value("homeDirectory", self.root_dir+"v2")
@@ -82,8 +82,8 @@ class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
         pl_desc2.set_attribute_value("plcHost", plchost2)
         pl_desc2.set_attribute_value("tapPortBase", self.port_base+500)
         pl_desc2.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc2.set_attribute_value("dedicatedSlice", True)
-        #pl_desc2.set_attribute_value("plLogLevel", "DEBUG")
+        pl_desc2.set_attribute_value("cleanProc", True)
+        pl_desc2.set_attribute_value("plLogLevel", "DEBUG")
         
         return pl_desc, pl_desc2, exp_desc
     
index 9513a1a..a737732 100755 (executable)
@@ -7,12 +7,12 @@ from nepi.core.execute import ExperimentController
 from nepi.util import proxy
 from nepi.util.constants import DeploymentConfiguration as DC, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
 import os
+import re
 import shutil
 import tempfile
 import test_util
 import time
 import unittest
-import re
 
 class PlanetLabCrossIntegrationTestCase(unittest.TestCase):
     testbed_id = "planetlab"
@@ -58,7 +58,7 @@ class PlanetLabCrossIntegrationTestCase(unittest.TestCase):
         pl_desc.set_attribute_value("plcHost", plchost)
         pl_desc.set_attribute_value("tapPortBase", self.port_base)
         pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
-        pl_desc.set_attribute_value("dedicatedSlice", True)
+        pl_desc.set_attribute_value("cleanProc", True)
         #pl_desc.set_attribute_value("plLogLevel", "DEBUG")
         
         return pl_desc, exp_desc
diff --git a/test/util/tunchannel.py b/test/util/tunchannel.py
new file mode 100644 (file)
index 0000000..7bd3176
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+
+from nepi.util import tunchannel
+import socket
+import time
+import threading
+import unittest
+
+class TunnChannelTestCase(unittest.TestCase):
+    def test_send_suspend_terminate(self):
+        def tun_fwd(local, remote, TERMINATE, SUSPEND, STOPPED):
+            tunchannel.tun_fwd(local, remote, True, True, None, True,
+                TERMINATE, SUSPEND, None)
+            STOPPED.append(None)
+    
+        TERMINATE = []
+        SUSPEND = []
+        STOPPED = []
+    
+        s1, s2 = socket.socketpair()
+        s3, s4 = socket.socketpair()
+        s4.settimeout(2.0)
+
+        t = threading.Thread(target=tun_fwd, args=[s2, s3, TERMINATE, SUSPEND, STOPPED])
+        t.start()
+
+        txt = "0000|received"
+        s1.send(txt)
+        rtxt = s4.recv(len(txt))
+
+        self.assertTrue(rtxt == txt[4:])
+        
+        # Let's try to suspend execution now
+        cond = threading.Condition()
+        SUSPEND.insert(0, cond)
+
+        txt = "0000|suspended"
+        s1.send(txt)
+        
+        rtxt = "timeout"
+        try:
+            rtxt = s4.recv(len(txt))
+        except socket.timeout:
+            pass
+                    
+        self.assertTrue(rtxt == "timeout")
+
+        # Let's see if we can resume and receive the message
+        cond = SUSPEND[0]
+        SUSPEND.remove(cond)
+        cond.acquire()
+        cond.notify()
+        cond.release()
+
+        rtxt = s4.recv(len(txt))
+        self.assertTrue(rtxt == txt[4:])
+              
+        # Stop forwarding         
+        TERMINATE.append(None)
+
+        txt = "0000|never received"
+        s1.send(txt)
+        
+        rtxt = "timeout"
+        try:
+            rtxt = s4.recv(len(txt))
+        except socket.timeout:
+            pass
+                    
+        self.assertTrue(rtxt == "timeout")
+        self.assertTrue(STOPPED)
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/util_scripts/pl_maintenance.py b/util_scripts/pl_maintenance.py
new file mode 100644 (file)
index 0000000..a01558c
--- /dev/null
@@ -0,0 +1,62 @@
+import nepi.testbeds.planetlab.plcapi
+from optparse import OptionParser, SUPPRESS_HELP
+import os
+import subprocess
+
+def do_maintenance(slicename, hostnames):
+    for hostname in hostnames:
+        login = "%s@%s" % (slicename, hostname)
+        command = 'sudo yum reinstall -y --nogpgcheck fedora-release'
+        proc = subprocess.Popen(['ssh', '-t', '-o', 'StrictHostKeyChecking=no', login, command], 
+            stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = False)
+        retcode = proc.wait()
+        print hostname
+        print retcode
+        if retcode > 0:
+            print proc.stdout.read()
+            print proc.stderr.read()
+
+def run(slicename, plc_host, pl_user, pl_pwd, pl_ssh_key):
+    api = nepi.testbeds.planetlab.plcapi.plcapi(pl_user, pl_pwd, plc_host,
+        "https://%(hostname)s:443/PLCAPI/")
+    node_ids = api.GetSliceNodes(slicename)
+    hostnames = [d['hostname'] for d in api.GetNodes(node_ids, ['hostname'])]
+
+    do_maintenance(slicename, hostnames)
+
+
+if __name__ == '__main__':
+    slicename = os.environ.get("PL_SLICE")
+    pl_host = os.environ.get("PL_HOST", "www.planet-lab.eu")
+    pl_ssh_key = os.environ.get(
+        "PL_SSH_KEY",
+        "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
+    pl_user = os.environ.get('PL_USER')
+    pl_pwd = os.environ.get('PL_PASS')
+
+    usage = "usage: %prog -s <pl_slice> -H <pl_host> -k <ssh_key> -u <pl_user> -p <pl_password>"
+
+    parser = OptionParser(usage=usage)
+    parser.add_option("-s", "--slicename", dest="slicename", 
+            help="PlanetLab slicename", default=slicename, type="str")
+    parser.add_option("-H", "--pl-host", dest="pl_host", 
+            help="PlanetLab site (e.g. www.planet-lab.eu)", 
+            default=pl_host, type="str")
+    parser.add_option("-k", "--ssh-key", dest="pl_ssh_key", 
+            help="Path to private ssh key used for PlanetLab authentication", 
+            default=pl_ssh_key, type="str")
+    parser.add_option("-u", "--pl-user", dest="pl_user", 
+            help="PlanetLab account user (i.e. Registration email address)", 
+            default=pl_user, type="str")
+    parser.add_option("-p", "--pl-pwd", dest="pl_pwd", 
+            help="PlanetLab account password", default=pl_pwd, type="str")
+    (options, args) = parser.parse_args()
+
+    slicename = options.slicename
+    pl_host = options.pl_host
+    pl_user= options.pl_user
+    pl_pwd = options.pl_pwd
+    pl_ssh_key = options.pl_ssh_key
+
+    run(slicename, pl_host, pl_user, pl_pwd, pl_ssh_key)
+
similarity index 92%
rename from tunbench.py
rename to util_scripts/tunbench.py
index 9a3e6e7..63d842f 100644 (file)
@@ -38,14 +38,18 @@ def test(cipher, passphrase, plr=None, queuemodule=None):
    else:
         queueclass = None
    TERMINATE = []
+   SUSPEND = []
+
    def stopme():
        time.sleep(100)
        TERMINATE.append(None)
+
    t = threading.Thread(target=stopme)
    t.start()
-   tunchannel.tun_fwd(tun, remote, True, True, passphrase, True, TERMINATE, None, tunkqueue=500,
-        rwrite = rwrite, rread = rread, cipher=cipher, queueclass=queueclass,
-        accept_local = accept, accept_remote = accept)
+   tunchannel.tun_fwd(tun, remote, True, True, passphrase, True, TERMINATE,
+            SUSPEND, None, tunkqueue=500, rwrite = rwrite, rread = rread, 
+            cipher=cipher, queueclass=queueclass, accept_local = accept,
+            accept_remote = accept)
 
 # Swallow exceptions on decryption
 def decrypt(packet, crypter, super=tunchannel.decrypt):