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
|
from os.path import exists, join, realpath, abspath
from os import listdir
import random
import socket
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):
if args.machine:
self.machine = args.machine
else:
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 args.efi:
self.bios = 'OVMF.fd'
else:
uboot = abspath(join(args.dir, self.machine, 'u-boot-qemux86-64.rom'))
if not exists(uboot):
raise ValueError("U-Boot image %s does not exist" % uboot)
self.bios = uboot
if exists(args.imagename):
image = args.imagename
else:
ext = EXTENSIONS.get(self.machine, 'wic')
image = join(args.dir, self.machine, '%s-%s.%s' % (args.imagename, self.machine, ext))
self.image = realpath(image)
if not exists(self.image):
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.overlay = args.overlay
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,
"-usb",
"-object", "rng-random,id=rng0,filename=/dev/urandom",
"-device", "virtio-rng-pci,rng=rng0",
"-device", "usb-tablet",
"-show-cursor",
"-vga", "std",
"-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 += ["-serial", "stdio"]
else:
cmdline.append('-nographic')
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
|