added a cleanProcessesAfter attribute to the linux::Node class, which defaults to...
[nepi.git] / src / nepi / resources / linux / node.py
index 7092a67..b0d63c9 100644 (file)
@@ -3,9 +3,8 @@
 #    Copyright (C) 2013 INRIA
 #
 #    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
+#    it under the terms of the GNU General Public License version 2 as
+#    published by the Free Software Foundation;
 #
 #    This program is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,7 +27,6 @@ import collections
 import os
 import random
 import re
-import socket
 import tempfile
 import time
 import threading
@@ -51,12 +49,12 @@ class OSType:
     """
     Supported flavors of Linux OS
     """
-    FEDORA_8 = "f8"
-    FEDORA_12 = "f12"
-    FEDORA_14 = "f14"
-    FEDORA = "fedora"
-    UBUNTU = "ubuntu"
-    DEBIAN = "debian"
+    DEBIAN = 1 
+    UBUNTU = 1 << 1 
+    FEDORA = 1 << 2
+    FEDORA_8 = 1 << 3 | FEDORA 
+    FEDORA_12 = 1 << 4 | FEDORA 
+    FEDORA_14 = 1 << 5 | FEDORA 
 
 @clsinit_copy
 class LinuxNode(ResourceManager):
@@ -145,7 +143,7 @@ class LinuxNode(ResourceManager):
     _rtype = "linux::Node"
     _help = "Controls Linux host machines ( either localhost or a host " \
             "that can be accessed using a SSH key)"
-    _backend_type = "linux"
+    _platform = "linux"
 
     @classmethod
     def _register_attributes(cls):
@@ -185,6 +183,13 @@ class LinuxNode(ResourceManager):
                 default = False,
                 flags = Flags.Design)
         
+        clean_processes_after = Attribute("cleanProcessesAfter", 
+                """Kill all running processes after starting experiment
+This might be dangerous when using user root""",
+                type = Types.Bool,
+                default = True,
+                flags = Flags.Design)
+        
         tear_down = Attribute("tearDown", "Bash script to be executed before " + \
                 "releasing the resource",
                 flags = Flags.Design)
@@ -208,6 +213,7 @@ class LinuxNode(ResourceManager):
         cls._register_attribute(clean_home)
         cls._register_attribute(clean_experiment)
         cls._register_attribute(clean_processes)
+        cls._register_attribute(clean_processes_after)
         cls._register_attribute(tear_down)
         cls._register_attribute(gateway_user)
         cls._register_attribute(gateway)
@@ -291,18 +297,18 @@ class LinuxNode(ResourceManager):
 
         out = self.get_os()
 
-        if out.find("Fedora release 8") == 0:
-            self._os = OSType.FEDORA_8
-        elif out.find("Fedora release 12") == 0:
-            self._os = OSType.FEDORA_12
-        elif out.find("Fedora release 14") == 0:
-            self._os = OSType.FEDORA_14
-        elif out.find("Fedora release") == 0:
-            self._os = OSType.FEDORA
-        elif out.find("Debian") == 0: 
+        if out.find("Debian") == 0: 
             self._os = OSType.DEBIAN
         elif out.find("Ubuntu") ==0:
             self._os = OSType.UBUNTU
+        elif out.find("Fedora release") == 0:
+            self._os = OSType.FEDORA
+            if out.find("Fedora release 8") == 0:
+                self._os = OSType.FEDORA_8
+            elif out.find("Fedora release 12") == 0:
+                self._os = OSType.FEDORA_12
+            elif out.find("Fedora release 14") == 0:
+                self._os = OSType.FEDORA_14
         else:
             msg = "Unsupported OS"
             self.error(msg, out)
@@ -329,12 +335,11 @@ class LinuxNode(ResourceManager):
 
     @property
     def use_deb(self):
-        return self.os in [OSType.DEBIAN, OSType.UBUNTU]
+        return (self.os & (OSType.DEBIAN|OSType.UBUNTU))
 
     @property
     def use_rpm(self):
-        return self.os in [OSType.FEDORA_12, OSType.FEDORA_14, OSType.FEDORA_8,
-                OSType.FEDORA]
+        return (self.os & OSType.FEDORA)
 
     @property
     def localhost(self):
@@ -369,18 +374,13 @@ class LinuxNode(ResourceManager):
 
         # Get Public IP address if possible
         if not self.get("ip"):
-            ip = None
-
-            if self.localhost:
-                ip = socket.gethostbyname(socket.gethostname())
-            else:
-                try:
-                    ip = socket.gethostbyname(self.get("hostname"))
-                except:
-                    msg = "DNS can not resolve hostname %s" % self.get("hostname") 
-                    self.debug(msg)
-
-            self.set("ip", ip)
+            try:
+                ip = sshfuncs.gethostbyname(self.get("hostname"))
+                self.set("ip", ip)
+            except:
+                if self.get("gateway") is None:
+                    msg = "Local DNS can not resolve hostname %s" % self.get("hostname") 
+                    self.error(msg)
 
         super(LinuxNode, self).do_provision()
 
