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'])
83 auth = plc.config.auth
85 bootimage_filename = '%(hostname)s-bootcd.iso' % locals()
87 homedir = node['homedir']
88 diskimage_path = "/%(homedir)s/%(hostname)s-hda.img" % locals()
89 bootimage_tmppath = "%(tmpdir)s/%(bootimage_filename)s" % locals()
90 bootimage_path = "%(homedir)s/%(bootimage_filename)s" % locals()
91 if host in ['localhost', None]:
92 remote_bootimage_path = bootimage_path
94 remote_bootimage_path = "%(host)s:%(bootimage_path)s" % locals()
96 # wait up to 30 minutes for a node to boot and install itself correctly
97 self.hostname = hostname
98 self.totaltime = 60*60*wait
101 nodes = api.GetNodes(auth, [hostname], ['hostname'])
103 raise Exception, "%s not found at plc %s" % (hostname, plc['name'])
104 node.update(nodes[0])
107 if self.config.verbose:
108 utils.header("Creating bootcd for %(hostname)s at %(host)s:%(bootimage_path)s" % locals())
109 bootimage = api.GetBootMedium(auth, hostname, image_type, '', ['serial'])
110 fp = open(bootimage_tmppath, 'w')
111 fp.write(base64.b64decode(bootimage))
114 # Move the boot image to the nodes home directory
115 node.host_commands("mkdir -p %(homedir)s" % locals())
116 node.scp(bootimage_tmppath, "%(remote_bootimage_path)s" % locals())
118 # Create a temporary disk image
119 qemu_img_cmd = "qemu-img create -f qcow2 %(diskimage_path)s %(disk_size)s" % locals()
120 node.host_commands(qemu_img_cmd)
122 if self.config.verbose:
123 utils.header("Booting %(hostname)s" % locals())
125 # Attempt to boot this node image
127 # generate a temp filename to which qemu should store its pid (crappy approach)
128 tmp = tempfile.mkstemp(".pid","qemu_")
133 # boot node with ramsize memory
136 # always use the 64 bit version of qemu, as this will work on both 32 & 64 bit host kernels
137 bootcmd = "qemu-system-x86_64"
138 # tell qemu to store its pid ina file
139 bootcmd = bootcmd + " -pidfile %(pidfile)s " % locals()
140 # boot with ramsize memory
141 bootcmd = bootcmd + " -m %(ramsize)s" % locals()
143 bootcmd = bootcmd + " -smp 1"
144 # redirect incomming tcp connections on specified port to guest node
145 if 'redir_port' in node and node['redir_port']:
146 port = node['redir_port']
147 bootcmd = bootcmd + " -redir tcp:%(port)s::22" % locals()
148 # no graphics support -> assume we are booting via serial console
149 bootcmd = bootcmd + " -nographic"
150 # boot from the supplied cdrom iso file
151 bootcmd = bootcmd + " -boot d"
152 bootcmd = bootcmd + " -cdrom %(bootimage_path)s" % locals()
153 # hard disk image to use for the node
154 bootcmd = bootcmd + " %(diskimage_path)s" % locals()
157 utils.header(bootcmd)
158 (self.stdin, self.stdout, self.stderr) = node.host_popen3(bootcmd)
160 # wait for qemu to start up
163 # get qemu's pid from its pidfile (crappy approach)
170 # loop until the node is either fully booted, some error
171 # occured, or we've reached our totaltime out
172 def catch(sig, frame):
173 self.totaltime = self.totaltime -1
174 utils.header("beep %d\n" %self.totaltime)
175 total = self.totaltime
177 (((total % 60)==0) and self.state_nanny()):
184 signal.signal(signal.SIGALRM, catch)
188 console_states = {"login:":1}
191 self.console_nanny(console_states)
192 except: # need a better way to catch exceptions
193 traceback.print_exc()
203 if __name__ == '__main__':
204 args = tuple(sys.argv[1:])