updated logging
[tests.git] / qaapi / qa / tests / boot_node.py
index 3c32232..f8109b9 100644 (file)
@@ -7,8 +7,10 @@ import time
 import tempfile
 import select
 import base64
+import traceback
 from Test import Test
 from qa import utils
+from qa.Nodes import Node, Nodes
 
 image_types = ['node-iso', 'node-usb', 'generic-iso', 'generic-usb']
 
@@ -29,74 +31,112 @@ class boot_node(Test):
         nodes = self.config.api.GetNodes(self.config.auth, [hostname], ['boot_state'])
         node = nodes[0]
         boot_state = node['boot_state']
-        if self.config.verbose:
-            utils.header("%(hostname)s boot_state is %(boot_state)s" % locals()) 
+        if True or self.config.verbose:
+            utils.header("%(hostname)s boot_state is %(boot_state)s" % locals(), False, self.config.logfile
             
-        if boot_state in ['boot', 'debug']:
+        if boot_state in ['boot']:
             self.exit = True
 
        if self.config.verbose:
            if boot_state in ['boot']:
-               utils.header("%(hostname)s correctly installed and booted" % locals())
+               utils.header("%(hostname)s correctly installed and booted" % locals(), False, self.config.logfile)
            else:
-               utils.header("%(hostname)s not fully booted" % locals())
+               utils.header("%(hostname)s not fully booted" % locals(), False, self.config.logfile)
         self.boot_state = boot_state
         return self.exit
         
     def console_nanny(self,console_states):
-        ready = select.select([],[self.stdout],[],1)[1]
+        #ready = select.select([],[self.stdout],[],1)[1]
         output = 0
-        if len(ready)>0:
+        if True or len(ready)>0:
             output = 1
-            line = self.stdout.readline()
-            for searchstring in console_states.keys():
-                result = line.find(searchstring)
+            retry = True
+            while retry:
+                try:
+                    lines = self.stdout.readlines()
+                    retry = False
+                except IOError, e:
+                    pass
+
+            #for searchstring in console_states.keys():
+            #    result = line.find(searchstring)
                 # if result... ret = console_states[searchstring]
-                break
+            #    break
                 # check result for whether we found it
 
             # for now just print it out
-            utils.header(line) 
+           for line in lines:
+                print line
+               utils.header(line, logfile = self.config.logfile) 
             # should be parsing for special strings that indicate whether
             # we've reached a particular state within the boot sequence
 
         return output
 
-    def call(self, hostname, image_type = 'node-iso', disk_size="4G", wait = 30):
-        # wait up to 30 minutes for a node to boot and install itself correctly
+    def call(self, plc_name, hostname, image_type = 'node-iso', disk_size="17G", wait = 30):
+
+        
+       # Get this nodes configuration 
+       node = self.config.get_node(hostname)
+       # Which plc does this node talk to 
+       plc = self.config.get_plc(plc_name)
+        api = plc.config.api
+        auth = plc.config.auth
+       path = node.get_path()
+       host = node['host']
+       homedir = node['homedir']
+       tmpdir = '/usr/tmp/'
+       bootimage_filename = "%(hostname)s-bootcd.iso" % locals()
+       diskimage_filename = "%(hostname)s-hda.img" % locals() 
+       bootimage = "%(homedir)s/%(bootimage_filename)s" % locals()
+       diskimage = "%(homedir)s/%(diskimage_filename)s" % locals() 
+       diskimage_path = "/%(path)s/%(diskimage_filename)s" % locals() 
+        bootimage_tmppath = "%(tmpdir)s/%(bootimage_filename)s" % locals()
+       bootimage_path = "%(path)s/%(bootimage_filename)s" % locals()
+       remote_bootimage_path = "%(homedir)s/%(bootimage_filename)s" % locals() 
+        
+       # wait up to 30 minutes for a node to boot and install itself correctly
         self.hostname = hostname
         self.totaltime = 60*60*wait
 
-       api = self.config.api
-       auth = self.config.auth
-       tdir = "/usr/tmp/"
-       
        # validate hostname
-       nodes = api.GetNodes(auth, [hostname], ['hostname'])
+       nodes = api.GetNodes(auth, [hostname], ['hostname', 'boot_state'])
        if not nodes:
-           raise Exception, "No such node %(hostname)s" % locals() 
-
-       bootimage = api.GetBootMedium(auth, hostname, image_type, '')
-       bootimage_path = '/%(tdir)s/%(hostname)s-bootcd.iso' % locals()
-
+           raise Exception, "%s not found at plc  %s" % (hostname, plc['name'])
+       node.update(nodes[0])
+
+       # try reinstalling the node if it is in debug state
+       if node['boot_state'] in ['dbg']:
+           if self.config.verbose:
+               utils.header("%(hostname)s is in debug state. Attempting a re-install" % locals(), logfile = self.config.logfiile)
+           api.UpdateNode(auth, node['node_id'], {'boot_state': 'rins'}) 
+       
+       # Create boot image
        if self.config.verbose:
-            utils.header("Creating bootcd for %(hostname)s at %(bootimage_path)s" % locals())  
-       # Create a temporary bootcd file
-       fp = open(bootimage_path, 'w')
-       fp.write(base64.b64decode(bootimage))
+            utils.header("Creating bootcd for %(hostname)s at %(bootimage_path)s" % locals(), logfile = self.config.logfile)   
+       nodeimage = api.GetBootMedium(auth, hostname, image_type, '', ['serial'])
+       fp = open(bootimage_tmppath, 'w')
+       fp.write(base64.b64decode(nodeimage))
        fp.close()
+
+       # Move the boot image to the nodes home directory
+       node.host_commands("mkdir -p %(homedir)s" % locals())
+       node.scp_to_host(bootimage_tmppath, "%(remote_bootimage_path)s" % locals())
+
+       # If node is vm (qemu) try installing kqemu
+       node.host_commands("yum -y install kqemu", False)
+       node.host_commands("modprobe kqemu")
        
-       # Create a temporary disk image
-       diskimage_path = "/%(tdir)s/%(hostname)s-hda.img" % locals() 
-       qemu_img_cmd = "qemu-img create -f qcow2 %(diskimage_path)s %(disk_size)s" % locals()
-       (stdin, stdout, stderr) = os.popen3(qemu_img_cmd)
-       self.errors = stderr.readlines()
-       if self.errors: 
-           raise Exception, "Unable to create disk image\n" + \
-                           "\n".join(self.errors)
+       # Create a temporary disk image if it doesnt already exist or we are reinstalling
+       img_check_cmd =  "ls -ld %(diskimage)s" % locals()
+       (status, output) = node.host_commands(img_check_cmd, False)
+       if status != 0 or node['boot_state'] in ['rins', 'inst']:
+           qemu_img_cmd = "qemu-img create -f qcow2 %(diskimage)s %(disk_size)s" % locals()
+           node.host_commands(qemu_img_cmd)
 
+       
        if self.config.verbose:
-            utils.header("Booting %(hostname)s" % locals())
+            utils.header("Booting %(hostname)s" % locals(), logfile = self.config.logfile)
 
        # Attempt to boot this node image
 
@@ -104,10 +144,10 @@ class boot_node(Test):
         tmp = tempfile.mkstemp(".pid","qemu_")
         pidfile=tmp[1]
         os.unlink(pidfile)
-        os.close(tmp[0])
-
+        
+       os.close(tmp[0])
         # boot node with ramsize memory
-        ramsize=400
+        ramsize=1024
 
         # always use the 64 bit version of qemu, as this will work on both 32 & 64 bit host kernels
         bootcmd = "qemu-system-x86_64" 
@@ -117,30 +157,53 @@ class boot_node(Test):
         bootcmd = bootcmd + " -m %(ramsize)s" % locals()
         # uniprocessor only
         bootcmd = bootcmd + " -smp 1"
+       # redirect incomming tcp connections on specified port to guest node
+       if 'redir_ssh_port' in node and node['redir_ssh_port']:
+           port = node['redir_ssh_port']
+           ip = node['nodenetworks'][0]['ip']
+           bootcmd = bootcmd + " -redir tcp:%(port)s:%(ip)s:22" % locals() 
         # no graphics support -> assume we are booting via serial console
         bootcmd = bootcmd + " -nographic"
         # boot from the supplied cdrom iso file
         bootcmd = bootcmd + " -boot d"
-        bootcmd = bootcmd + " -cdrom %(bootimage_path)s" % locals()
+        bootcmd = bootcmd + " -cdrom %(bootimage)s" % locals()
         # hard disk image to use for the node
-        bootcmd = bootcmd + " %(diskimage_path)s" % locals()
-        # launch qemu
-       (self.stdin, self.stdout, self.stderr) = os.popen3(bootcmd)
-
-        # wait for qemu to start up
-        time.sleep(3)
+        bootcmd = bootcmd + " %(diskimage)s" % locals()
+       # redirect stdout, stderr to logfile
+       bootcmd = bootcmd + " 2>&1 >> %s " % (node.logfile.filename)
+        
+       # kill any old qemu processes for this node
+       pid_cmd = "ps -elfy | grep qemu | grep %(hostname)s | awk '{print$3}'" % locals()
+       (status, output) = node.host_commands(pid_cmd)
+       pids = " ".join(output.split("\n")).strip() 
+       if pids:
+           kill_cmd = "kill %(pids)s" % locals()  
+           (status, output) = node.host_commands(kill_cmd)
+       
+       time.sleep(2)
+       # Rotate node's logfile
+       node.rotate_logfile()
+       
+       # launch qemu
+       (self.stdin, self.stdout, self.stderr) = node.host_popen3(bootcmd)
         
+       # wait for qemu to start up
+        time.sleep(5)
         # get qemu's pid from its pidfile (crappy approach)
-        fp = file(pidfile)
-        buf=fp.read()
-        self.pid=int(buf)
-        fp.close()
-        os.unlink(pidfile)
-
-        # loop until the node is either fully booted, some error
+       pid_cmd = "cat %(pidfile)s" % locals()
+       (staus, output)  = node.host_commands(pid_cmd)
+       self.pid = output.strip()   
+        #fp = file(pidfile)
+        #buf=fp.read()
+        #self.pid=int(buf)
+        #fp.close()
+        #os.unlink(pidfile)
+        
+       # loop until the node is either fully booted, some error
         # occured, or we've reached our totaltime out
         def catch(sig, frame):
             self.totaltime = self.totaltime -1
+           utils.header("beep %d\n" %self.totaltime, False, logfile = self.config.logfile )
             total = self.totaltime
             if (total == 0) or \
                    (((total % 60)==0) and self.state_nanny()):
@@ -154,12 +217,14 @@ class boot_node(Test):
             signal.alarm(1)
             self.exit = False
 
-            console_states = {"login:":1}
+            #console_states = {"login:":1}
             while not self.exit:
-                try:
-                    self.console_nanny(console_states)
-                except: # need a better way to catch exceptions
-                    pass
+               pass
+                #try:
+                #    self.console_nanny(console_states)
+                #except: # need a better way to catch exceptions
+                #    traceback.print_exc()
+                #    pass
 
             signal.alarm(0)
         except: