adding ccnx tree topology streamming over Internet example
[nepi.git] / src / nepi / testbeds / planetlab / rspawn.py
index 6004462..8be8ac5 100644 (file)
@@ -1,6 +1,7 @@
 # Utility library for spawning remote asynchronous tasks
 from nepi.util import server
 import getpass
+import logging
 
 class STDOUT: 
     """
@@ -26,7 +27,7 @@ class NOT_STARTED:
 def remote_spawn(command, pidfile, stdout='/dev/null', stderr=STDOUT, stdin='/dev/null', home=None, create_home=False, sudo=False,
         host = None, port = None, user = None, agent = None, 
         ident_key = None, server_key = None,
-        tty = False):
+        tty = False, hostip = None):
     """
     Spawn a remote command such that it will continue working asynchronously.
     
@@ -80,6 +81,7 @@ def remote_spawn(command, pidfile, stdout='/dev/null', stderr=STDOUT, stdin='/de
             'gohome' : 'cd %s ; ' % (server.shell_escape(home),) if home else '',
             'create' : 'mkdir -p %s ; ' % (server.shell_escape,) if create_home else '',
         }
+
     (out,err),proc = server.popen_ssh_command(
         cmd,
         host = host,
@@ -88,17 +90,19 @@ def remote_spawn(command, pidfile, stdout='/dev/null', stderr=STDOUT, stdin='/de
         agent = agent,
         ident_key = ident_key,
         server_key = server_key,
-        tty = tty 
+        tty = tty ,
+        hostip = hostip
         )
     
     if proc.wait():
-        raise RuntimeError, "Failed to set up application: %s %s" % (out,err,)
+        raise RuntimeError, "Failed to set up application on host %s: %s %s" % (host, out,err,)
 
     return (out,err),proc
 
+@server.eintr_retry
 def remote_check_pid(pidfile,
         host = None, port = None, user = None, agent = None, 
-        ident_key = None, server_key = None):
+        ident_key = None, server_key = None, hostip = None):
     """
     Check the pidfile of a process spawned with remote_spawn.
     
@@ -122,7 +126,8 @@ def remote_check_pid(pidfile,
         user = user,
         agent = agent,
         ident_key = ident_key,
-        server_key = server_key
+        server_key = server_key,
+        hostip = hostip
         )
         
     if proc.wait():
@@ -136,9 +141,10 @@ def remote_check_pid(pidfile,
             return None
 
 
+@server.eintr_retry
 def remote_status(pid, ppid, 
         host = None, port = None, user = None, agent = None, 
-        ident_key = None, server_key = None):
+        ident_key = None, server_key = None, hostip = None):
     """
     Check the status of a process spawned with remote_spawn.
     
@@ -153,7 +159,7 @@ def remote_status(pid, ppid,
     """
 
     (out,err),proc = server.popen_ssh_command(
-        "ps --ppid %(ppid)d -o pid | grep -c %(pid)d ; true" % {
+        "ps --pid %(pid)d -o pid | grep -c %(pid)d ; true" % {
             'ppid' : ppid,
             'pid' : pid,
         },
@@ -162,7 +168,8 @@ def remote_status(pid, ppid,
         user = user,
         agent = agent,
         ident_key = ident_key,
-        server_key = server_key
+        server_key = server_key,
+        hostip = hostip
         )
     
     if proc.wait():
@@ -173,14 +180,18 @@ def remote_status(pid, ppid,
         try:
             status = bool(int(out.strip()))
         except:
+            if out or err:
+                logging.warn("Error checking remote status:\n%s%s\n", out, err)
             # Ignore, many ways to fail that don't matter that much
             return NOT_STARTED
     return RUNNING if status else FINISHED
     
 
+@server.eintr_retry
 def remote_kill(pid, ppid, sudo = False,
         host = None, port = None, user = None, agent = None, 
-        ident_key = None, server_key = None):
+        ident_key = None, server_key = None, hostip = None,
+        nowait = False):
     """
     Kill a process spawned with remote_spawn.
     
@@ -198,35 +209,50 @@ def remote_kill(pid, ppid, sudo = False,
         
         Nothing, should have killed the process
     """
-
-    (out,err),proc = server.popen_ssh_command(
-        """
-%(sudo)s kill %(pid)d
-for x in 1 2 3 4 5 6 7 8 9 0 ; do 
-    sleep 0.1 
-    if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` == `0` ]; then
+    
+    if sudo:
+        subkill = "$(ps --ppid %(pid)d -o pid h)" % { 'pid' : pid }
+    else:
+        subkill = ""
+    cmd = """
+SUBKILL="%(subkill)s" ;
+%(sudo)s kill -- -%(pid)d $SUBKILL || /bin/true
+%(sudo)s kill %(pid)d $SUBKILL || /bin/true
+for x in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do 
+    sleep 0.2 
+    if [ `ps --pid %(pid)d -o pid | grep -c %(pid)d` == '0' ]; then
         break
+    else
+        %(sudo)s kill -- -%(pid)d $SUBKILL || /bin/true
+        %(sudo)s kill %(pid)d $SUBKILL || /bin/true
     fi
-    sleep 0.9
+    sleep 1.8
 done
-if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` != `0` ]; then
-    %(sudo)s kill -9 %(pid)d %(ppid)d
+if [ `ps --pid %(pid)d -o pid | grep -c %(pid)d` != '0' ]; then
+    %(sudo)s kill -9 -- -%(pid)d $SUBKILL || /bin/true
+    %(sudo)s kill -9 %(pid)d $SUBKILL || /bin/true
 fi
-""" % {
+"""
+    if nowait:
+        cmd = "( %s ) >/dev/null 2>/dev/null </dev/null &" % (cmd,)
+
+    (out,err),proc = server.popen_ssh_command(
+        cmd % {
             'ppid' : ppid,
             'pid' : pid,
-            'sudo' : 'sudo -S' if sudo else ''
+            'sudo' : 'sudo -S' if sudo else '',
+            'subkill' : subkill,
         },
         host = host,
         port = port,
         user = user,
         agent = agent,
         ident_key = ident_key,
-        server_key = server_key
+        server_key = server_key,
+        hostip = hostip
         )
     
     # wait, don't leave zombies around
     proc.wait()
-