+ Implemented option to cleanup directories on PlanetLab slivers.
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Sun, 6 May 2012 14:18:37 +0000 (16:18 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Sun, 6 May 2012 14:18:37 +0000 (16:18 +0200)
examples/ccnx/ccnx-0.6.0rc3.tar.gz [new file with mode: 0644]
examples/ccnx/planetlab_ccnx_unicast.py
src/nepi/testbeds/planetlab/application.py
src/nepi/testbeds/planetlab/execute.py
src/nepi/testbeds/planetlab/metadata.py
src/nepi/testbeds/planetlab/node.py

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
index 3b5a673..39c4489 100644 (file)
@@ -46,8 +46,12 @@ def create_slice_desc(slicename, plc_host, pl_user, pl_pwd, pl_ssh_key,
     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("dedicatedSlice", True)
+    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
  
@@ -63,6 +67,17 @@ def create_node(hostname, pl_inet, slice_desc):
 
 def create_ccnd(pl_node, 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
     routes = "|".join(map(lambda route: "udp {#[iface_%s].addr[0].[Address]#}" % route, routes))
     # Add multicast ccn routes 
@@ -177,7 +192,7 @@ if __name__ == '__main__':
     default_hostnames = ['openlab02.pl.sophia.inria.fr',
                  'ple4.ipv6.lip6.fr',
                  'planetlab2.di.unito.it',
-                 'merkur.planetlab.haw-hamburg.de',
+                 #'merkur.planetlab.haw-hamburg.de',
                  'planetlab1.cs.uit.no',
                  'planetlab3.cs.st-andrews.ac.uk',
                  'planetlab2.cs.uoi.gr',
index 53592ec..da4748a 100644 (file)
@@ -567,7 +567,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(
@@ -1107,41 +1107,62 @@ class CCNxDaemon(Application):
         # Attributes
         self.ccnroutes = None
         self.ccnsources = None
+        self.ccnxversion = "ccnx-0.6.0"
         
-        self.default_ccnx_sources = "http://www.ccnx.org/releases/ccnx-0.5.1.tar.gz"
+        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.default_build = (
+        self.ccnx_0_5_1_build = (
             " ( "
             "  cd .. && "
-            "  test -d ccnx-src/build/bin "
+            "  test -d ccnx-0.5.1-src/build/bin "
             " ) || ( "
                 # Not working, rebuild
                 "("
-                     " mkdir -p ccnx-src && "
-                     " ( %(not_custom_source)s &&"
-                     " wget -q -c -O ccnx-src.tar.gz %(ccnx_source_url)s &&"
-                     " tar xf ccnx-src.tar.gz --strip-components=1 -C ccnx-src "
-                     " ) || ( "
-                     " tar xf %(user_ccnx_tar)s --strip-components=1 -C ccnx-src "
-                     " ) "
+                     " 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-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.default_install = (
+        self.ccnx_0_6_0_build = (
             " ( "
             "  cd .. && "
-            "  test -d ${SOURCES}/bin "
+            "  test -d ccnx-0.6.0-src/build/bin "
             " ) || ( "
-            "  test -d ${BUILD}/ccnx-src/build/bin && "
-            "  cp -r ${BUILD}/ccnx-src/build/bin ${SOURCES}"
+                # 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}"
             " )"
         )
 
@@ -1149,22 +1170,17 @@ class CCNxDaemon(Application):
 
     def setup(self):
         # setting ccn sources
-        not_custom_source = "true"
-        sources = ""
-        if self.ccnsources:
-            self.sources = self.ccnsources
-            sources = "${SOURCES}/%s" % os.path.basename(self.ccnsources)
-            not_custom_source = "false"
-
         if not self.build:
-            self.build = self.default_build  % dict(
-                     ccnx_source_url = server.shell_escape(self.default_ccnx_sources),
-                     not_custom_source = server.shell_escape(not_custom_source),
-                     user_ccnx_tar = sources
-                )
-        
+            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:
-            self.install = self.default_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()
 
index e1095ee..467d9fe 100644 (file)
@@ -143,8 +143,10 @@ 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:
@@ -737,7 +739,8 @@ class TestbedController(testbed_impl.TestbedController):
     def _make_node(self, parameters):
         args = dict({'sliceapi': self.sliceapi})
         node = self._make_generic(parameters, self._node.Node, **args)
-        node.enable_cleanup = self.dedicatedSlice
+        node.enable_proc_cleanup = self.cleanProc
+        node.enable_home_cleanup = self.cleanHome
         return node
 
     def _make_node_iface(self, parameters):
index 7c7c530..39f506d 100644 (file)
@@ -1187,6 +1187,16 @@ 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,
+            }),
     "build": dict({
                 "name": "build",
                 "help": "Build commands to execute after deploying the sources. "
@@ -1573,7 +1583,8 @@ factories_info = dict({
             "status_function": status_application,
             "stop_function": stop_application,
             "configure_function": configure_application,
-            "box_attributes": ["ccnroutes", "ccnsources", "build", "install"],
+            "box_attributes": ["ccnroutes", "ccnsources", "build", 
+                "install", "ccnxversion", "sources"],
             "connector_types": ["node"],
             "traces": ["stdout", "stderr", "buildlog", "output"],
             "tags": [tags.APPLICATION],
@@ -1772,16 +1783,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 5275600..41205e5 100644 (file)
@@ -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
@@ -497,9 +498,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:
@@ -534,8 +537,10 @@ 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:
@@ -543,12 +548,12 @@ class Node(object):
             import util
             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 ; "
@@ -577,7 +582,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: