fine-grain & brute force qemu kill (kill_qemus and kill_all_qemus)
Thierry Parmentelat [Thu, 14 Feb 2008 12:39:46 +0000 (12:39 +0000)]
system/TestBox.py
system/TestMain.py
system/TestNode.py
system/TestPlc.py
system/qemu_kill.sh [new file with mode: 0755]
system/utils.py

index 088922a..63300ed 100644 (file)
@@ -14,10 +14,23 @@ class TestBox:
             return utils.system(command)
         else:
             if self.key:
-                to_run="ssh -i %s.rsa %s %s"%(self.key,self.hostname,command)
+                to_run="ssh -i %s.rsa %s %s"%(self.key,self.hostname,
+                                              utils.backslash_shell_specials(command))
             else:
-                to_run="ssh %s %s"%(self.hostname,command)
+                to_run="ssh %s %s"%(self.hostname,
+                                    utils.backslash_shell_specials(command))
+            return utils.system(to_run)
+        
+    def copy (self,local_file):
+        if self.hostname == "localhost":
+            return 0
+        else:
+            if self.key:
+                to_run="scp -i %s.rsa %s %s:"%(self.key,local_file,self.hostname)
+            else:
+                to_run="scp %s %s:"%(local_file,self.hostname)
             return utils.system(to_run)
         
     def kill_all_qemus(self):
         self.run("killall qemu")
+
index 9d7753f..b06f14a 100755 (executable)
@@ -21,10 +21,13 @@ class TestMain:
                      'clear_ssh_config','store_keys', 'initscripts', 
                      'sites', 'nodes', 'slices', 
                      'bootcd', 'nodegroups', 
-                     'start_nodes', 'standby_4','nodes_booted','standby_6','nodes_ssh', 'check_slices' ]
+                     'kill_all_qemus', 'start_nodes', 
+                     'standby_4', 'nodes_booted',
+                     'standby_6','nodes_ssh', 'check_slices',
+                     'check_tcp' ]
     other_steps = [ 'fresh_install', 'stop', 
                     'clean_sites', 'clean_nodes', 'clean_slices', 'clean_keys',
-                    'stop_nodes' ,  'db_dump' , 'db_restore',
+                    'kill_qemus', 'stop_nodes' ,  'db_dump' , 'db_restore',
                     'standby_1 through 20',
                     ]
     default_build_url = "http://svn.planet-lab.org/svn/build/trunk"
@@ -208,15 +211,15 @@ steps refer to a method in TestPlc or to a step_* module
                         utils.header("Running step %s on plc %s"%(stepname,plcname))
                         step_result = method(obj,self.options)
                         if step_result:
-                            utils.header('Successful step %s on %s'%(stepname,plcname))
+                            utils.header('********** SUCCESSFUL step %s on %s'%(stepname,plcname))
                         else:
                             overall_result = False
                             spec['disabled'] = True
-                            utils.header('Step %s on %s FAILED - discarding that plc from further steps'%(stepname,plcname))
+                            utils.header('********** Step %s on %s FAILED - discarding that plc from further steps'%(stepname,plcname))
                     except:
                         overall_result=False
                         spec['disabled'] = True
-                        utils.header ('Step %s on plc %s FAILED (exception) - discarding this plc from further steps'%(stepname,plcname))
+                        utils.header ('********** Step %s on plc %s FAILED (exception) - discarding this plc from further steps'%(stepname,plcname))
                         traceback.print_exc()
         return overall_result
 
index df6eb56..993594b 100644 (file)
@@ -169,19 +169,10 @@ class TestNode:
         self.test_plc.run_in_host("ssh root@%s ~/%s/%s/env-qemu start"%(host_box, path, dest_dir ))
         self.test_plc.run_in_host("ssh  root@%s DISPLAY=%s  ~/%s/start-qemu-node %s & "%( host_box, display, dest_dir, dest_dir))
         
-# needs rework - node_spec is a local atribute, no need to pass it
-# the code that stops ALL qemu instance on a given box has moved to TestBox
-# this code below should only kill THE qemu instance that goes with that particular hostname
-#    def stop_qemu(self,node_spec):
-#        try:
-#            if self.is_qemu_model(node_spec['node_fields']['model']):
-#                hostname=node_spec['node_fields']['hostname']
-#                host_box=node_spec['host_box']
-#                self.test_plc.run_in_host('ssh root@%s  killall qemu'%host_box)
-#                utils.header('Stoping qemu emulation of %s on the host machine %s and Restoring the initial network'
-#                             %(hostname,host_box))
-#                self.test_plc.run_in_host("ssh root@%s ~/qemu-%s/env-qemu stop "%(host_box, hostname ))
-#            return True
-#        except Exception,e :
-#            print str(e)
-#            return False
+    def kill_qemu (self):
+        hostname = self.name()
+        # kill the right processes 
+        command="kill $(ps $(pgrep qemu) | grep %s | awk '{print $1;}')"%hostname
+        utils.header("Stopping qemu for host %s on box %s"%(hostname,self.host_box()))
+        TestBox(self.host_box()).run(command)
+        return True
index 4694d1c..cb3a11b 100644 (file)
@@ -16,17 +16,6 @@ from TestKey import TestKey
 from TestSlice import TestSlice
 from TestBox import TestBox
 
-# inserts a backslash before each occurence of the following chars
-# \ " ' < > & | ; ( ) $ * ~ 
-def backslash_shell_specials (command):
-    result=''
-    for char in command:
-        if char in "\\\"'<>&|;()$*~":
-            result +='\\'+char
-        else:
-            result +=char
-    return result
-
 # step methods must take (self, options) and return a boolean
 
 def standby(minutes):
@@ -76,14 +65,14 @@ class TestPlc:
         if self.vserver:
             return "vserver %s exec %s"%(self.vservername,command)
         else:
-            return "chroot /plc/root %s"%backslash_shell_specials(command)
+            return "chroot /plc/root %s"%utils.backslash_shell_specials(command)
 
     # command gets run on the right box
     def to_host(self,command):
         if self.is_local():
             return command
         else:
-            return "ssh %s %s"%(self.plc_spec['hostname'],backslash_shell_specials(command))
+            return "ssh %s %s"%(self.plc_spec['hostname'],utils.backslash_shell_specials(command))
 
     def full_command(self,command):
         return self.to_host(self.host_to_guest(command))
@@ -143,34 +132,44 @@ class TestPlc:
 
     # all different hostboxes used in this plc
     def gather_hostBoxes(self):
-        # maps on sites and nodes, return [ (host_box,hostname) ]
+        # maps on sites and nodes, return [ (host_box,test_node) ]
         tuples=[]
         for site_spec in self.plc_spec['sites']:
             test_site = TestSite (self,site_spec)
             for node_spec in site_spec['nodes']:
                 test_node = TestNode (self, test_site, node_spec)
                 if not test_node.is_real():
-                    tuples.append( (test_node.host_box(),node_spec['node_fields']['hostname']) )
+                    tuples.append( (test_node.host_box(),test_node) )
         # transform into a dict { 'host_box' -> [ hostnames .. ] }
         result = {}
-        for (box,hostname) in tuples:
+        for (box,node) in tuples:
             if not result.has_key(box):
-                result[box]=[hostname]
+                result[box]=[node]
             else:
-                result[box].append(hostname)
+                result[box].append(node)
         return result
                     
     # a step for checking this stuff
     def showboxes (self,options):
         print 'showboxes'
-        for (box,hosts) in self.gather_hostBoxes().iteritems():
-            print box,":"," + ".join(hosts)
+        for (box,nodes) in self.gather_hostBoxes().iteritems():
+            print box,":"," + ".join( [ node.name() for node in nodes ] )
         return True
 
-    def kill_all_qemus(self):
-        for (box,hosts) in self.gather_hostBoxes().iteritems():
+    # make this a valid step
+    def kill_all_qemus(self,options):
+        for (box,nodes) in self.gather_hostBoxes().iteritems():
             # this is the brute force version, kill all qemus on that host box
             TestBox(box).kill_all_qemus()
+        return True
+
+    # kill only the right qemus
+    def kill_qemus(self,options):
+        for (box,nodes) in self.gather_hostBoxes().iteritems():
+            # the fine-grain version
+            for node in nodes:
+                node.kill_qemu()
+        return True
 
     def clear_ssh_config (self,options):
         # install local ssh_config file as root's .ssh/config - ssh should be quiet
@@ -528,7 +527,6 @@ class TestPlc:
         return status
     
     def start_nodes (self, options):
-        self.kill_all_qemus()
         utils.header("Starting  nodes")
         for site_spec in self.plc_spec['sites']:
             TestSite(self,site_spec).start_nodes (options)
@@ -538,6 +536,10 @@ class TestPlc:
         self.kill_all_qemus()
         return True
 
+    def check_tcp (self, options):
+        print 'check_tcp not yet implemented'
+        return True
+
     # returns the filename to use for sql dump/restore, using options.dbname if set
     def dbfile (self, database, options):
         # uses options.dbname if it is found
diff --git a/system/qemu_kill.sh b/system/qemu_kill.sh
new file mode 100755 (executable)
index 0000000..ad1a01f
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+COMMAND=$(basename $0)
+
+hostname=$1; shift
+pids="$(ps $(pgrep qemu) | grep $hostname | awk '{print $1;}')"
+
+if [ -z "$pids" ] ; then
+    echo $COMMAND: no qemu instance for $hostname found on $(hostname)
+else
+    echo Killing $pids
+    kill $pids
+    sleep 2
+    if [ -n "$(ps $pids)" ] ; then
+       echo Killing -9 $pids
+       kill -9 $pids
+    fi
+    echo Done
+fi
index fab6844..4468b20 100644 (file)
@@ -36,3 +36,15 @@ def check_ping (hostname):
     command="ping -c 1 %s 1 %s"%(ping_timeout_option,hostname)
     (status,output) = commands.getstatusoutput(command)
     return status == 0
+
+# inserts a backslash before each occurence of the following chars
+# \ " ' < > & | ; ( ) $ * ~ 
+def backslash_shell_specials (command):
+    result=''
+    for char in command:
+        if char in "\\\"'<>&|;()$*~":
+            result +='\\'+char
+        else:
+            result +=char
+    return result
+