Added ccnxdaemon box to PlanetLab
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 9 Apr 2012 15:06:30 +0000 (17:06 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 9 Apr 2012 15:06:30 +0000 (17:06 +0200)
src/nepi/testbeds/planetlab/application.py
src/nepi/testbeds/planetlab/execute.py
src/nepi/testbeds/planetlab/metadata.py

index e198a5f..32e21cf 100644 (file)
@@ -206,10 +206,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') ),
                     )
@@ -1089,3 +1092,109 @@ 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.command = None
+        self.routes = None
+         
+        self.buildDepends = 'make gcc development-tools openssl-devel expat-devel libpcap-devel libxml2-devel'
+        
+        # We have to download the sources, untar, build...
+        ccnx_source_url = "http://www.ccnx.org/releases/ccnx-0.5.1.tar.gz"
+
+        self.build = (
+            " ( "
+            "  cd .. && "
+            "  test -d ccnx-src/build/bin "
+            " ) || ( "
+                # Not working, rebuild
+                     "wget -q -c -O ccnx-src.tar.gz %(ccnx_source_url)s &&"
+                     "mkdir -p ccnx-src && "
+                     "tar xzf ccnx-src.tar.gz --strip-components=1 -C ccnx-src && "
+                     "cd ccnx-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(ccnx_source_url),
+                 ))
+
+        self.install = (
+            " ( "
+            "  cd .. && "
+            "  test -d ${SOURCES}/bin "
+            " ) || ( "
+            "  test -d ${BUILD}/ccnx-src/build/bin && "
+            "  cp -r ${BUILD}/ccnx-src/build/bin ${SOURCES}"
+            " )"
+        )
+
+        self.env['PATH'] = "$PATH:${SOURCES}/bin"
+    
+    def start(self):
+        # Start will be invoked in prestart step
+        routes = ""
+        if self.ccnroutes:
+            routes = map(lambda route: "ccndc add ccnx:/ %s" % route, 
+                self.ccnroutes.split("|"))
+            routes = " && " + " && ".join(routes)
+        self.command = "ccndstart %s" % routes
+
+        super(CCNxDaemon, self).start()
+            
+    def kill(self):
+        self._logger.info("Killing %s", self)
+
+        cmd = self._replace_paths("${SOURCES}/bin/ccndstop")
+        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 a815158..e1095ee 100644 (file)
@@ -684,6 +684,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
@@ -754,8 +755,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 09800a0..7b6e3f9 100644 (file)
@@ -22,6 +22,7 @@ NODEIFACE = "NodeInterface"
 TUNIFACE = "TunInterface"
 TAPIFACE = "TapInterface"
 APPLICATION = "Application"
+CCNXDAEMON = "CCNxDaemon"
 DEPENDENCY = "Dependency"
 NEPIDEPENDENCY = "NepiDependency"
 NS3DEPENDENCY = "NS3Dependency"
@@ -202,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)
@@ -323,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)
@@ -389,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)
@@ -696,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
     }),
@@ -1106,7 +1126,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,
@@ -1313,14 +1340,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, 
@@ -1328,11 +1356,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), 
@@ -1526,6 +1556,20 @@ 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"],
+            "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,