summaryrefslogtreecommitdiffstats
path: root/scripts/run-qemu-ota
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/run-qemu-ota')
-rwxr-xr-xscripts/run-qemu-ota132
1 files changed, 16 insertions, 116 deletions
diff --git a/scripts/run-qemu-ota b/scripts/run-qemu-ota
index 6a3586c..b2f55e9 100755
--- a/scripts/run-qemu-ota
+++ b/scripts/run-qemu-ota
@@ -2,127 +2,17 @@
2 2
3from argparse import ArgumentParser 3from argparse import ArgumentParser
4from subprocess import Popen 4from subprocess import Popen
5from os.path import exists, join, realpath 5from os.path import exists
6from os import listdir
7import random
8import sys 6import sys
9import socket 7from qemucommand import QemuCommand
10 8
11DEFAULT_DIR = 'tmp/deploy/images' 9DEFAULT_DIR = 'tmp/deploy/images'
12 10
13EXTENSIONS = {
14 'intel-corei7-64': 'wic',
15 'qemux86-64': 'otaimg'
16}
17
18
19def find_local_port(start_port):
20 """"
21 Find the next free TCP port after 'start_port'.
22 """
23
24 for port in range(start_port, start_port + 10):
25 try:
26 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
27 s.bind(('', port))
28 return port
29 except socket.error:
30 print("Skipping port %d" % port)
31 finally:
32 s.close()
33 raise Exception("Could not find a free TCP port")
34
35
36def random_mac():
37 """Return a random Ethernet MAC address
38 @link https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml#ethernet-numbers-2
39 """
40 head = "ca:fe:"
41 hex_digits = '0123456789abcdef'
42 tail = ':'.join([random.choice(hex_digits) + random.choice(hex_digits) for _ in range(4)])
43 return head + tail
44
45
46class QemuCommand(object):
47 def __init__(self, args):
48 if args.machine:
49 self.machine = args.machine
50 else:
51 machines = listdir(args.dir)
52 if len(machines) == 1:
53 self.machine = machines[0]
54 else:
55 raise ValueError("Could not autodetect machine type from %s" % args.dir)
56 if args.efi:
57 self.bios = 'OVMF.fd'
58 else:
59 uboot = join(args.dir, self.machine, 'u-boot-qemux86-64.rom')
60 if not exists(uboot):
61 raise ValueError("U-Boot image %s does not exist" % uboot)
62 self.bios = uboot
63 ext = EXTENSIONS.get(self.machine, 'wic')
64 image = join(args.dir, self.machine, '%s-%s.%s' % (args.imagename, self.machine, ext))
65 self.image = realpath(image)
66 if not exists(self.image):
67 raise ValueError("OS image %s does not exist" % self.image)
68 if args.mac:
69 self.mac_address = args.mac
70 else:
71 self.mac_address = random_mac()
72 self.serial_port = find_local_port(8990)
73 self.ssh_port = find_local_port(2222)
74 self.kvm = not args.no_kvm
75 self.gui = not args.no_gui
76 self.gdb = args.gdb
77 self.pcap = args.pcap
78 self.overlay = args.overlay
79
80 def command_line(self):
81 netuser = 'user,hostfwd=tcp:0.0.0.0:%d-:22,restrict=off' % self.ssh_port
82 if self.gdb:
83 netuser += ',hostfwd=tcp:0.0.0.0:2159-:2159'
84 cmdline = [
85 "qemu-system-x86_64",
86 "-bios", self.bios
87 ]
88 if not self.overlay:
89 cmdline += ["-drive", "file=%s,if=ide,format=raw,snapshot=on" % self.image]
90 cmdline += [
91 "-serial", "tcp:127.0.0.1:%d,server,nowait" % self.serial_port,
92 "-m", "1G",
93 "-usb",
94 "-usbdevice", "tablet",
95 "-show-cursor",
96 "-vga", "std",
97 "-net", netuser,
98 "-net", "nic,macaddr=%s" % self.mac_address
99 ]
100 if self.pcap:
101 cmdline += ['-net', 'dump,file=' + self.pcap]
102 if self.gui:
103 cmdline += ["-serial", "stdio"]
104 else:
105 cmdline.append('-nographic')
106 if self.kvm:
107 cmdline.append('-enable-kvm')
108 else:
109 cmdline += ['-cpu', 'Haswell']
110 if self.overlay:
111 cmdline.append(self.overlay)
112 return cmdline
113
114 def img_command_line(self):
115 cmdline = [
116 "qemu-img", "create",
117 "-o", "backing_file=%s" % self.image,
118 "-f", "qcow2",
119 self.overlay]
120 return cmdline
121
122 11
123def main(): 12def main():
124 parser = ArgumentParser(description='Run meta-updater image in qemu') 13 parser = ArgumentParser(description='Run meta-updater image in qemu')
125 parser.add_argument('imagename', default='core-image-minimal', nargs='?') 14 parser.add_argument('imagename', default='core-image-minimal', nargs='?',
15 help="Either the name of the bitbake image target, or a path to the image to run")
126 parser.add_argument('mac', default=None, nargs='?') 16 parser.add_argument('mac', default=None, nargs='?')
127 parser.add_argument('--dir', default=DEFAULT_DIR, 17 parser.add_argument('--dir', default=DEFAULT_DIR,
128 help='Path to build directory containing the image and u-boot-qemux86-64.rom') 18 help='Path to build directory containing the image and u-boot-qemux86-64.rom')
@@ -131,11 +21,21 @@ def main():
131 'OSTREE_BOOTLOADER = "grub" and OVMF.fd firmware to be installed (try "apt install ovmf")', 21 'OSTREE_BOOTLOADER = "grub" and OVMF.fd firmware to be installed (try "apt install ovmf")',
132 action='store_true') 22 action='store_true')
133 parser.add_argument('--machine', default=None, help="Target MACHINE") 23 parser.add_argument('--machine', default=None, help="Target MACHINE")
134 parser.add_argument('--no-kvm', help='Disable KVM in QEMU', action='store_true') 24 kvm_group = parser.add_argument_group()
25 kvm_group.add_argument('--force-kvm', help='Force use of KVM (default is to autodetect)',
26 dest='kvm', action='store_true', default=None)
27 kvm_group.add_argument('--no-kvm', help='Disable KVM in QEMU',
28 dest='kvm', action='store_false')
135 parser.add_argument('--no-gui', help='Disable GUI', action='store_true') 29 parser.add_argument('--no-gui', help='Disable GUI', action='store_true')
136 parser.add_argument('--gdb', help='Export gdbserver port 2159 from the image', action='store_true') 30 parser.add_argument('--gdb', help='Export gdbserver port 2159 from the image', action='store_true')
137 parser.add_argument('--pcap', default=None, help='Dump all network traffic') 31 parser.add_argument('--pcap', default=None, help='Dump all network traffic')
138 parser.add_argument('-o', '--overlay', type=str, metavar='file.cow', help='Use an overlay storage image file. Will be created if it does not exist. This option lets you have a persistent image without modifying the underlying image file, permitting multiple different persistent machines.') 32 parser.add_argument('-o', '--overlay', type=str, metavar='file.cow',
33 help='Use an overlay storage image file. Will be created if it does not exist. ' +
34 'This option lets you have a persistent image without modifying the underlying image ' +
35 'file, permitting multiple different persistent machines.')
36 parser.add_argument('--secondary-network', action='store_true', dest='secondary_network',
37 help='Give the image a second network card connected to a virtual network. ' +
38 'This can be used to test Uptane Primary/Secondary communication.')
139 parser.add_argument('-n', '--dry-run', help='Print qemu command line rather then run it', action='store_true') 39 parser.add_argument('-n', '--dry-run', help='Print qemu command line rather then run it', action='store_true')
140 args = parser.parse_args() 40 args = parser.parse_args()
141 try: 41 try: