Merging with HEAD
authorClaudio-Daniel Freire <claudio-daniel.freire@inria.fr>
Thu, 9 Jun 2011 13:06:22 +0000 (15:06 +0200)
committerClaudio-Daniel Freire <claudio-daniel.freire@inria.fr>
Thu, 9 Jun 2011 13:06:22 +0000 (15:06 +0200)
20 files changed:
examples/big_buck_bunny_240p_mpeg4.ts [moved from examples/big_buck_bunny_480p_h264.ts with 57% similarity]
examples/vlc_wireless_netns_ns3.py
src/nepi/core/execute.py
src/nepi/core/testbed_impl.py
src/nepi/testbeds/netns/execute.py
src/nepi/testbeds/netns/metadata_v01.py
src/nepi/testbeds/ns3/attributes_metadata_v3_9.py
src/nepi/testbeds/ns3/connection_metadata_v3_9.py
src/nepi/testbeds/ns3/execute.py
src/nepi/testbeds/ns3/factories_metadata_v3_9.py
src/nepi/testbeds/planetlab/execute.py
src/nepi/util/constants.py
src/nepi/util/parser/_xml.py
src/nepi/util/parser/base.py
src/nepi/util/proxy.py
test/core/execute.py
test/core/integration.py
test/testbeds/netns/execute.py
test/testbeds/netns/integration.py
test/testbeds/ns3/integration.py

similarity index 57%
rename from examples/big_buck_bunny_480p_h264.ts
rename to examples/big_buck_bunny_240p_mpeg4.ts
index 514789a..542244b 100644 (file)
Binary files a/examples/big_buck_bunny_480p_h264.ts and b/examples/big_buck_bunny_240p_mpeg4.ts differ
index 5c78868..1ecea3f 100644 (file)
@@ -114,7 +114,7 @@ class VlcWirelessNetnsNs3Example(object):
     def run(self):
         bounds_width = bounds_height = 200
         x = y = 100
-        speed = 1
+        speed = 7
 
         exp_desc = ExperimentDescription()
 
index 7f0d3ed..075b0a5 100644 (file)
@@ -341,6 +341,19 @@ class TestbedController(object):
     def trace(self, guid, trace_id, attribute='value'):
         raise NotImplementedError
 
+    def traces_info(self):
+        """ dictionary of dictionaries:
+            traces_info = dict({
+                guid = dict({
+                    trace_id = dict({
+                            host = host,
+                            filepath = filepath,
+                            filesize = size in bytes,
+                        })
+                })
+            })"""
+        raise NotImplementedError
+
     def shutdown(self):
         raise NotImplementedError
 
@@ -383,6 +396,12 @@ class ExperimentController(object):
             return testbed.trace(guid, trace_id, attribute)
         raise RuntimeError("No element exists with guid %d" % guid)    
 
+    def traces_info(self):
+        traces_info = dict()
+        for guid, testbed in self._testbeds.iteritems():
+            traces_info[guid] = testbed.traces_info()
+        return traces_info
+
     @staticmethod
     def _parallel(callables):
         excs = []
@@ -553,7 +572,9 @@ class ExperimentController(object):
         except:
             # Just print exceptions, this is just cleanup
             import traceback
-            traceback.print_exc(file=sys.stderr)
+            ######## BUG ##########
+            #BUG: If the next line is uncomented pyQt explodes when shutting down the experiment !!!!!!!!
+            #traceback.print_exc(file=sys.stderr)
 
     def stop(self):
        for testbed in self._testbeds.values():
index dbe944f..92cfb93 100644 (file)
@@ -12,9 +12,11 @@ from nepi.util.constants import STATUS_UNDETERMINED, TIME_NOW, \
     TESTBED_STATUS_CROSS_CONNECTED, \
     TESTBED_STATUS_CONFIGURED, \
     TESTBED_STATUS_STARTED, \
-    TESTBED_STATUS_STOPPED
+    TESTBED_STATUS_STOPPED,\
+    CONNECTION_DELAY
 
 import collections
+import copy
 
 class TestbedController(execute.TestbedController):
     def __init__(self, testbed_id, testbed_version):
@@ -204,27 +206,38 @@ class TestbedController(execute.TestbedController):
         self._status = TESTBED_STATUS_CREATED
 
     def _do_connect(self, init = True):
-        for guid1, connections in self._connect.iteritems():
-            factory1 = self._get_factory(guid1)
-            for connector_type_name1, connections2 in connections.iteritems():
-                connector_type1 = factory1.connector_type(connector_type_name1)
-                for guid2, connector_type_name2 in connections2.iteritems():
-                    factory_id2 = self._create[guid2]
-                    # Connections are executed in a "From -> To" direction only
-                    # This explicitly ignores the "To -> From" (mirror) 
-                    # connections of every connection pair.
-                    if init:
-                        connect_code = connector_type1.connect_to_init_code(
-                                self._testbed_id, factory_id2, 
-                                connector_type_name2,
-                                False)
-                    else:
-                        connect_code = connector_type1.connect_to_compl_code(
-                                self._testbed_id, factory_id2, 
-                                connector_type_name2,
-                                False)
-                    if connect_code:
-                        connect_code(self, guid1, guid2)
+        unconnected = copy.deepcopy(self._connect)
+        
+        while unconnected:
+            for guid1, connections in unconnected.items():
+                factory1 = self._get_factory(guid1)
+                for connector_type_name1, connections2 in connections.items():
+                    connector_type1 = factory1.connector_type(connector_type_name1)
+                    for guid2, connector_type_name2 in connections2.items():
+                        factory_id2 = self._create[guid2]
+                        # Connections are executed in a "From -> To" direction only
+                        # This explicitly ignores the "To -> From" (mirror) 
+                        # connections of every connection pair.
+                        if init:
+                            connect_code = connector_type1.connect_to_init_code(
+                                    self._testbed_id, factory_id2, 
+                                    connector_type_name2,
+                                    False)
+                        else:
+                            connect_code = connector_type1.connect_to_compl_code(
+                                    self._testbed_id, factory_id2, 
+                                    connector_type_name2,
+                                    False)
+                        delay = None
+                        if connect_code:
+                            delay = connect_code(self, guid1, guid2)
+
+                        if delay is not CONNECTION_DELAY:
+                            del unconnected[guid1][connector_type_name1][guid2]
+                    if not unconnected[guid1][connector_type_name1]:
+                        del unconnected[guid1][connector_type_name1]
+                if not unconnected[guid1]:
+                    del unconnected[guid1]
 
     def do_connect_init(self):
         self._do_connect()
@@ -445,22 +458,46 @@ class TestbedController(execute.TestbedController):
 
     def trace(self, guid, trace_id, attribute='value'):
         if attribute == 'value':
-            fd = open("%s" % self.trace_filename(guid, trace_id), "r")
+            fd = open("%s" % self.trace_filepath(guid, trace_id), "r")
             content = fd.read()
             fd.close()
         elif attribute == 'path':
-            content = self.trace_filename(guid, trace_id)
+            content = self.trace_filepath(guid, trace_id)
+        elif attribute == 'size':
+            content = str(self.traces_filesize(guid, trace_id))
         else:
             content = None
         return content
 
-    def trace_filename(self, guid, trace_id):
+    def traces_info(self):
+        traces_info = dict()
+        host = self._attributes.get_attribute_value("deployment_host")
+        for guid, trace_list in self._add_trace.iteritems(): 
+            traces_info[guid] = dict()
+            for trace_id in trace_list:
+                traces_info[guid][trace_id] = dict()
+                filepath = self.trace(guid, trace_id, attribute = "path")
+                # TODO: Filesize!
+                # filesize = self.trace(guid, trace_id)
+                filesize = -1
+                traces_info[guid][trace_id]["host"] = host
+                traces_info[guid][trace_id]["filepath"] = filepath
+                traces_info[guid][trace_id]["filesize"] = str(filesize)
+        return traces_info
+
+    def trace_filepath(self, guid, trace_id):
         """
         Return a trace's file path, for TestbedController's default 
         implementation of trace()
         """
         raise NotImplementedError
 
+    def trace_filesize(self, guid, trace_id):
+        """
+        Return a trace's filesize in bytes
+        """
+        raise NotImplementedError
+
     #shutdown: NotImplementedError
 
     def get_connected(self, guid, connector_type_name, 
index 2ec1a72..a76547a 100644 (file)
@@ -5,15 +5,55 @@ from constants import TESTBED_ID
 from nepi.core import testbed_impl
 from nepi.util.constants import TIME_NOW
 import os
+import fcntl
+import threading
 
 class TestbedController(testbed_impl.TestbedController):
     from nepi.util.tunchannel_impl import TunChannel
+    
+    class HostLock(object):
+        taken = False
+        processcond = threading.Condition()
+        
+        def __init__(self, lockfile):
+            processcond = self.__class__.processcond
+            
+            processcond.acquire()
+            try:
+                # It's not reentrant
+                while self.__class__.taken:
+                    processcond.wait()
+                self.__class__.taken = True
+            finally:
+                processcond.release()
+            
+            self.lockfile = lockfile
+            fcntl.flock(self.lockfile, fcntl.LOCK_EX)
+        
+        def __del__(self):
+            processcond = self.__class__.processcond
+            
+            processcond.acquire()
+            try:
+                assert self.__class__.taken, "HostLock unlocked without being locked!"
 
+                fcntl.flock(self.lockfile, fcntl.LOCK_UN)
+                
+                # It's not reentrant
+                self.__class__.taken = False
+                processcond.notify()
+            finally:
+                processcond.release()
+    
     def __init__(self, testbed_version):
         super(TestbedController, self).__init__(TESTBED_ID, testbed_version)
         self._netns = None
         self._home_directory = None
         self._traces = dict()
+        self._netns_lock = open("/tmp/nepi-netns-lock","a")
+    
+    def _lock(self):
+        return self.HostLock(self._netns_lock)
 
     @property
     def home_directory(self):
@@ -24,14 +64,29 @@ class TestbedController(testbed_impl.TestbedController):
         return self._netns
 
     def do_setup(self):
+        lock = self._lock()
+        
         self._home_directory = self._attributes.\
             get_attribute_value("homeDirectory")
+        # create home...
+        home = os.path.normpath(self.home_directory)
+        if not os.path.exists(home):
+            os.makedirs(home, 0755)
+
         self._netns = self._load_netns_module()
         super(TestbedController, self).do_setup()
+    
+    def do_create(self):
+        lock = self._lock()
+        super(TestbedController, self).do_create()    
 
     def set(self, guid, name, value, time = TIME_NOW):
         super(TestbedController, self).set(guid, name, value, time)
         # TODO: take on account schedule time for the task 
+        factory_id = self._create[guid]
+        factory = self._factories[factory_id]
+        if factory.box_attributes.is_attribute_design_only(name):
+            return
         element = self._elements.get(guid)
         if element:
             setattr(element, name, value)
@@ -53,8 +108,12 @@ class TestbedController(testbed_impl.TestbedController):
         raise NotImplementedError
 
     def shutdown(self):
-        for trace in self._traces.values():
-            trace.close()
+        lock = self._lock()
+        
+        for guid, traces in self._traces.iteritems():
+            for trace_id, (trace, filename) in traces.iteritems():
+                if hasattr(trace, "close"):
+                    trace.close()
         for guid, element in self._elements.iteritems():
             if isinstance(element, self.TunChannel):
                 element.Cleanup()
@@ -64,12 +123,15 @@ class TestbedController(testbed_impl.TestbedController):
                     element.destroy()
         self._elements.clear()
 
-    def trace_filename(self, guid, trace_id):
-        # TODO: Need to be defined inside a home!!!! with and experiment id_code
-        return os.path.join(self.home_directory, "%d_%s" % (guid, trace_id))
+    def trace_filepath(self, guid, trace_id, filename = None):
+        if not filename:
+            (trace, filename) = self._traces[guid][trace_id]
+        return os.path.join(self.home_directory, filename)
 
-    def follow_trace(self, trace_id, trace):
-        self._traces[trace_id] = trace
+    def follow_trace(self, guid, trace_id, trace, filename):
+        if not guid in self._traces:
+            self._traces[guid] = dict()
+        self._traces[guid][trace_id] = (trace, filename)
 
     def _load_netns_module(self):
         # TODO: Do something with the configuration!!!
index 9c2ee37..45be3b1 100644 (file)
@@ -27,6 +27,12 @@ TUNCHANNEL = "TunChannel"
 NS3_TESTBED_ID = "ns3"
 FDNETDEV = "ns3::FileDescriptorNetDevice"
 
+def _follow_trace(testbed_instance, guid, trace_id, filename):
+    filepath = testbed_instance.trace_filepath(guid, trace_id, filename)
+    trace = open(filepath, "wb")
+    testbed_instance.follow_trace(guid, trace_id, trace, filename)
+    return trace
+
 ### Connection functions ####
 
 def connect_switch(testbed_instance, switch_guid, interface_guid):
@@ -75,6 +81,27 @@ def connect_tunchannel_tap(testbed_instance, chan_guid, tap_guid):
         pass
     chan.with_pi = with_pi
 
+### Trace functions ###
+
+def nodepcap_trace(testbed_instance, guid, trace_id):
+    node = testbed_instance._elements[guid]
+    parameters = testbed_instance._get_parameters(guid)
+    filename = "%d-cap.stdout" % guid
+    stdout = _follow_trace(testbed_instance, guid, "pcap_stdout", filename)
+    filename = "%d-pcap.stderr" % guid
+    stderr = _follow_trace(testbed_instance, guid, "pcap_stderr", filename)
+    filename = "%d-node.pcap" % guid
+    filepath = testbed_instance.trace_filepath(guid, trace_id, filename)
+    command = "tcpdump -i 'any' -w %s" % filepath
+    user = "root"
+    trace = node.Popen(command, shell = True, stdout = stdout, 
+            stderr = stderr, user = user)
+    testbed_instance.follow_trace(guid, trace_id, trace, filename)
+
+trace_functions = dict({
+    "pcap": nodepcap_trace,
+    })
+
 ### Creation functions ###
 
 def create_node(testbed_instance, guid):
@@ -148,14 +175,11 @@ def start_application(testbed_instance, guid):
         user = parameters["user"]
     stdout = stderr = None
     if "stdout" in traces:
-        filename = testbed_instance.trace_filename(guid, "stdout")
-        stdout = open(filename, "wb")
-        testbed_instance.follow_trace("stdout", stdout)
+        filename = "%d-stdout.trace" % guid
+        stdout = _follow_trace(testbed_instance, guid, "stdout", filename)
     if "stderr" in traces:
-        filename = testbed_instance.trace_filename(guid, "stderr")
-        stderr = open(filename, "wb")
-        testbed_instance.follow_trace("stderr", stderr)
-
+        filename = "%d-stderr.trace" % guid
+        stderr = _follow_trace(testbed_instance, guid, "stderr", filename)
     node_guid = testbed_instance.get_connected(guid, "node", "apps")
     if len(node_guid) == 0:
         raise RuntimeError("Can't instantiate interface %d outside netns \
@@ -165,6 +189,11 @@ def start_application(testbed_instance, guid):
             stderr = stderr, user = user)
     testbed_instance.elements[guid] = element
 
+def stop_application(testbed_instance, guid):
+    #app = testbed_instance.elements[guid]
+    #app.signal()
+    pass
+
 ### Status functions ###
 
 def status_application(testbed_instance, guid):
@@ -177,7 +206,16 @@ def status_application(testbed_instance, guid):
 
 ### Configure functions ###
 
+def configure_traces(testbed_instance, guid):
+    traces = testbed_instance._get_traces(guid)
+    for trace_id in traces:
+        if trace_id not in trace_functions:
+            continue
+        trace_func = trace_functions[trace_id]
+        trace_func(testbed_instance, guid, trace_id)
+
 def configure_device(testbed_instance, guid):
+    configure_traces(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     if not guid in testbed_instance._add_address:
         return
@@ -188,6 +226,7 @@ def configure_device(testbed_instance, guid):
         element.add_v4_address(address, netprefix)
 
 def configure_node(testbed_instance, guid):
+    configure_traces(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     if not guid in testbed_instance._add_route:
         return
@@ -403,6 +442,10 @@ traces = dict({
     "stderr": dict({
                 "name": "stderr",
                 "help": "Application standard error",
+        }),
+    "node_pcap": dict({
+                "name": "pcap",
+                "help": "tcpdump at all node interfaces",
         }) 
     })
 
@@ -422,7 +465,8 @@ factories_info = dict({
             "create_function": create_node,
             "configure_function": configure_node,
             "box_attributes": ["forward_X11"],
-            "connector_types": ["devs", "apps"]
+            "connector_types": ["devs", "apps"],
+            "traces": ["node_pcap"]
        }),
     P2PIFACE: dict({
             "allow_addresses": True,
@@ -472,6 +516,7 @@ factories_info = dict({
             "category": "applications",
             "create_function": create_application,
             "start_function": start_application,
+            "stop_function": stop_application,
             "status_function": status_application,
             "box_attributes": ["command", "user"],
             "connector_types": ["node"],
index 4aa3880..85127d6 100644 (file)
@@ -2415,7 +2415,7 @@ attributes = dict({
         "name": "Standard",
         "validation_function": validation.is_string,
         "value": "WIFI_PHY_STANDARD_80211a",
-        "flags": Attribute.DesignOnly,
+        "flags": Attribute.DesignOnly | Attribute.HasNoDefaultValue,
         "type": Attribute.ENUM,
         "allowed": wifi_standards.keys(),
         "help": "Wifi PHY standard"
@@ -2527,4 +2527,12 @@ attributes = dict({
         "type": Attribute.ENUM,
         "help": "Service flow scheduling type",
     }),
+   "WaypointList": dict({
+        "name": "WaypointList",
+        "validation_function": validation.is_string, # TODO: SPECIAL VALIDATION FUNC
+        "value": "",
+        "flags": Attribute.DesignOnly,
+        "type": Attribute.STRING,
+        "help": "Comma separated list of waypoints in format t:x:y:z. Ex: 0s:0:0:0, 1s:1:0:0"
+    }),
 })
index 64fcbeb..aa16b6e 100644 (file)
@@ -3,6 +3,7 @@
 
 from constants import TESTBED_ID
 import functools
+from nepi.util.constants import CONNECTION_DELAY
 from nepi.util.tunchannel_impl import \
     crossconnect_tunchannel_peer_init, \
     crossconnect_tunchannel_peer_compl
@@ -29,6 +30,8 @@ def connect_manager_device(testbed_instance, manager_guid, device_guid):
 
 def connect_phy_device(testbed_instance, phy_guid, device_guid):
     phy = testbed_instance._elements[phy_guid]
+    if phy.GetErrorRateModel() == None:
+        return CONNECTION_DELAY
     device = testbed_instance._elements[device_guid]
     device.SetPhy(phy)
     phy.SetDevice(device)
@@ -413,6 +416,54 @@ connections = [
             "init_code": connect_manager_device,
             "can_cross": False
     }),
+    dict({
+            "from": ( "ns3", "ns3::AarfcdWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::AarfWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::AmrrWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::CaraWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::IdealWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::MinstrelWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::OnoeWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::RraaWifiManager", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
+            "init_code": connect_manager_device,
+            "can_cross": False
+    }),
     dict({
             "from": ( "ns3", "ns3::YansWifiPhy", "dev" ),
             "to":   ( "ns3", "ns3::WifiNetDevice", "phy" ),  
@@ -443,6 +494,18 @@ connections = [
             "init_code": connect_mac_device,
             "can_cross": False
     }),
+    dict({
+            "from": ( "ns3", "ns3::NqapWifiMac", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "mac" ),
+            "init_code": connect_mac_device,
+            "can_cross": False
+    }),
+    dict({
+            "from": ( "ns3", "ns3::NqstaWifiMac", "dev" ),
+            "to":   ( "ns3", "ns3::WifiNetDevice", "mac" ),
+            "init_code": connect_mac_device,
+            "can_cross": False
+    }),
     dict({
             "from": ( "ns3", "ns3::RateErrorModel", "dev" ),
             "to":   ( "ns3", "ns3::CsmaNetDevice", "err" ),
@@ -658,6 +721,12 @@ connections = [
         "init_code": connect_node_other,
         "can_cross": False
     }),
+    dict({
+        "from": ( "ns3", "ns3::Node", "mobility" ),
+        "to":   ( "ns3", "ns3::WaypointMobilityModel", "node" ),
+        "init_code": connect_node_other,
+        "can_cross": False
+    }),
     dict({
         "from": ( "ns3", "ns3::SubscriberStationNetDevice", "sflows" ),
         "to":   ( "ns3", "ns3::ServiceFlow", "dev" ),
index 1e5a8b9..754c206 100644 (file)
@@ -55,14 +55,12 @@ class TestbedController(testbed_impl.TestbedController):
         self._condition = threading.Condition()
         self._simulator_thread = threading.Thread(target = self._simulator_run,
                 args = [self._condition])
-        self._simulator_thread.setDaemon(True)
         self._simulator_thread.start()
 
     def stop(self, time = TIME_NOW):
         super(TestbedController, self).stop(time)
-        # BUG!!!! RealtimeSimulatorImpl never stops simulation with Stop()!!!
-        self.ns3.Simulator.Stop()
-        #self._stop_simulation(time)
+        #self.ns3.Simulator.Stop()
+        self._stop_simulation(time)
 
     def set(self, guid, name, value, time = TIME_NOW):
         super(TestbedController, self).set(guid, name, value, time)
@@ -116,13 +114,12 @@ class TestbedController(testbed_impl.TestbedController):
     def action(self, time, guid, action):
         raise NotImplementedError
 
-    def trace_filename(self, guid, trace_id):
-        # TODO: Need to be defined inside a home!!!! with and experiment id_code
+    def trace_filepath(self, guid, trace_id):
         filename = self._traces[guid][trace_id]
         return os.path.join(self.home_directory, filename)
 
     def follow_trace(self, guid, trace_id, filename):
-        if guid not in self._traces:
+        if not guid in self._traces:
             self._traces[guid] = dict()
         self._traces[guid][trace_id] = filename
 
@@ -133,14 +130,10 @@ class TestbedController(testbed_impl.TestbedController):
                 element.Cleanup()
         self._elements.clear()
         if self.ns3:
-            self.ns3.Simulator.Stop()
-            ##################################################
-            # BUG!!!! RealtimeSimulatorImpl never stops simulation with Stop()!!!
-            # self._stop_simulation("0s")
-            # if self._simulator_thread:
-            #    print "Joining thread"
-            #    self._simulator_thread.join()
-            #################################################
+            #self.ns3.Simulator.Stop()
+            self._stop_simulation("0s")
+            if self._simulator_thread:
+                self._simulator_thread.join()
             self.ns3.Simulator.Destroy()
         self._ns3 = None
         sys.stdout.flush()
index 990b6ca..4a2f929 100644 (file)
@@ -7,6 +7,7 @@ from nepi.util.constants import AF_INET, STATUS_NOT_STARTED, STATUS_RUNNING, \
 from nepi.util.tunchannel_impl import \
     preconfigure_tunchannel, postconfigure_tunchannel, \
     wait_tunchannel, create_tunchannel
+import re
 
 wifi_standards = dict({
     "WIFI_PHY_STANDARD_holland": 5,
@@ -76,6 +77,11 @@ def _get_dev_number(testbed_instance, guid):
         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)
+    return filepath
+
 ### create traces functions ###
 
 def p2pascii_trace(testbed_instance, guid, trace_id):
@@ -83,11 +89,10 @@ def p2pascii_trace(testbed_instance, guid, trace_id):
     interface_number = _get_dev_number(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     filename = "trace-p2p-node-%d-dev-%d.tr" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.PointToPointHelper()
     asciiHelper = testbed_instance.ns3.AsciiTraceHelper()
-    stream = asciiHelper.CreateFileStream (filepath)
+    stream = asciiHelper.CreateFileStream(filepath)
     helper.EnableAscii(stream, element)
 
 def p2ppcap_trace(testbed_instance, guid, trace_id):
@@ -95,8 +100,7 @@ def p2ppcap_trace(testbed_instance, guid, trace_id):
     interface_number = _get_dev_number(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     filename = "trace-p2p-node-%d-dev-%d.pcap" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.PointToPointHelper()
     helper.EnablePcap(filepath, element, explicitFilename = True)
 
@@ -105,8 +109,7 @@ def _csmapcap_trace(testbed_instance, guid, trace_id, promisc):
     interface_number = _get_dev_number(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     filename = "trace-csma-node-%d-dev-%d.pcap" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.CsmaHelper()
     helper.EnablePcap(filepath, element, promiscuous = promisc, 
             explicitFilename = True)
@@ -124,8 +127,7 @@ def fdpcap_trace(testbed_instance, guid, trace_id):
     interface_number = _get_dev_number(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     filename = "trace-fd-node-%d-dev-%d.pcap" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.FileDescriptorHelper()
     helper.EnablePcap(filepath, element, explicitFilename = True)
 
@@ -135,8 +137,7 @@ def yanswifipcap_trace(testbed_instance, guid, trace_id):
     interface_number = _get_dev_number(testbed_instance, dev_guid)
     element = testbed_instance._elements[dev_guid]
     filename = "trace-yanswifi-node-%d-dev-%d.pcap" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.YansWifiPhyHelper()
     helper.EnablePcap(filepath, element, explicitFilename = True)
 
@@ -145,8 +146,7 @@ def wimaxascii_trace(testbed_instance, guid, trace_id):
     interface_number = _get_dev_number(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     filename = "trace-wimax-node-%d-dev-%d.tr" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.WimaxHelper()
     asciiHelper = testbed_instance.ns3.AsciiTraceHelper()
     stream = asciiHelper.CreateFileStream (filepath)
@@ -158,8 +158,7 @@ def wimaxpcap_trace(testbed_instance, guid, trace_id):
     interface_number = _get_dev_number(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     filename = "trace-wimax-node-%d-dev-%d.pcap" % (node_guid, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     helper = testbed_instance.ns3.WimaxHelper()
     helper.EnablePcap(filepath, element, explicitFilename = True)
 
@@ -168,12 +167,10 @@ def rtt_trace(testbed_instance, guid, trace_id):
     helper = testbed_instance.ns3.PlotHelper()
     prefix = "trace-app-%d" % (guid, )
     filename = helper.GetFilenameFromSource(prefix, element, trace_id)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(guid, trace_id)
+    filepath = _follow_trace(testbed_instance, guid, trace_id, filename)
     prefix = filepath[:filepath.find(prefix)+len(prefix)]
     helper.EnableTrace(element, trace_id, prefix, "T")
 
-
 trace_functions = dict({
     "P2PPcapTrace": p2ppcap_trace,
     "P2PAsciiTrace": p2pascii_trace,
@@ -208,10 +205,25 @@ def create_wifi_standard_model(testbed_instance, guid):
     create_element(testbed_instance, guid)
     element = testbed_instance._elements[guid]
     parameters = testbed_instance._get_parameters(guid)
-    if "Standard" in parameters:
-        standard = parameters["Standard"]
-        if standard:
-            element.ConfigureStandard(wifi_standards[standard])
+    standard = parameters.get("Standard")
+    if not standard:
+        raise RuntimeError("No wifi standard set for %d" % guid)
+    element.ConfigureStandard(wifi_standards[standard])
+
+def create_waypoint_mobility(testbed_instance, guid):
+    create_element(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    parameters = testbed_instance._get_parameters(guid)
+    ns3 = testbed_instance.ns3
+    waypoints = parameters.get("WaypointList", "")
+    waypoints = re.sub(" |\(|\)", "", waypoints)
+    for swp in waypoints.split(","):
+        dwp = swp.split(":")
+        t = str(dwp[0])
+        time = ns3.Time(t)
+        pos = ns3.Vector(float(dwp[1]), float(dwp[2]), float(dwp[3]))
+        waypoint = ns3.Waypoint(time, pos)
+        element.AddWaypoint(waypoint)
 
 def create_ipv4protocol(testbed_instance, guid):
     create_element(testbed_instance, guid)
@@ -269,14 +281,10 @@ def create_wimax_phy(testbed_instance, guid):
 
 def create_service_flow(testbed_instance, guid):
     parameters = testbed_instance._get_parameters(guid)
-    direction = None
-    if "Direction" in parameters:
-        direction = parameters["Direction"]
+    direction = parameters.get("Direction")
     if direction == None:
         raise RuntimeError("No SchedulingType was found for service flow %d" % guid)
-    sched = None
-    if "SchedulingType" in parameters:
-        sched = parameters["SchedulingType"]
+    sched = parameters.get("SchedulingType")
     if sched == None:
         raise RuntimeError("No SchedulingType was found for service flow %d" % guid)
     ServiceFlow = testbed_instance.ns3.ServiceFlow
@@ -300,58 +308,38 @@ def create_service_flow(testbed_instance, guid):
 
 def create_ipcs_classifier_record(testbed_instance, guid):
     parameters = testbed_instance._get_parameters(guid)
-    src_address = None
-    if "SrcAddress" in parameters:
-        src_address = parameters["SrcAddress"]
+    src_address = parameters.get("SrcAddress")
     if src_address == None:
         raise RuntimeError("No SrcAddress was found for classifier %d" % guid)
     src_address = testbed_instance.ns3.Ipv4Address(src_address)
-    src_mask= None
-    if "SrcMask" in parameters:
-        src_mask = parameters["SrcMask"]
+    src_mask = parameters.get("SrcMask")
     if src_mask == None:
         raise RuntimeError("No SrcMask was found for classifier %d" % guid)
     src_mask = testbed_instance.ns3.Ipv4Mask(src_mask)
-    dst_address = None
-    if "DstAddress" in parameters:
-        dst_address = parameters["DstAddress"]
+    dst_address = parameters.get("DstAddress")
     if dst_address == None:
         raise RuntimeError("No Dstddress was found for classifier %d" % guid)
     dst_address = testbed_instance.ns3.Ipv4Address(dst_address)
-    dst_mask= None
-    if "DstMask" in parameters:
-        dst_mask = parameters["DstMask"]
+    dst_mask = parameters.get("DstMask")
     if dst_mask == None:
         raise RuntimeError("No DstMask was found for classifier %d" % guid)
     dst_mask = testbed_instance.ns3.Ipv4Mask(dst_mask)
-    src_port_low = None
-    if "SrcPortLow" in parameters:
-        src_port_low = parameters["SrcPortLow"]
+    src_port_low = parameters.get("SrcPortLow")
     if src_port_low == None:
         raise RuntimeError("No SrcPortLow was found for classifier %d" % guid)
-    src_port_high= None
-    if "SrcPortHigh" in parameters:
-        src_port_high = parameters["SrcPortHigh"]
+    src_port_high = parameters.get("SrcPortHigh")
     if src_port_high == None:
         raise RuntimeError("No SrcPortHigh was found for classifier %d" % guid)
-    dst_port_low = None
-    if "DstPortLow" in parameters:
-        dst_port_low = parameters["DstPortLow"]
+    dst_port_low = parameters.get("DstPortLow")
     if dst_port_low == None:
         raise RuntimeError("No DstPortLow was found for classifier %d" % guid)
-    dst_port_high = None
-    if "DstPortHigh" in parameters:
-        dst_port_high = parameters["DstPortHigh"]
+    dst_port_high = parameters.get("DstPortHigh")
     if dst_port_high == None:
         raise RuntimeError("No DstPortHigh was found for classifier %d" % guid)
-    protocol = None
-    if "Protocol" in parameters:
-        protocol = parameters["Protocol"]
+    protocol = parameters.get("Protocol")
     if protocol == None or protocol not in l4_protocols:
         raise RuntimeError("No Protocol was found for classifier %d" % guid)
-    priority = None
-    if "Priority" in parameters:
-        priority = parameters["Priority"]
+    priority = parameters.get("Priority")
     if priority == None:
         raise RuntimeError("No Priority was found for classifier %d" % guid)
     element = testbed_instance.ns3.IpcsClassifierRecord(src_address, src_mask,
@@ -382,13 +370,13 @@ def status_application(testbed_instance, guid):
         return STATUS_NOT_STARTED
     app = testbed_instance.elements[guid]
     parameters = testbed_instance._get_parameters(guid)
-    if "StartTime" in parameters and parameters["StartTime"]:
-        start_value = parameters["StartTime"]
+    start_value = parameters.get("StartTime")
+    if start_value != None:
         start_time = testbed_instance.ns3.Time(start_value)
         if now.Compare(start_time) < 0:
             return STATUS_NOT_STARTED
-    if "StopTime" in parameters and parameters["StopTime"]:
-        stop_value = parameters["StopTime"]
+    stop_value = parameters.get("StopTime")
+    if stop_value != None:
         stop_time = testbed_instance.ns3.Time(stop_value)
         if now.Compare(stop_time) < 0:
             return STATUS_RUNNING
@@ -413,8 +401,8 @@ def configure_device(testbed_instance, guid):
     element = testbed_instance._elements[guid]
 
     parameters = testbed_instance._get_parameters(guid)
-    if "macAddress" in parameters:
-        address = parameters["macAddress"]
+    address = parameters.get("macAddress")
+    if address:
         macaddr = testbed_instance.ns3.Mac48Address(address)
     else:
         macaddr = testbed_instance.ns3.Mac48Address.Allocate()
@@ -732,7 +720,7 @@ factories_info = dict({
         "tags": [tags.MOBILE],
     }),
      "ns3::Node": dict({
-        "category": "Topology",
+        "category": "Node",
         "create_function": create_node,
         "configure_function": configure_node,
         "help": "",
@@ -853,7 +841,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["SuccessK",
             "TimerK",
             "MaxSuccessThreshold",
@@ -1033,13 +1021,14 @@ factories_info = dict({
     }),
      "ns3::WaypointMobilityModel": dict({
         "category": "Mobility",
-        "create_function": create_element,
+        "create_function": create_waypoint_mobility,
         "configure_function": configure_element,
-        "help": "",
-        "connector_types": [],
+        "help": "Waypoint-based mobility model.",
+        "connector_types": ["node"],
         "box_attributes": ["WaypointsLeft",
             "Position",
-            "Velocity"],
+            "Velocity",
+            "WaypointList"],
         "tags": [tags.MOBILE],
     }),
      "ns3::FileDescriptorNetDevice": dict({
@@ -1089,10 +1078,10 @@ factories_info = dict({
     }),
      "ns3::NqstaWifiMac": dict({
         "category": "Mac",
-        "create_function": create_element,
+        "create_function": create_wifi_standard_model,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["ProbeRequestTimeout",
             "AssocRequestTimeout",
             "MaxMissedBeacons",
@@ -1256,7 +1245,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["ProbeThreshold",
             "FailureThreshold",
             "SuccessThreshold",
@@ -1349,10 +1338,10 @@ factories_info = dict({
     }),
      "ns3::NqapWifiMac": dict({
         "category": "Mac",
-        "create_function": create_element,
+        "create_function": create_wifi_standard_model,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["BeaconInterval",
             "BeaconGeneration",
             "CtsTimeout",
@@ -1487,7 +1476,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["SuccessK",
             "TimerK",
             "MaxSuccessThreshold",
@@ -1581,7 +1570,7 @@ factories_info = dict({
         "box_attributes": ["DefaultLoss"],
     }),
      "ns3::WifiNetDevice": dict({
-        "category": "Wifi",
+        "category": "Device",
         "create_function": create_element,
         "configure_function": configure_device,
         "help": "",
@@ -1590,7 +1579,7 @@ factories_info = dict({
         "box_attributes": ["Mtu"],
     }),
      "ns3::CsmaChannel": dict({
-        "category": "Topology",
+        "category": "Channel",
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
@@ -1758,7 +1747,7 @@ factories_info = dict({
             "EnableBeaconCollisionAvoidance"],
     }),
      "ns3::MeshPointDevice": dict({
-        "category": "Topology",
+        "category": "Device",
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
@@ -1939,7 +1928,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["BerThreshold",
             "IsLowLatency",
             "MaxSsrc",
@@ -2029,7 +2018,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["Basic",
             "Timeout",
             "ewndFor54mbps",
@@ -2082,7 +2071,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["UpdateStatistics",
             "LookAroundRate",
             "EWMA",
@@ -2170,7 +2159,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["UpdatePeriod",
             "RaiseThreshold",
             "AddCreditThreshold",
@@ -2381,7 +2370,7 @@ factories_info = dict({
         "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
-        "connector_types": [],
+        "connector_types": ["dev"],
         "box_attributes": ["UpdatePeriod",
             "FailureRatio",
             "SuccessRatio",
index aa17562..8813ae4 100644 (file)
@@ -393,6 +393,9 @@ class TestbedController(testbed_impl.TestbedController):
                 content = None
         elif attribute == 'path':
             content = app.remote_trace_path(trace_id)
+        elif attribute == 'size':
+            # TODO
+            raise NotImplementedError
         else:
             content = None
         return content
index ec00adc..f5cfa11 100644 (file)
@@ -20,6 +20,7 @@ TESTBED_STATUS_STOPPED = 7
 
 TIME_NOW = "0s"
 
+CONNECTION_DELAY = 0
 
 ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP = "_nepi_testbed_environment_setup"
 
index 7f439cf..8eb3f07 100644 (file)
@@ -16,7 +16,7 @@ class XmlExperimentParser(ExperimentParser):
         exp_tag.appendChild(testbeds_tag)
 
         elements_tags = dict()
-        for guid in data.guids:
+        for guid in sorted(data.guids):
             if data.is_testbed_data(guid):
                 elements_tag = self.testbed_data_to_xml(doc, testbeds_tag, guid, data)
                 elements_tags[guid] = elements_tag
index 89d88de..c06dabc 100644 (file)
@@ -261,7 +261,7 @@ class ExperimentParser(object):
 
     def from_data(self, experiment_description, data):
         box_guids = list()
-        for guid in data.guids:
+        for guid in sorted(data.guids):
             if data.is_testbed_data(guid):
                 self.testbed_from_data(experiment_description, guid, data)
             else:
index 7ed34ce..b13c8d2 100644 (file)
@@ -57,6 +57,7 @@ DO_PRESTART = 37
 GET_FACTORY_ID = 38
 GET_TESTBED_ID = 39
 GET_TESTBED_VERSION = 40
+TRACES_INFO = 41
 
 instruction_text = dict({
     OK:     "OK",
@@ -98,6 +99,7 @@ instruction_text = dict({
     GUIDS:  "GUIDS",
     TESTBED_ID: "TESTBED_ID",
     TESTBED_VERSION: "TESTBED_VERSION",
+    TRACES_INFO: "TRACES_INFO",
     })
 
 def log_msg(server, params):
@@ -179,7 +181,7 @@ class PermDir(object):
     def __init__(self, path):
         self.path = path
 
-def create_controller(xml, access_config = None):
+def create_experiment_controller(xml, access_config = None):
     mode = None if not access_config \
             else access_config.get_attribute_value(DC.DEPLOYMENT_MODE)
     launch = True if not access_config \
@@ -475,6 +477,12 @@ class TestbedControllerServer(BaseServer):
     def trace(self, guid, trace_id, attribute):
         return self._testbed.trace(guid, trace_id, attribute)
 
+    @Marshalling.handles(TRACES_INFO)
+    @Marshalling.args()
+    @Marshalling.retval( Marshalling.pickled_data )
+    def traces_info(self):
+        return self._testbed.traces_info()
+
     @Marshalling.handles(START)
     @Marshalling.args()
     @Marshalling.retvoid
@@ -655,90 +663,96 @@ class ExperimentControllerServer(BaseServer):
     def __init__(self, root_dir, log_level, experiment_xml):
         super(ExperimentControllerServer, self).__init__(root_dir, log_level)
         self._experiment_xml = experiment_xml
-        self._controller = None
+        self._experiment = None
 
     def post_daemonize(self):
         from nepi.core.execute import ExperimentController
-        self._controller = ExperimentController(self._experiment_xml, 
+        self._experiment = ExperimentController(self._experiment_xml, 
             root_dir = self._root_dir)
 
     @Marshalling.handles(GUIDS)
     @Marshalling.args()
     @Marshalling.retval( Marshalling.pickled_data )
     def guids(self):
-        return self._controller.guids
+        return self._experiment.guids
 
     @Marshalling.handles(XML)
     @Marshalling.args()
     @Marshalling.retval()
     def experiment_xml(self):
-        return self._controller.experiment_xml
+        return self._experiment.experiment_xml
         
     @Marshalling.handles(TRACE)
     @Marshalling.args(int, str, Marshalling.base64_data)
     @Marshalling.retval()
     def trace(self, guid, trace_id, attribute):
-        return str(self._controller.trace(guid, trace_id, attribute))
+        return str(self._experiment.trace(guid, trace_id, attribute))
+
+    @Marshalling.handles(TRACES_INFO)
+    @Marshalling.args()
+    @Marshalling.retval( Marshalling.pickled_data )
+    def traces_info(self):
+        return self._experiment.traces_info()
 
     @Marshalling.handles(FINISHED)
     @Marshalling.args(int)
     @Marshalling.retval(Marshalling.bool)
     def is_finished(self, guid):
-        return self._controller.is_finished(guid)
+        return self._experiment.is_finished(guid)
 
     @Marshalling.handles(GET)
     @Marshalling.args(int, Marshalling.base64_data, str)
     @Marshalling.retval( Marshalling.pickled_data )
     def get(self, guid, name, time):
-        return self._controller.get(guid, name, time)
+        return self._experiment.get(guid, name, time)
 
     @Marshalling.handles(SET)
     @Marshalling.args(int, Marshalling.base64_data, Marshalling.pickled_data, str)
     @Marshalling.retvoid
     def set(self, guid, name, value, time):
-        self._controller.set(guid, name, value, time)
+        self._experiment.set(guid, name, value, time)
 
     @Marshalling.handles(START)
     @Marshalling.args()
     @Marshalling.retvoid
     def start(self):
-        self._controller.start()
+        self._experiment.start()
 
     @Marshalling.handles(STOP)
     @Marshalling.args()
     @Marshalling.retvoid
     def stop(self):
-        self._controller.stop()
+        self._experiment.stop()
 
     @Marshalling.handles(RECOVER)
     @Marshalling.args()
     @Marshalling.retvoid
     def recover(self):
-        self._controller.recover()
+        self._experiment.recover()
 
     @Marshalling.handles(SHUTDOWN)
     @Marshalling.args()
     @Marshalling.retvoid
     def shutdown(self):
-        self._controller.shutdown()
+        self._experiment.shutdown()
 
     @Marshalling.handles(GET_TESTBED_ID)
     @Marshalling.args(int)
     @Marshalling.retval()
     def get_testbed_id(self, guid):
-        return self._controller.get_testbed_id(guid)
+        return self._experiment.get_testbed_id(guid)
 
     @Marshalling.handles(GET_FACTORY_ID)
     @Marshalling.args(int)
     @Marshalling.retval()
     def get_factory_id(self, guid):
-        return self._controller.get_factory_id(guid)
+        return self._experiment.get_factory_id(guid)
 
     @Marshalling.handles(GET_TESTBED_VERSION)
     @Marshalling.args(int)
     @Marshalling.retval()
     def get_testbed_version(self, guid):
-        return self._controller.get_testbed_version(guid)
+        return self._experiment.get_testbed_version(guid)
 
 class BaseProxy(object):
     _ServerClass = None
index 8055e99..2c59ceb 100755 (executable)
@@ -48,9 +48,20 @@ class ExecuteTestCase(unittest.TestCase):
 --- 10.0.0.2 ping statistics ---
 1 packets transmitted, 1 received, 0% packet loss, time 0ms
 """
-        
         self.assertTrue(app_result.startswith(comp_result))
 
+        traces_info = instance.traces_info()
+        expected_traces_info = dict({
+            7 : dict({
+                'fake': dict({
+                    'host': 'localhost', 
+                    'filesize': '-1', 
+                    'filepath': '<test>'
+                    })
+                })
+            })
+        self.assertEquals(traces_info, expected_traces_info)
+
         instance.stop()
         instance.shutdown()
 
index c135b5f..4c0240b 100755 (executable)
@@ -75,7 +75,7 @@ class ExecuteTestCase(unittest.TestCase):
                 self.make_cross_test_experiment()
         xml = exp_desc.to_xml()
         access_config = None
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         cross1 = controller.get(iface12.guid, "cross")
@@ -88,7 +88,7 @@ class ExecuteTestCase(unittest.TestCase):
         exp_desc, desc, app, node1, node2, iface1, iface2 = self.make_test_experiment()
         xml = exp_desc.to_xml()
         access_config = None
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
@@ -114,7 +114,7 @@ class ExecuteTestCase(unittest.TestCase):
         access_config = proxy.AccessConfiguration()
         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
@@ -142,7 +142,7 @@ class ExecuteTestCase(unittest.TestCase):
 
         xml = exp_desc.to_xml()
         
-        controller = proxy.create_controller(xml, access_config = None)
+        controller = proxy.create_experiment_controller(xml, access_config = None)
 
         controller.start()
         while not controller.is_finished(app.guid):
@@ -175,7 +175,7 @@ class ExecuteTestCase(unittest.TestCase):
         access_config = proxy.AccessConfiguration()
         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
@@ -192,6 +192,20 @@ class ExecuteTestCase(unittest.TestCase):
         self.assertEquals(controller.get_testbed_version(node1.guid), "01")
         self.assertEquals(controller.get_factory_id(node1.guid), "Node")
 
+        traces_info = controller.traces_info()
+        expected_traces_info = dict({
+            1: dict({ # testbed guid
+                6: dict({ # element guid
+                    'fake': dict({ # trace_id
+                        'host': 'localhost', 
+                        'filesize': '-1', 
+                        'filepath': '<test>'
+                        })
+                    })
+                })
+            })
+        self.assertEquals(traces_info, expected_traces_info)
+
         controller.stop()
         controller.shutdown()
 
@@ -208,7 +222,7 @@ class ExecuteTestCase(unittest.TestCase):
         access_config = proxy.AccessConfiguration()
         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
@@ -230,7 +244,7 @@ class ExecuteTestCase(unittest.TestCase):
         
         # recover
         access_config.set_attribute_value(DC.RECOVER,True)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
         
         # test recovery
         self.assertTrue(controller.is_finished(app.guid))
@@ -250,7 +264,7 @@ class ExecuteTestCase(unittest.TestCase):
         
         xml = exp_desc.to_xml()
         access_config = None
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
         controller.start()
         while not controller.is_finished(app.guid):
             time.sleep(0.5)
@@ -285,7 +299,7 @@ class ExecuteTestCase(unittest.TestCase):
         
         xml = exp_desc.to_xml()
         access_config = None
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
         controller.start()
         while not controller.is_finished(app.guid):
             time.sleep(0.5)
@@ -328,7 +342,7 @@ class ExecuteTestCase(unittest.TestCase):
         access_config.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
         access_config.set_attribute_value(DC.DEPLOYMENT_PORT, env.port)
         access_config.set_attribute_value(DC.USE_AGENT, True)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
index 39fd54d..178d773 100755 (executable)
@@ -165,7 +165,46 @@ class NetnsExecuteTestCase(unittest.TestCase):
         self.assertTrue(ping_result.startswith(comp_result))
         instance.stop()
         instance.shutdown()
-        
+
+    @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
+    def test_node_pcap_trace(self):
+        user = getpass.getuser()
+        testbed_version = "01"
+        instance = netns.TestbedController(testbed_version)
+        instance.defer_configure("homeDirectory", self.root_dir)
+        instance.defer_create(2, "Node")
+        instance.defer_add_trace(2, "pcap")
+        instance.defer_create(3, "Node")
+        instance.defer_create(4, "P2PNodeInterface")
+        instance.defer_create_set(4, "up", True)
+        instance.defer_connect(2, "devs", 4, "node")
+        instance.defer_add_address(4, "10.0.0.1", 24, None)
+        instance.defer_create(5, "P2PNodeInterface")
+        instance.defer_create_set(5, "up", True)
+        instance.defer_connect(3, "devs", 5, "node")
+        instance.defer_add_address(5, "10.0.0.2", 24, None)
+        instance.defer_connect(4, "p2p", 5, "p2p")
+        instance.defer_create(6, "Application")
+        instance.defer_add_trace(6, "stdout")
+        instance.defer_create_set(6, "command", "ping -qc5 10.0.0.2")
+        instance.defer_create_set(6, "user", user)
+        instance.defer_connect(6, "node", 2, "apps")
+
+        instance.do_setup()
+        instance.do_create()
+        instance.do_connect_init()
+        instance.do_connect_compl()
+        instance.do_preconfigure()
+        instance.do_configure()
+        instance.do_prestart()
+        instance.start()
+        while instance.status(6) != STATUS_FINISHED:
+            time.sleep(0.5)
+        pcap_result = instance.trace(2, "pcap")
+        self.assertEquals(len(pcap_result), 1024)
+        instance.stop()
+        instance.shutdown()
+
     def tearDown(self):
         try:
             shutil.rmtree(self.root_dir)
index c2d494a..96d68cd 100755 (executable)
@@ -108,7 +108,7 @@ class NetnsIntegrationTestCase(unittest.TestCase):
         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
         access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
@@ -171,7 +171,7 @@ class NetnsIntegrationTestCase(unittest.TestCase):
         access_config.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION, DC.ACCESS_SSH)
         access_config.set_attribute_value(DC.DEPLOYMENT_PORT, env.port)
         access_config.set_attribute_value(DC.USE_AGENT, True)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):
index d247d21..5625c96 100755 (executable)
@@ -140,7 +140,7 @@ class Ns3IntegrationTestCase(unittest.TestCase):
         access_config.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
         access_config.set_attribute_value(DC.ROOT_DIRECTORY, self.root_dir)
         access_config.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
-        controller = proxy.create_controller(xml, access_config)
+        controller = proxy.create_experiment_controller(xml, access_config)
 
         controller.start()
         while not controller.is_finished(app.guid):