From 06711c8543a3af13203b4352b25b1875c29c16f2 Mon Sep 17 00:00:00 2001 From: Patrick Vacek Date: Tue, 7 Nov 2017 15:20:53 +0100 Subject: Refactor QemuCommand class into its own file/module. --- scripts/qemucommand.py | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 scripts/qemucommand.py (limited to 'scripts/qemucommand.py') diff --git a/scripts/qemucommand.py b/scripts/qemucommand.py new file mode 100644 index 0000000..ed14d9b --- /dev/null +++ b/scripts/qemucommand.py @@ -0,0 +1,118 @@ +from os.path import exists, join, realpath +from os import listdir +import random +import socket + +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 + 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) + self.kvm = not args.no_kvm + self.gui = not args.no_gui + self.gdb = args.gdb + self.pcap = args.pcap + self.overlay = args.overlay + + 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", "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'] + 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 + + -- cgit v1.2.3-54-g00ecf From 9d5ad230a7558ae9adea42ea69d633d489c6dec0 Mon Sep 17 00:00:00 2001 From: Patrick Vacek Date: Tue, 7 Nov 2017 17:34:13 +0100 Subject: Rough draft of a run-qemu-ota test. Not very useful yet. Could be made into a function for the purpose of running arbitrary commands via SSH, for example. However, I had plenty of trouble even getting this far. Note that I created a softlink to qemucommand to get around the Python path issues in oe-selftest. I'm not sure if there's a better way to handle that, since manipulating the path is seemingly impossible. --- .gitignore | 1 + lib/oeqa/selftest/qemucommand.py | 1 + lib/oeqa/selftest/updater.py | 33 +++++++++++++++++++++++++++++++++ scripts/qemucommand.py | 4 ++-- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 120000 lib/oeqa/selftest/qemucommand.py (limited to 'scripts/qemucommand.py') diff --git a/.gitignore b/.gitignore index bee8a64..8d35cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +*.pyc diff --git a/lib/oeqa/selftest/qemucommand.py b/lib/oeqa/selftest/qemucommand.py new file mode 120000 index 0000000..bc06dde --- /dev/null +++ b/lib/oeqa/selftest/qemucommand.py @@ -0,0 +1 @@ +../../../scripts/qemucommand.py \ No newline at end of file diff --git a/lib/oeqa/selftest/updater.py b/lib/oeqa/selftest/updater.py index e9048fd..4cdd1a2 100644 --- a/lib/oeqa/selftest/updater.py +++ b/lib/oeqa/selftest/updater.py @@ -4,6 +4,9 @@ import logging from oeqa.selftest.base import oeSelfTest from oeqa.utils.commands import runCmd, bitbake, get_bb_var +import subprocess +from oeqa.selftest.qemucommand import QemuCommand +import time class UpdaterTests(oeSelfTest): @@ -39,3 +42,33 @@ class UpdaterTests(oeSelfTest): def test_hsm(self): self.write_config('SOTA_CLIENT_FEATURES="hsm hsm-test"') bitbake('core-image-minimal') + + def test_qemu(self): + print('') + # Create empty object. + args = type('', (), {})() + args.imagename = 'core-image-minimal' + args.mac = None + args.dir = 'tmp/deploy/images' + args.efi = False + args.machine = None + args.no_kvm = False + args.no_gui = True + args.gdb = False + args.pcap = None + args.overlay = None + args.dry_run = False + + qemu_command = QemuCommand(args) + cmdline = qemu_command.command_line() + print('Booting image with run-qemu-ota...') + s = subprocess.Popen(cmdline) + time.sleep(10) + print('Machine name (hostname) of device is:') + ssh_cmd = ['ssh', '-q', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no', 'root@localhost', '-p', str(qemu_command.ssh_port), 'hostname'] + s2 = subprocess.Popen(ssh_cmd) + time.sleep(5) + try: + s.terminate() + except KeyboardInterrupt: + pass diff --git a/scripts/qemucommand.py b/scripts/qemucommand.py index ed14d9b..a75ffb6 100644 --- a/scripts/qemucommand.py +++ b/scripts/qemucommand.py @@ -1,4 +1,4 @@ -from os.path import exists, join, realpath +from os.path import exists, join, realpath, abspath from os import listdir import random import socket @@ -49,7 +49,7 @@ class QemuCommand(object): if args.efi: self.bios = 'OVMF.fd' else: - uboot = join(args.dir, self.machine, 'u-boot-qemux86-64.rom') + 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 -- cgit v1.2.3-54-g00ecf