1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
from os.path import exists, isdir, join, realpath, abspath
from os import listdir
import random
import socket
from shutil import copyfile
from subprocess import check_output
EXTENSIONS = {
'intel-corei7-64': 'wic',
'qemux86-64': 'ota-ext4'
}
def find_local_port(start_port):
""""
Find the next free TCP port after 'start_port'.
"""
for port in range(start_port, start_port + 10):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', port))
return port
except socket.error:
print("Skipping port %d" % port)
finally:
s.close()
raise Exception("Could not find a free TCP port")
def random_mac():
"""Return a random Ethernet MAC address
@link https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml#ethernet-numbers-2
"""
head = "ca:fe:"
hex_digits = '0123456789abcdef'
tail = ':'.join([random.choice(hex_digits) + random.choice(hex_digits) for _ in range(4)])
return head + tail
class QemuCommand(object):
def __init__(self, args):
self.dry_run = args.dry_run
self.overlay = args.overlay
if args.machine:
self.machine = args.machine
else:
if not isdir(args.dir):
raise ValueError("Directory %s does not exist, please specify a --machine or a valid images directory" % args.dir)
machines = listdir(args.dir)
if len(machines) == 1:
self.machine = machines[0]
else:
raise ValueError("Could not autodetect machine type. More than one entry in %s. Maybe --machine qemux86-64?" % args.dir)
# If using an overlay with U-Boot, copy the rom when we create the
# overlay so that we can keep it around just in case.
if args.efi:
self.bios = 'OVMF.fd'
else:
uboot_path = abspath(join(args.dir, self.machine, 'u-boot-qemux86-64.rom'))
if self.overlay:
new_uboot_path = self.overlay + '.u-boot.rom'
if not exists(self.overlay):
if not exists(uboot_path):
raise ValueError("U-Boot image %s does not exist" % uboot_path)
if not exists(new_uboot_path):
if self.dry_run:
print("cp %s %s" % (uboot_path, new_uboot_path))
else:
copyfile(uboot_path, new_uboot_path)
uboot_path = new_uboot_path
if not exists(uboot_path) and not (self.dry_run and not exists(self.overlay)):
raise ValueError("U-Boot image %s does not exist" % uboot_path)
self.bios = uboot_path
# If using an overlay, we need to keep the "backing" image around, as
# bitbake will often clean it up, and the overlay silently depends on
# the hardcoded path. The easiest solution is to keep the file and use
# a relative path to it.
if exists(args.imagename):
image = realpath(args.imagename)
else:
ext = EXTENSIONS.get(self.machine, 'wic')
image = join(args.dir, self.machine, '%s-%s.%s' % (args.imagename, self.machine, ext))
if self.overlay:
new_image_path = self.overlay + '.img'
if not exists(self.overlay):
if not exists(image):
raise ValueError("OS image %s does not exist" % image)
if not exists(new_image_path):
if self.dry_run:
print("cp %s %s" % (image, new_image_path))
else:
copyfile(image, new_image_path)
self.image = new_image_path
else:
self.image = realpath(image)
if not exists(self.image) and not (self.dry_run and not exists(self.overlay)):
raise ValueError("OS image %s does not exist" % self.image)
if args.mac:
self.mac_address = args.mac
else:
self.mac_address = random_mac()
self.serial_port = find_local_port(8990)
self.ssh_port = find_local_port(2222)
if args.mem:
self.mem = args.mem
else:
self.mem = "1G"
if args.kvm is None:
# Autodetect KVM using 'kvm-ok'
try:
check_output(['kvm-ok'])
self.kvm = True
except Exception:
self.kvm = False
else:
self.kvm = args.kvm
self.gui = not args.no_gui
self.gdb = args.gdb
self.pcap = args.pcap
self.secondary_network = args.secondary_network
def command_line(self):
netuser = 'user,hostfwd=tcp:0.0.0.0:%d-:22,restrict=off' % self.ssh_port
if self.gdb:
netuser += ',hostfwd=tcp:0.0.0.0:2159-:2159'
cmdline = [
"qemu-system-x86_64",
"-bios", self.bios
]
if not self.overlay:
cmdline += ["-drive", "file=%s,if=ide,format=raw,snapshot=on" % self.image]
cmdline += [
"-serial", "tcp:127.0.0.1:%d,server,nowait" % self.serial_port,
"-m", self.mem,
"-object", "rng-random,id=rng0,filename=/dev/urandom",
"-device", "virtio-rng-pci,rng=rng0",
"-net", netuser,
"-net", "nic,macaddr=%s" % self.mac_address
]
if self.pcap:
cmdline += ['-net', 'dump,file=' + self.pcap]
if self.secondary_network:
cmdline += [
'-netdev', 'socket,id=vlan1,mcast=230.0.0.1:1234,localaddr=127.0.0.1',
'-device', 'e1000,netdev=vlan1,mac='+random_mac(),
]
if self.gui:
cmdline += [
"-usb",
"-device", "usb-tablet",
"-show-cursor",
"-vga", "std"
]
else:
cmdline += [
"-nographic",
"-monitor", "null",
]
if self.kvm:
cmdline += ['-enable-kvm', '-cpu', 'host']
else:
cmdline += ['-cpu', 'Haswell']
if self.overlay:
cmdline.append(self.overlay)
return cmdline
def img_command_line(self):
cmdline = [
"qemu-img", "create",
"-o", "backing_file=%s" % self.image,
"-f", "qcow2",
self.overlay]
return cmdline
|