@@ -414,7 +414,8 @@ class LinuxNode(ResourceManager):
         if tear_down:
             self.execute(tear_down)
 
-        self.clean_processes()
+        if self.get("cleanProcessesAfter"):
+            self.clean_processes()
 
         super(LinuxNode, self).do_release()
 
@@ -430,6 +431,7 @@ class LinuxNode(ResourceManager):
         
         if self.get("username") != 'root':
             cmd = ("sudo -S killall tcpdump || /bin/true ; " +
+                "sudo -S kill -9 $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; " +
                 "sudo -S killall -u %s || /bin/true ; " % self.get("username"))
         else:
             if self.state >= ResourceState.READY:
@@ -446,14 +448,14 @@ class LinuxNode(ResourceManager):
                     kill_pids = ' '.join(dict(kill_pids).keys())
 
                     cmd = ("killall tcpdump || /bin/true ; " +
-                        "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; " +
+                        "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; " +
                         "kill %s || /bin/true ; " % kill_pids)
                 else:
                     cmd = ("killall tcpdump || /bin/true ; " +
-                        "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; ")
+                        "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; ")
             else:
                 cmd = ("killall tcpdump || /bin/true ; " +
-                    "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; ")
+                    "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; ")
 
         (out, err), proc = self.execute(cmd, retry = 1, with_lock = True)
 
@@ -844,17 +846,18 @@ class LinuxNode(ResourceManager):
         return self.execute(cmd, with_lock = True)
         
     def run_and_wait(self, command, home, 
-            shfile = "cmd.sh",
-            env = None,
-            overwrite = True,
-            pidfile = "pidfile", 
-            ecodefile = "exitcode", 
-            stdin = None, 
-            stdout = "stdout", 
-            stderr = "stderr", 
-            sudo = False,
-            tty = False,
-            raise_on_error = True):
+            shfile="cmd.sh",
+            env=None,
+            overwrite=True,
+            wait_run=True,
+            pidfile="pidfile", 
+            ecodefile="exitcode", 
+            stdin=None, 
+            stdout="stdout", 
+            stderr="stderr", 
+            sudo=False,
+            tty=False,
+            raise_on_error=True):
         """
         Uploads the 'command' to a bash script in the host.
         Then runs the script detached in background in the host, and
@@ -893,25 +896,26 @@ class LinuxNode(ResourceManager):
                 pidfile = pidfile, 
                 raise_on_error = raise_on_error)
 
-        # wait until command finishes to execute
-        self.wait_run(pid, ppid)
-      
-        (eout, err), proc = self.check_errors(home,
-            ecodefile = ecodefile,
-            stderr = stderr)
+        if wait_run:
+            # wait until command finishes to execute
+            self.wait_run(pid, ppid)
+          
+            (eout, err), proc = self.check_errors(home,
+                ecodefile = ecodefile,
+                stderr = stderr)
 
-        # Out is what was written in the stderr file
-        if err:
-            msg = " Failed to run command '%s' " % command
-            self.error(msg, eout, err)
+            # Out is what was written in the stderr file
+            if err:
+                msg = " Failed to run command '%s' " % command
+                self.error(msg, eout, err)
 
-            if raise_on_error:
-                raise RuntimeError, msg
+                if raise_on_error:
+                    raise RuntimeError, msg
 
         (out, oerr), proc = self.check_output(home, stdout)
         
         return (out, err), proc
-
+        
     def exitcode(self, home, ecodefile = "exitcode"):
         """
         Get the exit code of an application.
@@ -935,10 +939,10 @@ class LinuxNode(ResourceManager):
         return ExitCode.ERROR
 
     def upload_command(self, command, 
-            shfile = "cmd.sh",
-            ecodefile = "exitcode",
-            overwrite = True,
-            env = None):
+            shfile="cmd.sh",
+            ecodefile="exitcode",
+            overwrite=True,
+            env=None):
         """ Saves the command as a bash script file in the remote host, and
         forces to save the exit code of the command execution to the ecodefile
         """
@@ -958,9 +962,9 @@ class LinuxNode(ResourceManager):
         # Add environ to command
         command = environ + command
 
-        return self.upload(command, shfile, text = True, overwrite = overwrite)
+        return self.upload(command, shfile, text=True, overwrite=overwrite)
 
-    def format_environment(self, env, inline = False):
+    def format_environment(self, env, inline=False):
         """ Formats the environment variables for a command to be executed
         either as an inline command
         (i.e. export PYTHONPATH=src/..; export LALAL= ..;python script.py) or