Unit tests for linux_node.py
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 12 Nov 2012 17:39:47 +0000 (18:39 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 12 Nov 2012 17:39:47 +0000 (18:39 +0100)
src/neco/resources/base/linux_node.py
src/neco/util/sshfuncs.py
test/resources/base/linux_node.py [new file with mode: 0644]
test/util/plot.py

index e0ec18b..b763b95 100644 (file)
@@ -36,60 +36,31 @@ class LinuxNode(Resource):
         out = self.execute("cat /etc/issue")
 
         if out.find("Fedora") == 0:
-            self._pm = "yum -y "
+            self._pm = "yum"
         elif out.find("Debian") == 0 or out.find("Ubuntu") ==0:
-            self._pm = "apt-get -y "
+            self._pm = "apt-get"
         else:
             msg = "Can't resolve package management system. Unknown OS."
             self._logger.error(msg)
             raise RuntimeError(msg)
 
         return self._pm
-    
-    def execute(self, command,
-            agent = True,
-            sudo = False,
-            stdin = "", 
-            tty = False,
-            timeout = None,
-            retry = 0,
-            err_on_timeout = True,
-            connect_timeout = 30,
-            persistent = True):
-        """ Notice that this invocation will block until the
-        execution finishes. If this is not the desired behavior,
-        use 'run' instead."""
-        (out, err), proc = eintr_retry(rexec)(
-                command, 
-                self.host or self.ip, 
-                self.user,
-                port = self.port, 
-                agent = agent,
-                sudo = sudo,
-                stdin = stdin, 
-                identity_file = self.identity_file,
-                tty = tty,
-                timeout = timeout,
-                retry = retry,
-                err_on_timeout = err_on_timeout,
-                connect_timeout = connect_timeout,
-                persistent = persistent)
 
-        if proc.wait():
-            msg = "Failed to execute command %s at node %s: %s %s" % \
-                    (command, self.host or self.ip, out, err,)
-            self._logger.warn(msg)
-            raise RuntimeError(msg)
+    def install(self, packages):
+        if not isinstance(packages, list):
+            packages = [packages]
 
-        return out
+        for p in packages:
+            self.execute("%s -y install %s" % (self.pm, p), sudo = True, 
+                    tty = True)
 
-    def package_install(self, dependencies):
-        if not isinstance(dependencies, list):
-            dependencies = [dependencies]
+    def uninstall(self, packages):
+        if not isinstance(packages, list):
+            packages = [packages]
 
-        for d in dependencies:
-            self.execute("%s install %s" % (self.pm, d), sudo = True, 
-                    tty2 = True)
+        for p in packages:
+            self.execute("%s -y remove %s" % (self.pm, p), sudo = True, 
+                    tty = True)
 
     def upload(self, src, dst):
         if not os.path.isfile(src):
@@ -130,11 +101,7 @@ class LinuxNode(Resource):
 
     def mkdir(self, path, clean = True):
         if clean:
-            self.execute(
-                "rm -rf %s" % path,
-                timeout = 120,
-                retry = 3
-                )
+            self.rmdir(path)
 
         self.execute(
             "mkdir -p %s" % path,
@@ -142,6 +109,50 @@ class LinuxNode(Resource):
             retry = 3
             )
 
+    def rmdir(self, path):
+        self.execute(
+            "rm -rf %s" % path,
+            timeout = 120,
+            retry = 3
+            )
+
+    def execute(self, command,
+            agent = True,
+            sudo = False,
+            stdin = "", 
+            tty = False,
+            timeout = None,
+            retry = 0,
+            err_on_timeout = True,
+            connect_timeout = 30,
+            persistent = True):
+        """ Notice that this invocation will block until the
+        execution finishes. If this is not the desired behavior,
+        use 'run' instead."""
+        (out, err), proc = eintr_retry(rexec)(
+                command, 
+                self.host or self.ip, 
+                self.user,
+                port = self.port, 
+                agent = agent,
+                sudo = sudo,
+                stdin = stdin, 
+                identity_file = self.identity_file,
+                tty = tty,
+                timeout = timeout,
+                retry = retry,
+                err_on_timeout = err_on_timeout,
+                connect_timeout = connect_timeout,
+                persistent = persistent)
+
+        if proc.wait():
+            msg = "Failed to execute command %s at node %s: %s %s" % \
+                    (command, self.host or self.ip, out, err,)
+            self._logger.warn(msg)
+            raise RuntimeError(msg)
+
+        return out
+
     def run(self, command, home, 
             stdin = None, 
             stdout = 'stdout', 
index 347056f..872143d 100644 (file)
@@ -118,7 +118,6 @@ def rexec(command, host, user,
         stdin = "", 
         identity_file = None,
         tty = False,
-        tty2 = False,
         timeout = None,
         retry = 0,
         err_on_timeout = True,
@@ -153,9 +152,9 @@ def rexec(command, host, user,
         args.extend(('-i', identity_file))
     if tty:
         args.append('-t')
-    elif tty2:
-        args.append('-t')
-        args.append('-t')
+        if sudo:
+            args.append('-t')
+
     if sudo:
         command = "sudo " + command
     args.append(command)
@@ -582,10 +581,7 @@ def rkill(pid, ppid,
         Nothing, should have killed the process
     """
     
-    if sudo:
-        subkill = "$(ps --ppid %(pid)d -o pid h)" % { 'pid' : pid }
-    else:
-        subkill = ""
+    subkill = "$(ps --ppid %(pid)d -o pid h)" % { 'pid' : pid }
     cmd = """
 SUBKILL="%(subkill)s" ;
 %(sudo)s kill -- -%(pid)d $SUBKILL || /bin/true
diff --git a/test/resources/base/linux_node.py b/test/resources/base/linux_node.py
new file mode 100644 (file)
index 0000000..159c9f4
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+from neco.resources.base.linux_node import LinuxNode
+from neco.design.box import Box
+from neco.util.sshfuncs import RUNNING, FINISHED
+
+import os.path
+import time
+import unittest
+
+class DummyEC(object):
+    pass
+
+class LinuxBoxTestCase(unittest.TestCase):
+    def test_execute(self):
+        box = Box()
+        ec = DummyEC()
+
+        node = LinuxNode(box, ec)
+        node.host = 'nepi2.pl.sophia.inria.fr'
+        node.user = 'inria_nepi'
+
+        self.assertEquals(node.pm, "yum")
+        self.assertTrue(node.is_alive())
+
+        command = "ping -qc3 nepi5.pl.sophia.inria.fr"
+        out = node.execute(command)
+
+        expected = """3 packets transmitted, 3 received, 0% packet loss"""
+
+        self.assertTrue(out.find(expected) > 0)
+
+    def test_run(self):
+        box = Box()
+        ec = DummyEC()
+
+        node = LinuxNode(box, ec)
+        node.host = 'nepi2.pl.sophia.inria.fr'
+        node.user = 'inria_nepi'
+
+        home = '${HOME}/test-app'
+        node.mkdir(home, clean = True)
+        
+        command = "ping nepi5.pl.sophia.inria.fr"
+        dst = os.path.join(home, "app.sh")
+        node.upload(command, dst)
+        
+        cmd = "bash ./app.sh"
+        node.run(cmd, home)
+        pid, ppid = node.checkpid(home)
+
+        status = node.status(pid, ppid)
+        self.assertTrue(status, RUNNING)
+
+        node.kill(pid, ppid)
+        status = node.status(pid, ppid)
+        self.assertTrue(status, FINISHED)
+
+        node.rmdir(home)
+
+    def test_install(self):
+        box = Box()
+        ec = DummyEC()
+
+        node = LinuxNode(box, ec)
+        node.host = 'nepi2.pl.sophia.inria.fr'
+        node.user = 'inria_nepi'
+
+        self.assertEquals(node.pm, "yum")
+        self.assertTrue(node.is_alive())
+
+        home = '${HOME}/test-app'
+        node.mkdir(home, clean = True)
+
+        prog = """#include <stdio.h>
+
+int
+main (void)
+{
+    printf ("Hello, world!\\n");
+    return 0;
+}
+"""
+        dst = os.path.join(home, "hello.c")
+        node.upload(prog, dst)
+
+        node.install('gcc')
+
+        command = "cd ${HOME}/test-app; gcc -Wall hello.c -o hello"
+        out = node.execute(command)
+
+        command = "${HOME}/test-app/hello"
+        out = node.execute(command)
+
+        self.assertEquals(out, "Hello, world!\n")
+
+        node.uninstall('gcc')
+        node.rmdir(home)
+
+if __name__ == '__main__':
+    unittest.main()
+
index 6c20da6..20ae511 100755 (executable)
@@ -8,6 +8,8 @@ import unittest
 
 class BoxPlotTestCase(unittest.TestCase):
     def xtest_plot(self):
+        """ XXX: This test is interactive, it will open an evince instance,
+        so it should not run automatically """
         node1 = Box(label="node1")
         ping1 = Box(label="ping")
         mobility1 = Box(label="mob1")