From 5ec153ae190020bfc5a75b5064348d45a565d21b Mon Sep 17 00:00:00 2001 From: Phil Wise Date: Thu, 20 Jul 2017 10:20:31 +0200 Subject: Copy run-qemu script over from meta-updater-qemux86-64 Also remove old bash scripts for running inside qemu --- scripts/run-qemu-ota | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100755 scripts/run-qemu-ota (limited to 'scripts/run-qemu-ota') diff --git a/scripts/run-qemu-ota b/scripts/run-qemu-ota new file mode 100755 index 0000000..181558c --- /dev/null +++ b/scripts/run-qemu-ota @@ -0,0 +1,150 @@ +#! /usr/bin/env python + +from argparse import ArgumentParser +from subprocess import Popen +from os.path import exists, join, realpath +from os import listdir +import random +import sys +import socket + +DEFAULT_DIR = 'tmp/deploy/images' + +EXTENSIONS = { + 'intel-corei7-64': 'wic', + 'qemux86-64': 'otaimg' +} + + +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 from %s" % args.dir) + if args.efi: + self.bios = 'OVMF.fd' + else: + uboot = 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 + 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) + self.kvm = not args.no_kvm + self.gui = not args.no_gui + self.gdb = args.gdb + self.pcap = args.pcap + + 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, + "-drive", "file=%s,if=ide,format=raw,snapshot=on" % self.image, + "-serial", "tcp:127.0.0.1:%d,server,nowait" % self.serial_port, + "-m", "1G", + "-usb", + "-usbdevice", "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.gui: + cmdline += ["-serial", "stdio"] + else: + cmdline.append('-nographic') + if self.kvm: + cmdline.append('-enable-kvm') + else: + cmdline += ['-cpu', 'Haswell'] + return cmdline + + +def main(): + parser = ArgumentParser(description='Run meta-updater image in qemu') + parser.add_argument('imagename', default='core-image-minimal', nargs='?') + parser.add_argument('mac', default=None, nargs='?') + parser.add_argument('--dir', default=DEFAULT_DIR, + help='Path to build directory containing the image and u-boot-qemux86-64.rom') + parser.add_argument('--efi', + help='Boot using UEFI rather than U-Boot. This requires the image to be built with ' + + 'OSTREE_BOOTLOADER = "grub" and OVMF.fd firmware to be installed (try "apt install ovmf")', + action='store_true') + parser.add_argument('--machine', default=None, help="Target MACHINE") + parser.add_argument('--no-kvm', help='Disable KVM in QEMU', action='store_true') + parser.add_argument('--no-gui', help='Disable GUI', action='store_true') + parser.add_argument('--gdb', help='Export gdbserver port 2159 from the image', action='store_true') + parser.add_argument('--pcap', default=None, help='Dump all network traffic') + parser.add_argument('-n', '--dry-run', help='Print qemu command line rather then run it', action='store_true') + args = parser.parse_args() + try: + qemu_command = QemuCommand(args) + except ValueError as e: + print(e.message) + sys.exit(1) + + print("Launching %s with mac address %s" % (args.imagename, qemu_command.mac_address)) + print("To connect via SSH:") + print(" ssh -o StrictHostKeyChecking=no root@localhost -p %d" % qemu_command.ssh_port) + print("To connect to the serial console:") + print(" nc localhost %d" % qemu_command.serial_port) + + cmdline = qemu_command.command_line() + if args.dry_run: + print(" ".join(cmdline)) + else: + s = Popen(cmdline) + try: + s.wait() + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main() -- cgit v1.2.3-54-g00ecf