summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py164
-rwxr-xr-xscripts/runqemu2
2 files changed, 165 insertions, 1 deletions
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
new file mode 100644
index 0000000..3132b68
--- /dev/null
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -0,0 +1,164 @@
1import subprocess
2import optparse
3import sys
4import os
5import time
6import signal
7import re
8import bb
9from oeqa.utils.oeqemuconsole import oeQemuConsole
10
11class QemuRunner:
12
13 def __init__(self, machine, rootfs, display = None, tmpdir = None, logfile = None):
14 # Popen object
15 self.runqemu = None
16
17 self.machine = machine
18 self.rootfs = rootfs
19
20 self.streampath = '/tmp/qemuconnection.%s' % os.getpid()
21 self.qemuparams = 'bootparams="console=ttyS0" qemuparams="-snapshot -serial unix:%s,server,nowait"' % self.streampath
22 self.qemupid = None
23 self.ip = None
24
25 self.display = display
26 self.tmpdir = tmpdir
27 self.logfile = logfile
28
29 def launch(self, qemuparams = None):
30
31 if qemuparams:
32 self.qemuparams = self.qemuparams[:-1] + " " + qemuparams + " " + '\"'
33
34 if self.display:
35 os.environ["DISPLAY"] = self.display
36 else:
37 bb.error("To start qemu I need a X desktop, please set DISPLAY correctly (e.g. DISPLAY=:1)")
38 return False
39 if not os.path.exists(self.rootfs):
40 bb.error("Invalid rootfs %s" % self.rootfs)
41 return False
42 if not os.path.exists(self.tmpdir):
43 bb.error("Invalid TMPDIR path %s" % self.tmpdir)
44 return False
45 else:
46 os.environ["OE_TMPDIR"] = self.tmpdir
47
48 launch_cmd = 'runqemu %s %s %s' % (self.machine, self.rootfs, self.qemuparams)
49 self.runqemu = subprocess.Popen(launch_cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,preexec_fn=os.setpgrp)
50
51 bb.note("runqemu started, pid is %s" % self.runqemu.pid)
52 # wait at most 30 seconds until qemu pid appears
53 bb.note("waiting at most 60 seconds for qemu pid")
54 endtime = time.time() + 60
55 while not self.is_alive() and time.time() < endtime:
56 time.sleep(1)
57
58 if self.is_alive():
59 bb.note("qemu started - qemu procces pid is %s" % self.qemupid)
60
61 console = oeQemuConsole(self.streampath, self.logfile)
62 bb.note("Waiting at most 200 seconds for login banner")
63 (match, text) = console.read_all_timeout("login:", 200)
64
65 if match:
66 bb.note("Reached login banner")
67 console.write("root\n")
68 (index, match, text) = console.expect([r"(root@[\w-]+:~#)"],10)
69 if not match:
70 bb.note("Couldn't get prompt, all I got was:\n%s" % match.group(0))
71 return False
72 console.write("ip addr show eth0 | sed -n '3p' | awk '{ print $2 }' | cut -f 1 -d \"/\"\n")
73 (index, match, text) = console.expect([r"((?:[0-9]{1,3}\.){3}[0-9]{1,3})"],10)
74 console.close()
75 if match:
76 self.ip = match.group(0)
77 bb.note("Ip found: %s" % self.ip)
78 else:
79 bb.note("Couldn't determine ip, all I got was:\n%s" % text)
80 return False
81 else:
82 console.close()
83 bb.note("Target didn't reached login boot in 120 seconds")
84 lines = "\n".join(text.splitlines()[-5:])
85 bb.note("Last 5 lines of text:\n%s" % lines)
86 bb.note("Check full boot log: %s" % self.logfile)
87 return False
88 else:
89 bb.note("Qemu pid didn't appeared in 30 seconds")
90 self.runqemu.terminate()
91 self.runqemu.kill()
92 bb.note("Output from runqemu: %s " % self.runqemu.stdout.read())
93 self.runqemu.stdout.close()
94 return False
95
96 return self.is_alive()
97
98
99 def kill(self):
100 if self.runqemu:
101 os.kill(-self.runqemu.pid,signal.SIGTERM)
102 self.qemupid = None
103 self.ip = None
104 if os.path.exists(self.streampath):
105 os.remove(self.streampath)
106
107 def restart(self, qemuparams = None):
108 if self.is_alive():
109 self.kill()
110 bb.note("Qemu Restart required...")
111 return self.launch(qemuparams)
112
113 def is_alive(self):
114 qemu_child = self.find_child(str(self.runqemu.pid))
115 if qemu_child:
116 self.qemupid = qemu_child[0]
117 if os.path.exists("/proc/" + str(self.qemupid)) and os.path.exists(self.streampath):
118 return True
119 return False
120
121 def find_child(self,parent_pid):
122 #
123 # Walk the process tree from the process specified looking for a qemu-system. Return its [pid'cmd]
124 #
125 ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,command'], stdout=subprocess.PIPE).communicate()[0]
126 processes = ps.split('\n')
127 nfields = len(processes[0].split()) - 1
128 pids = {}
129 commands = {}
130 for row in processes[1:]:
131 data = row.split(None, nfields)
132 if len(data) != 3:
133 continue
134 if data[1] not in pids:
135 pids[data[1]] = []
136
137 pids[data[1]].append(data[0])
138 commands[data[0]] = data[2]
139
140 if parent_pid not in pids:
141 sys.stderr.write("No children found matching %s\n" % parent_pid)
142 return []
143
144 parents = []
145 newparents = pids[parent_pid]
146 while newparents:
147 next = []
148 for p in newparents:
149 if p in pids:
150 for n in pids[p]:
151 if n not in parents and n not in next:
152 next.append(n)
153 if p not in parents:
154 parents.append(p)
155 newparents = next
156 #print "Children matching %s:" % str(parents)
157 for p in parents:
158 # Need to be careful here since runqemu-internal runs "ldd qemu-system-xxxx"
159 # Also, old versions of ldd (2.11) run "LD_XXXX qemu-system-xxxx"
160 basecmd = commands[p].split()[0]
161 basecmd = os.path.basename(basecmd)
162 if "qemu-system" in basecmd and "-serial unix" in commands[p]:
163 return [int(p),commands[p]]
164
diff --git a/scripts/runqemu b/scripts/runqemu
index f2eb2e1..406092b 100755
--- a/scripts/runqemu
+++ b/scripts/runqemu
@@ -156,7 +156,7 @@ while true; do
156 serial_option=`expr "$SCRIPT_QEMU_EXTRA_OPT" : '.*\(-serial\)'` 156 serial_option=`expr "$SCRIPT_QEMU_EXTRA_OPT" : '.*\(-serial\)'`
157 kvm_option=`expr "$SCRIPT_QEMU_EXTRA_OPT" : '.*\(-enable-kvm\)'` 157 kvm_option=`expr "$SCRIPT_QEMU_EXTRA_OPT" : '.*\(-enable-kvm\)'`
158 [ ! -z "$serial_option" -o ! -z "$kvm_option" ] && \ 158 [ ! -z "$serial_option" -o ! -z "$kvm_option" ] && \
159 error "Please use simplified serial or kvm options instead" 159 echo "Please use simplified serial or kvm options instead"
160 ;; 160 ;;
161 "bootparams="*) 161 "bootparams="*)
162 SCRIPT_KERNEL_OPT="$SCRIPT_KERNEL_OPT ${arg##bootparams=}" 162 SCRIPT_KERNEL_OPT="$SCRIPT_KERNEL_OPT ${arg##bootparams=}"