13 from qa.Nodes import Node, Nodes
15 image_types = ['node-iso', 'node-usb', 'generic-iso', 'generic-usb']
19 os.kill(pid, signal.SIGKILL)
20 os.waitpid(pid,os.WNOHANG)
24 class boot_node(Test):
26 Attempts to boot the specified node using qemu.
29 def state_nanny(self):
30 hostname = self.hostname
31 nodes = self.config.api.GetNodes(self.config.auth, [hostname], ['boot_state'])
33 boot_state = node['boot_state']
34 if True or self.config.verbose:
35 utils.header("%(hostname)s boot_state is %(boot_state)s" % locals())
37 if boot_state in ['boot', 'debug']:
40 if self.config.verbose:
41 if boot_state in ['boot']:
42 utils.header("%(hostname)s correctly installed and booted" % locals())
44 utils.header("%(hostname)s not fully booted" % locals())
45 self.boot_state = boot_state
48 def console_nanny(self,console_states):
49 #ready = select.select([],[self.stdout],[],1)[1]
51 if True or len(ready)>0:
56 lines = self.stdout.readlines()
61 #for searchstring in console_states.keys():
62 # result = line.find(searchstring)
63 # if result... ret = console_states[searchstring]
65 # check result for whether we found it
67 # for now just print it out
71 # should be parsing for special strings that indicate whether
72 # we've reached a particular state within the boot sequence
76 def call(self, hostname, image_type = 'node-iso', disk_size="4G", wait = 30):
78 # Get this nodes configuration
79 node = self.config.get_node(hostname)
80 # Which plc does this node talk to
81 plc = self.config.get_plc(node['plc'])
84 auth = plc.config.auth
86 bootimage_filename = '%(hostname)s-bootcd.iso' % locals()
88 homedir = node['homedir']
89 diskimage_path = "/%(homedir)s/%(hostname)s-hda.img" % locals()
90 bootimage_tmppath = "%(tmpdir)s/%(bootimage_filename)s" % locals()
91 bootimage_path = "%(homedir)s/%(bootimage_filename)s" % locals()
92 if host in ['localhost', None]:
93 remote_bootimage_path = bootimage_path
95 remote_bootimage_path = "%(host)s:%(bootimage_path)s" % locals()
97 # wait up to 30 minutes for a node to boot and install itself correctly
98 self.hostname = hostname
99 self.totaltime = 60*60*wait
102 nodes = api.GetNodes(auth, [hostname], ['hostname'])
104 raise Exception, "%s not found at plc %s" % (hostname, plc['name'])
105 node.update(nodes[0])
108 if self.config.verbose:
109 utils.header("Creating bootcd for %(hostname)s at %(host)s:%(bootimage_path)s" % locals())
110 bootimage = api.GetBootMedium(auth, hostname, image_type, '', ['serial'])
111 fp = open(bootimage_tmppath, 'w')
112 fp.write(base64.b64decode(bootimage))
115 # Move the boot image to the nodes home directory
116 node.commands("mkdir -p %(homedir)s" % locals())
117 node.scp(bootimage_tmppath, "%(remote_bootimage_path)s" % locals())
119 # Create a temporary disk image
120 qemu_img_cmd = "qemu-img create -f qcow2 %(diskimage_path)s %(disk_size)s" % locals()
121 node.commands(qemu_img_cmd)
123 if self.config.verbose:
124 utils.header("Booting %(hostname)s" % locals())
126 # Attempt to boot this node image
128 # generate a temp filename to which qemu should store its pid (crappy approach)
129 tmp = tempfile.mkstemp(".pid","qemu_")
134 # boot node with ramsize memory
137 # always use the 64 bit version of qemu, as this will work on both 32 & 64 bit host kernels
138 bootcmd = "qemu-system-x86_64"
139 # tell qemu to store its pid ina file
140 bootcmd = bootcmd + " -pidfile %(pidfile)s " % locals()
141 # boot with ramsize memory
142 bootcmd = bootcmd + " -m %(ramsize)s" % locals()
144 bootcmd = bootcmd + " -smp 1"
146 #bootcmd = bootcmd + " -net nic -net tap,script=%s/qemu-ifup" % self.config.qemu_scripts_path
147 # no graphics support -> assume we are booting via serial console
148 bootcmd = bootcmd + " -nographic"
149 # boot from the supplied cdrom iso file
150 bootcmd = bootcmd + " -boot d"
151 bootcmd = bootcmd + " -cdrom %(bootimage_path)s" % locals()
152 # hard disk image to use for the node
153 bootcmd = bootcmd + " %(diskimage_path)s" % locals()
156 utils.header(bootcmd)
157 (self.stdin, self.stdout, self.stderr) = node.popen3(bootcmd)
159 # wait for qemu to start up
162 # get qemu's pid from its pidfile (crappy approach)
169 # loop until the node is either fully booted, some error
170 # occured, or we've reached our totaltime out
171 def catch(sig, frame):
172 self.totaltime = self.totaltime -1
173 utils.header("beep %d\n" %self.totaltime)
174 total = self.totaltime
176 (((total % 60)==0) and self.state_nanny()):
183 signal.signal(signal.SIGALRM, catch)
187 console_states = {"login:":1}
190 self.console_nanny(console_states)
191 except: # need a better way to catch exceptions
192 traceback.print_exc()
202 if __name__ == '__main__':
203 args = tuple(sys.argv[1:])