]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
mkosi: add "qemu" verb 180/head
authorLennart Poettering <lennart@poettering.net>
Wed, 25 Oct 2017 10:40:28 +0000 (12:40 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Nov 2017 11:23:24 +0000 (12:23 +0100)
This adds a new "mkosi qemu" verb that is like "mkosi boot" but invokes
things in a QEMU environment.

This tries to find the native qemu implementation, with a couple of
fallbacks if none is found, always opting for KVM acceleration.

This also tries to automatically discover the UEFI firmware blobs. For
now only the location where the files are on Fedora is encoded in the
search path, but this can be updated for other distributions easily
later on.

Fixes: #179
mkosi

diff --git a/mkosi b/mkosi
index 8507c05547fd92f92058fb29f7b9a1c361028107..54ad739a3b2e53b52d984e0a48387a877a9d05c6 100755 (executable)
--- a/mkosi
+++ b/mkosi
@@ -2135,8 +2135,8 @@ def parse_args():
     parser = argparse.ArgumentParser(description='Build Legacy-Free OS Images', add_help=False)
 
     group = parser.add_argument_group("Commands")
-    group.add_argument("verb", choices=("build", "clean", "help", "summary", "shell", "boot"), nargs='?', default="build", help='Operation to execute')
-    group.add_argument("cmdline", nargs=argparse.REMAINDER, help="The command line to use for 'shell' and 'boot'")
+    group.add_argument("verb", choices=("build", "clean", "help", "summary", "shell", "boot", "qemu"), nargs='?', default="build", help='Operation to execute')
+    group.add_argument("cmdline", nargs=argparse.REMAINDER, help="The command line to use for 'shell', 'boot', 'qemu'")
     group.add_argument('-h', '--help', action='help', help="Show this help")
     group.add_argument('--version', action='version', version='%(prog)s ' + __version__)
 
@@ -2713,8 +2713,8 @@ def load_args():
     find_passphrase(args)
     find_secure_boot(args)
 
-    if args.cmdline and args.verb not in ('shell', 'boot'):
-        die("Additional parameters only accepted for 'shell' and 'boot' invocations.")
+    if args.cmdline and args.verb not in ('shell', 'boot', 'qemu'):
+        die("Additional parameters only accepted for 'shell', 'boot', 'qemu' invocations.")
 
     args.force = args.force_count > 0
 
@@ -2894,12 +2894,16 @@ def load_args():
         if args.secure_boot_certificate is None:
             die("UEFI SecureBoot enabled, but couldn't find certificate. (Consider placing it in mkosi.secure-boot.crt?)")
 
-    if args.verb in ("shell", "boot"):
+    if args.verb in ("shell", "boot", "qemu"):
         if args.output_format == OutputFormat.tar:
             die("Sorry, can't acquire shell in or boot a tar archive.")
         if args.xz:
             die("Sorry, can't acquire shell in or boot an XZ compressed image.")
 
+    if args.verb == "qemu":
+        if args.output_format not in (OutputFormat.raw_gpt, OutputFormat.raw_btrfs, OutputFormat.raw_squashfs):
+            die("Sorry, can't boot non-raw images with qemu.")
+
     return args
 
 def check_output(args):
@@ -3299,17 +3303,46 @@ def run_shell(args):
 
     os.execvp(cmdline[0], cmdline)
 
+def run_qemu(args):
+
+    # Look for the right qemu command line to use
+    ARCH_BINARIES = { 'x86_64' : 'qemu-system-x86_64' }
+    arch_binary = ARCH_BINARIES.get(platform.machine(), None)
+    for cmdline in ([arch_binary, '-machine', 'accel=kvm'],
+                    ['qemu', '-machine', 'accel=kvm'],
+                    ['qemu-kvm']):
+
+           if cmdline[0] and shutil.which(cmdline[0]):
+               break
+    else:
+        die("Couldn't find QEMU/KVM binary")
+
+    # Look for UEFI firmware blob
+    for firmware in ('/usr/share/edk2/ovmf/OVMF_CODE.fd',):
+        if os.path.exists(firmware):
+            break
+    else:
+        die("Couldn't find OVMF UEFI firmware blob.")
+
+    cmdline += [ "-bios", firmware,
+                 "-smp", "2",
+                 "-m", "1024",
+                 "-drive", "format=raw,file=" + args.output,
+                 *args.cmdline ]
+
+    os.execvp(cmdline[0], cmdline)
+
 def main():
     args = load_args()
 
-    if args.verb in ("build", "clean", "shell", "boot"):
+    if args.verb in ("build", "clean", "shell", "boot", "qemu"):
         check_root()
         unlink_output(args)
 
     if args.verb == "build":
         check_output(args)
 
-    needs_build = args.verb == "build" or (not os.path.exists(args.output) and args.verb in ("shell", "boot"))
+    needs_build = args.verb == "build" or (not os.path.exists(args.output) and args.verb in ("shell", "boot", "qemu"))
 
     if args.verb == "summary" or needs_build:
         print_summary(args)
@@ -3323,5 +3356,8 @@ def main():
     if args.verb in ("shell", "boot"):
         run_shell(args)
 
+    if args.verb == "qemu":
+        run_qemu(args)
+
 if __name__ == "__main__":
     main()