]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Replace --qemu-headless with --qemu-gui
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 19 Mar 2023 11:30:45 +0000 (12:30 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 29 Mar 2023 08:39:10 +0000 (10:39 +0200)
We add extra kernel command line arguments that configure term and
the tty size at runtime. We start qemu in the terminal on a serial tty
by default now as well.

We introduce --qemu-gui to still allow booting qemu in a graphical
interface

We also pass the host environment to qemu and nspawn to mimick what
we do with ssh and because qemu needs the host environment to
initialize gtk properly.

.github/workflows/ci.yml
NEWS.md
mkosi.md
mkosi/__init__.py
mkosi/backend.py
mkosi/install.py

index f5a1df1daba9c27ff4f2b3c51ef924c17f493d9e..d0c24314abb60524ccdf649173fe33c14e3511a4 100644 (file)
@@ -194,7 +194,6 @@ jobs:
 
         [Host]
         Autologin=yes
-        QemuHeadless=yes
 
         [Content]
         ExtraTrees=.github/mkosi.extra
diff --git a/NEWS.md b/NEWS.md
index c9ad915e3b48980d3979b66d5e65b55a7aa7c3a3..0127a568e63cb0bb0799c4d95bd3f98c0e885611 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -54,6 +54,8 @@
   `machinectl` to access images booted with `mkosi boot`. Use --extra-tree or --credential with the
   `.ssh.authorized_keys.root` credentials as alternatives for provisioning the public key inside the image.
 - Only configuration files matching `*.conf` are parsed in dropin directories now.
+- Removed `--qemu-headless`, we now start qemu in the terminal by default and configure the serial console at
+  runtime. Use the new `--qemu-gui` option to start qemu in its graphical interface.
 
 ## v14
 
index 24f072021ea98966f4f3b015fa2ec196603f0b7f..7bd1e4d79b349f8f266f7fc3b87c03abff1ae304 100644 (file)
--- a/mkosi.md
+++ b/mkosi.md
@@ -672,8 +672,7 @@ a boolean argument: either "1", "yes", or "true" to enable, or "0",
 `Autologin=`, `--autologin`
 
 : Enable autologin for the `root` user on `/dev/pts/0` (nspawn),
-  `/dev/tty1` (QEMU) and `/dev/ttyS0` (QEMU with `QemuHeadless=yes`)
-  by patching `/etc/pam.d/login`.
+  `/dev/tty1` and `/dev/ttyS0` by patching `/etc/pam.d/login`.
 
 `BuildScript=`, `--build-script=`
 
@@ -784,20 +783,10 @@ a boolean argument: either "1", "yes", or "true" to enable, or "0",
 : List of colon-separated paths to look for tools in, before using the
   regular `$PATH` search path.
 
-`QemuHeadless=`, `--qemu-headless=`
+`QemuGui=`, `--qemu-gui=`
 
-: When used with the `build` verb, this option adds `console=ttyS0` to
-  the image's kernel command line and sets the terminal type of the
-  serial console in the image to the terminal type of the host (more
-  specifically, the value of the `$TERM` environment variable passed
-  to mkosi). This makes sure that all terminal features such as colors
-  and shortcuts still work as expected when connecting to the qemu VM
-  over the serial console (for example via `-nographic`).
-
-: When used with the `qemu` verb, this option adds the `-nographic`
-  option to `qemu`'s command line so qemu starts a headless vm and
-  connects to its serial console from the current terminal instead of
-  launching the VM in a separate window.
+: If enabled, qemu is executed with its graphical interface instead of
+  with a serial console.
 
 `QemuSmp=`, `--qemu-smp=`
 
index 01ef45c82f4311204efe0fa52d02d861d4a4788c..7a006ea93543912eca6192e34c7616d6c5ef5dd1 100644 (file)
@@ -57,7 +57,6 @@ from mkosi.backend import (
     tmp_dir,
 )
 from mkosi.install import (
-    add_dropin_config,
     add_dropin_config_from_resource,
     copy_path,
     flock,
@@ -496,25 +495,6 @@ def configure_autologin(state: MkosiState) -> None:
         pam_add_autologin(state.root, ttys)
 
 
-def configure_serial_terminal(state: MkosiState) -> None:
-    """Override TERM for the serial console with the terminal type from the host."""
-
-    if not state.config.qemu_headless or state.for_cache:
-        return
-
-    with complete_step("Configuring serial tty (/dev/ttyS0)…"):
-        columns, lines = shutil.get_terminal_size(fallback=(80, 24))
-        add_dropin_config(state.root, "serial-getty@ttyS0.service", "term",
-                          f"""\
-                          [Service]
-                          Environment=TERM={os.getenv('TERM', 'vt220')}
-                          Environment=COLUMNS={columns}
-                          Environment=LINES={lines}
-                          TTYColumns={columns}
-                          TTYRows={lines}
-                          """)
-
-
 def mount_build_overlay(state: MkosiState) -> ContextManager[Path]:
     return mount_overlay(state.root, state.build_overlay, state.workdir, state.root)
 
@@ -855,15 +835,6 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None:
 
             cmdline += state.config.kernel_command_line
 
-            if state.config.qemu_headless and not any("console=ttyS0" in x for x in cmdline):
-                cmdline += ["console=ttyS0"]
-
-            # By default, the serial console gets spammed with kernel log messages.
-            # Let's up the log level to only show warning and error messages when
-            # --qemu-headless is enabled to avoid this spam.
-            if state.config.qemu_headless and not any("loglevel" in x for x in cmdline):
-                cmdline += ["loglevel=4"]
-
             # Older versions of systemd-stub expect the cmdline section to be null terminated. We can't embed
             # nul terminators in argv so let's communicate the cmdline via a file instead.
             state.workspace.joinpath("cmdline").write_text(f"{' '.join(cmdline).strip()}\x00")
@@ -1883,10 +1854,10 @@ def create_parser() -> ArgumentParserMkosi:
         help=argparse.SUPPRESS,
     )
     group.add_argument(
-        "--qemu-headless",
+        "--qemu-gui",
         metavar="BOOL",
         action=BooleanAction,
-        help="Configure image for qemu's -nographic mode",
+        help="Start QEMU in graphical mode",
     )
     group.add_argument(
         "--qemu-smp",
@@ -2370,6 +2341,27 @@ def load_credentials(args: argparse.Namespace) -> dict[str, str]:
     return creds
 
 
+def load_kernel_command_line_extra(args: argparse.Namespace) -> list[str]:
+    cmdline = []
+
+    for s in args.kernel_command_line_extra:
+        key, sep, value = s.partition("=")
+        if " " in value:
+            value = f'"{value}"'
+        cmdline += [key if not sep else f"{key}={value}"]
+
+    columns, lines = shutil.get_terminal_size()
+
+    cmdline += [
+        f"systemd.tty.term.ttyS0={os.getenv('TERM', 'vt220')}",
+        f"systemd.tty.columns.ttyS0={columns}",
+        f"systemd.tty.rows.ttyS0={lines}",
+        "console=ttyS0",
+    ]
+
+    return cmdline
+
+
 def load_args(args: argparse.Namespace) -> MkosiConfig:
     ARG_DEBUG.update(args.debug)
 
@@ -2520,6 +2512,7 @@ def load_args(args: argparse.Namespace) -> MkosiConfig:
         args.environment = {}
 
     args.credentials = load_credentials(args)
+    args.kernel_command_line_extra = load_kernel_command_line_extra(args)
 
     if args.cache_path is not None:
         args.cache_path = args.cache_path.absolute()
@@ -2853,7 +2846,6 @@ def print_summary(config: MkosiConfig) -> None:
     print("\nHOST CONFIGURATION:")
 
     print("        Extra search paths:", line_join_list(config.extra_search_paths))
-    print("             QEMU Headless:", yes_no(config.qemu_headless))
     print("      QEMU Extra Arguments:", line_join_list(config.qemu_args))
     print("                    Netdev:", yes_no(config.netdev))
 
@@ -3186,7 +3178,6 @@ def build_image(state: MkosiState, *, manifest: Optional[Manifest] = None) -> No
         configure_locale(state)
         configure_hostname(state)
         configure_root_password(state)
-        configure_serial_terminal(state)
         configure_autologin(state)
         configure_dracut(state, cached)
         configure_netdev(state)
@@ -3445,7 +3436,7 @@ def run_shell(config: MkosiConfig) -> None:
         acl_toggle_remove(config, config.output, uid, allow=False)
 
     try:
-        run(cmdline, stdout=sys.stdout)
+        run(cmdline, stdout=sys.stdout, env=os.environ)
     finally:
         if config.output_format == OutputFormat.directory:
             acl_toggle_remove(config, config.output, uid, allow=True)
@@ -3623,12 +3614,12 @@ def run_qemu(config: MkosiConfig) -> None:
 
     cmdline += ["-cpu", "max"]
 
-    if config.qemu_headless:
+    if config.qemu_gui:
+        cmdline += ["-vga", "virtio"]
+    else:
         # -nodefaults removes the default CDROM device which avoids an error message during boot
         # -serial mon:stdio adds back the serial device removed by -nodefaults.
         cmdline += ["-nographic", "-nodefaults", "-serial", "mon:stdio"]
-    else:
-        cmdline += ["-vga", "virtio"]
 
     if config.netdev:
         cmdline += ["-nic", "user,model=virtio-net-pci"]
@@ -3701,7 +3692,7 @@ def run_qemu(config: MkosiConfig) -> None:
         cmdline += config.cmdline
 
         print_running_cmd(cmdline)
-        run(cmdline, stdout=sys.stdout)
+        run(cmdline, stdout=sys.stdout, env=os.environ)
 
 
 def run_ssh(config: MkosiConfig) -> None:
index 94233e4251c3028763fb4b520119e9cce61b40b5..584134023a4b604367db10eb68069d6e22379231 100644 (file)
@@ -310,7 +310,7 @@ class MkosiConfig:
     acl: bool
 
     # QEMU-specific options
-    qemu_headless: bool
+    qemu_gui: bool
     qemu_smp: str
     qemu_mem: str
     qemu_kvm: bool
index d681115fbe95ead403955d0c4211f664df959c84..b95e3e067e9d3ad530e180e0aa12453682a9bf0f 100644 (file)
@@ -8,7 +8,6 @@ import shutil
 import stat
 from collections.abc import Iterator
 from pathlib import Path
-from textwrap import dedent
 from typing import Optional
 
 from mkosi.backend import MkosiState
@@ -32,14 +31,6 @@ def write_resource(
         make_executable(where)
 
 
-def add_dropin_config(root: Path, unit: str, name: str, content: str) -> None:
-    """Add a dropin config `name.conf` in /etc/systemd/system for `unit`."""
-    dropin = root / f"etc/systemd/system/{unit}.d/{name}.conf"
-    dropin.parent.mkdir(mode=0o755, parents=True, exist_ok=True)
-    dropin.write_text(dedent(content))
-    dropin.chmod(0o644)
-
-
 def add_dropin_config_from_resource(
     root: Path, unit: str, name: str, resource: str, key: str
 ) -> None: