]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Remove --bootable option
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 6 Apr 2023 11:11:57 +0000 (13:11 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 12 Apr 2023 14:40:20 +0000 (16:40 +0200)
Instead, we just do the necessary setup for a bootable image if all
the required components are available in the image. In practice, this
means that if a user installs systemd-boot, the kernel, and dracut,
they'll get a bootable image.

27 files changed:
.github/mkosi.conf.d/10-common.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-alma.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-arch.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-centos.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-debian.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-fedora.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-opensuse.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-rocky.conf [new file with mode: 0644]
.github/mkosi.conf.d/20-ubuntu.conf [new file with mode: 0644]
.github/workflows/ci.yml
NEWS.md
docs/bootable.md [new file with mode: 0644]
mkosi.md
mkosi/__init__.py
mkosi/backend.py
mkosi/config.py
mkosi/distributions/arch.py
mkosi/distributions/centos.py
mkosi/distributions/debian.py
mkosi/distributions/fedora.py
mkosi/distributions/gentoo.py
mkosi/distributions/mageia.py
mkosi/distributions/openmandriva.py
mkosi/distributions/opensuse.py
mkosi/distributions/ubuntu.py
mkosi/resources/dpkg-reconfigure-dracut.install [deleted file]
tests/test_parse_load_args.py

diff --git a/.github/mkosi.conf.d/10-common.conf b/.github/mkosi.conf.d/10-common.conf
new file mode 100644 (file)
index 0000000..f8e66be
--- /dev/null
@@ -0,0 +1,9 @@
+[Output]
+CacheDirectory=mkosi.cache
+KernelCommandLine=console=hvc0
+                  systemd.unit=mkosi-check-and-shutdown.service
+                  systemd.log_target=console
+                  systemd.default_standard_output=journal+console
+
+[Host]
+Autologin=yes
diff --git a/.github/mkosi.conf.d/20-alma.conf b/.github/mkosi.conf.d/20-alma.conf
new file mode 100644 (file)
index 0000000..b41f6be
--- /dev/null
@@ -0,0 +1,12 @@
+[Match]
+Distribution=alma
+
+[Distribution]
+Repositories=epel
+
+[Content]
+Packages=kernel
+         systemd
+         systemd-boot
+         systemd-udev
+         dracut
diff --git a/.github/mkosi.conf.d/20-arch.conf b/.github/mkosi.conf.d/20-arch.conf
new file mode 100644 (file)
index 0000000..fb8471f
--- /dev/null
@@ -0,0 +1,7 @@
+[Match]
+Distribution=arch
+
+[Content]
+Packages=linux
+         systemd
+         dracut
diff --git a/.github/mkosi.conf.d/20-centos.conf b/.github/mkosi.conf.d/20-centos.conf
new file mode 100644 (file)
index 0000000..a2cefed
--- /dev/null
@@ -0,0 +1,9 @@
+[Match]
+Distribution=centos
+
+[Content]
+Packages=kernel
+         systemd
+         systemd-boot
+         systemd-udev
+         dracut
diff --git a/.github/mkosi.conf.d/20-debian.conf b/.github/mkosi.conf.d/20-debian.conf
new file mode 100644 (file)
index 0000000..d7c3589
--- /dev/null
@@ -0,0 +1,11 @@
+[Match]
+Distribution=debian
+
+[Content]
+Packages=linux-image-cloud-amd64
+         systemd
+         systemd-boot
+         systemd-sysv
+         udev
+         dracut
+         dbus
diff --git a/.github/mkosi.conf.d/20-fedora.conf b/.github/mkosi.conf.d/20-fedora.conf
new file mode 100644 (file)
index 0000000..c2a7e08
--- /dev/null
@@ -0,0 +1,10 @@
+[Match]
+Distribution=fedora
+
+[Content]
+Packages=kernel
+         systemd
+         systemd-boot
+         systemd-udev
+         dracut
+         util-linux
diff --git a/.github/mkosi.conf.d/20-opensuse.conf b/.github/mkosi.conf.d/20-opensuse.conf
new file mode 100644 (file)
index 0000000..829dc2e
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Distribution=opensuse
+
+[Content]
+Packages=kernel-default
+         dracut
+         systemd
+         udev
diff --git a/.github/mkosi.conf.d/20-rocky.conf b/.github/mkosi.conf.d/20-rocky.conf
new file mode 100644 (file)
index 0000000..0e515d5
--- /dev/null
@@ -0,0 +1,12 @@
+[Match]
+Distribution=rocky
+
+[Distribution]
+Repositories=epel
+
+[Content]
+Packages=kernel
+         systemd
+         systemd-boot
+         systemd-udev
+         dracut
diff --git a/.github/mkosi.conf.d/20-ubuntu.conf b/.github/mkosi.conf.d/20-ubuntu.conf
new file mode 100644 (file)
index 0000000..24c4fe5
--- /dev/null
@@ -0,0 +1,13 @@
+[Match]
+Distribution=ubuntu
+
+[Distribution]
+Repositories=main,universe
+
+[Content]
+Packages=linux-virtual
+         systemd
+         systemd-sysv
+         udev
+         dracut
+         dbus
index 69c40ba639d5008b768b18c5aa7749a8089360fd..d3400c376a161353694cce8fbfeb9337385c697e 100644 (file)
@@ -102,6 +102,9 @@ jobs:
     concurrency:
       group: ${{ github.workflow }}-${{ matrix.distro }}-${{ matrix.format }}-${{ matrix.prebuilt-initrd }}-${{ github.ref }}
       cancel-in-progress: true
+    defaults:
+      run:
+        working-directory: ./.github
     strategy:
       fail-fast: false
       matrix:
@@ -124,10 +127,6 @@ jobs:
           - no
           - yes
         exclude:
-          # Debian prebuilt initrds are so large they cause OOMs.
-          # TODO: Revisit this if Debian ever decides to compress their kernel modules.
-          - distro: debian
-            prebuilt-initrd: yes
           - distro: gentoo
             prebuilt-initrd: yes
 
@@ -170,55 +169,30 @@ jobs:
 
     # Do a manual install so we have the latest changes from the pull request available.
     - name: Install
-      run: sudo python3 -m pip install .
+      run: sudo python3 -m pip install ..
 
     - name: Build ${{ matrix.distro }} initrd
       if: matrix.prebuilt-initrd == 'yes'
+      # Run the build in .github/workflows/ so we don't pick up any of the configuration files in .github/
       run: python3 -m mkosi -d ${{ matrix.distro }} -t cpio -p systemd -p udev -p kmod -o $PWD/initrd build
+      working-directory: ./.github/workflows
 
     - name: Configure ${{ matrix.distro }}/${{ matrix.format }}
       run: |
-        mkdir -p mkosi.conf.d
-
-        tee mkosi.conf.d/mkosi.conf <<- EOF
+        tee mkosi.conf.d/00-ci.conf <<- EOF
         [Distribution]
         Distribution=${{ matrix.distro }}
 
         [Output]
         Format=${{ matrix.format }}
-        Bootable=yes
-        KernelCommandLine=systemd.unit=mkosi-check-and-shutdown.service
-                          systemd.log_target=console
-                          systemd.default_standard_output=journal+console
-
-        [Host]
-        Autologin=yes
-
-        [Content]
-        ExtraTrees=.github/mkosi.extra
-        EOF
-
-        mkdir -p mkosi.skeleton/etc/portage
-
-        tee mkosi.skeleton/etc/portage/binrepos.conf <<- EOF
-        [binhost]
-        sync-uri = https://raw.githubusercontent.com/257/binpkgs/master
         EOF
 
     - name: Configure ${{ matrix.distro }}/${{ matrix.format }} initrd
       if: matrix.prebuilt-initrd == 'yes'
       run: |
-        tee mkosi.conf.d/initrd.conf <<- EOF
-        [Distribution]
-        Initrds=initrd.zst
-        EOF
-
-    - name: Configure EPEL
-      if: matrix.distro == 'centos' || matrix.distro == 'rocky' || matrix.distro == 'alma'
-      run: |
-        tee mkosi.conf.d/epel.conf <<- EOF
+        tee mkosi.conf.d/00-initrd.conf <<- EOF
         [Distribution]
-        Repositories=epel
+        Initrds=workflows/initrd.zst
         EOF
 
     - name: Build ${{ matrix.distro }}/${{ matrix.format }}
@@ -229,7 +203,7 @@ jobs:
     # FIXME: Remove when Arch/Debian/Ubuntu ship systemd v253
     - name: Mask systemd-resolved
       if: matrix.format == 'directory'
-      run: sudo systemctl --root mkosi.output/${{ matrix.distro }}~*/image mask systemd-resolved
+      run: sudo systemctl --root image mask systemd-resolved
 
     - name: Boot ${{ matrix.distro }}/${{ matrix.format }} systemd-nspawn
       if: matrix.format == 'disk' || matrix.format == 'directory'
diff --git a/NEWS.md b/NEWS.md
index 7a09833a5ab2b344b5541ceb651d16e30b642c93..dc0849ec30a66305c7ea0d00fbea939bb63ab96a 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -65,6 +65,9 @@
 - Removed `--qcow2` option in favor of supporting only raw disk images as the disk image output format.
 - Removed `--bmap` option as it can be trivially added manually by utilizing a finalize script.
 - The `never` value for `--with-network` was spun of into its own custom option `--cache-only`.
+- Removed `--bootable` in favor of automatically generating a bootable image if all the necessary packages
+  are installed. Documentation was added in docs/bootable.ld on how a bootable image can be generated on
+  mainstream distros.
 
 ## v14
 
diff --git a/docs/bootable.md b/docs/bootable.md
new file mode 100644 (file)
index 0000000..43ed45b
--- /dev/null
@@ -0,0 +1,73 @@
+# Building a bootable image on different distros
+
+To build a bootable image, you'll need to install a list of packages that differs depending on the
+distribution. We give an overview here of what's needed to generate a bootable image for some common
+distributions:
+
+## Arch
+
+```
+[Content]
+Packages=linux
+         systemd
+         dracut
+```
+
+## Fedora
+
+```
+[Content]
+Packages=kernel
+         systemd
+         systemd-boot
+         systemd-udev
+         dracut
+         util-linux
+```
+
+## CentOS
+
+```
+[Content]
+Packages=kernel
+         systemd
+         systemd-boot
+         systemd-udev
+         dracut
+```
+
+## Debian
+
+```
+[Content]
+Packages=linux-image-generic
+         systemd
+         systemd-boot
+         systemd-sysv
+         udev
+         dracut
+         dbus
+```
+
+## Ubuntu
+
+```
+[Content]
+Repositories=main,universe
+Packages=linux-image-generic
+         systemd
+         systemd-sysv
+         udev
+         dracut
+         dbus
+```
+
+## Opensuse
+
+```
+[Content]
+Packages=kernel-default
+         dracut
+         systemd
+         udev
+```
index 8bf673721a8a76fdf3ac110a4bb4a9e196ba4c6c..caba56ad961d0cfd75b2bdf1349b66e1c8fecd61 100644 (file)
--- a/mkosi.md
+++ b/mkosi.md
@@ -75,9 +75,7 @@ The following command line verbs are known:
 
 : Similar to `boot`, but uses `qemu` to boot up the image, i.e. instead of
   container virtualization virtual machine virtualization is used. This verb is
-  only supported for images that contain a boot loader, i.e. those built with
-  `Bootable=yes` (see below). This command must be executed as `root` unless
-  the image already exists and `-f` is not specified. Any options specified
+  only supported for disk images that contain a boot loader. Any options specified
   after the `qemu` verb are appended to the `qemu` invocation.
 
 `ssh`
@@ -372,21 +370,17 @@ a boolean argument: either "1", "yes", or "true" to enable, or "0",
 
   <!--  FIXME: allow `Force=<n>` -->
 
-`Bootable=`, `--bootable`, `-b`
-
-: Generate a bootable image for UEFI systems.
-
 `KernelCommandLine=`, `--kernel-command-line=`
 
-: Use the specified kernel command line when building bootable
-  images. By default command line arguments get appended. To remove all
-  arguments from the current list pass "!\*". To remove specific arguments
-  add a space separated list of "!" prefixed arguments.
-  For example adding "!\* console=ttyS0 rw" to a `mkosi.conf` file or the
-  command line arguments passes "console=ttyS0 rw" to the kernel in any
-  case. Just adding "console=ttyS0 rw" would append these two arguments
-  to the kernel command line created by lower priority configuration
-  files or previous `KernelCommandLine=` command line arguments.
+: Use the specified kernel command line when building images. By default
+  command line arguments get appended. To remove all arguments from the
+  current list pass "!\*". To remove specific arguments add a space
+  separated list of "!" prefixed arguments. For example adding
+  "!\* console=ttyS0 rw" to a `mkosi.conf` file or the command line
+  arguments passes "console=ttyS0 rw" to the kernel in any case. Just
+  adding "console=ttyS0 rw" would append these two arguments to the kernel
+  command line created by lower priority configuration files or previous
+  `KernelCommandLine=` command line arguments.
 
 `SecureBoot=`, `--secure-boot`
 
@@ -989,38 +983,6 @@ that packages `emerge` may be used to build *Gentoo* images.
 
 Currently, *Fedora Linux* packages all relevant tools as of Fedora 28.
 
-## Compatibility
-
-Legacy concepts are avoided: generated images use *GPT* disk labels
-(and no *MBR* labels), and only systemd-based images may be generated.
-
-All generated *GPT* disk images may be booted in a local
-container directly with:
-
-```bash
-systemd-nspawn -bi image.raw
-```
-
-Additionally, bootable *GPT* disk images (as created with the
-`--bootable` flag) work when booted directly by *EFI* systems,
-for example in *KVM* via:
-
-```bash
-qemu-kvm -m 512 -smp 2 -bios /usr/share/edk2/ovmf/OVMF_CODE.fd -drive format=raw,file=image.raw
-```
-
-*EFI* bootable *GPT* images are larger than plain *GPT* images, as
-they additionally carry an *EFI* system partition containing a
-boot loader, as well as a kernel, kernel modules, udev and
-more.
-
-All directory or btrfs subvolume images may be booted directly
-with:
-
-```bash
-systemd-nspawn -bD image
-```
-
 # Files
 
 To make it easy to build images for development versions of your
@@ -1323,13 +1285,13 @@ variables:
 Create and run a raw *GPT* image with *ext4*, as `image.raw`:
 
 ```bash
-# mkosi --bootable --incremental boot
+# mkosi -p systemd --incremental boot
 ```
 
 Create and run a bootable *GPT* image, as `foobar.raw`:
 
 ```bash
-# mkosi --format disk --bootable -o foobar.raw
+# mkosi -d fedora -p kernel -p systemd -p udev -o foobar.raw
 # mkosi --output foobar.raw boot
 # mkosi --output foobar.raw qemu
 ```
@@ -1360,10 +1322,9 @@ Release=24
 
 [Output]
 Format=disk
-Bootable=yes
 
 [Content]
-Packages=openssh-clients,httpd
+Packages=kernel,systemd,systemd-udev,openssh-clients,httpd
 BuildPackages=make,gcc,libcurl-devel
 EOF
 # cat >mkosi.build <<EOF
@@ -1375,7 +1336,7 @@ make -j `nproc`
 make install
 EOF
 # chmod +x mkosi.build
-# mkosi --bootable --incremental boot
+# mkosi --incremental boot
 # systemd-nspawn -bi image.raw
 ```
 
index 43d574d56922777a3be3b4be531c532a9a52c1cf..6aa218885520c40cd24ff5cdf9cedd58f50a942e 100644 (file)
@@ -75,28 +75,6 @@ MKOSI_COMMANDS_NEED_BUILD = (Verb.shell, Verb.boot, Verb.qemu, Verb.serve)
 MKOSI_COMMANDS_SUDO = (Verb.shell, Verb.boot)
 MKOSI_COMMANDS_CMDLINE = (Verb.build, Verb.shell, Verb.boot, Verb.qemu, Verb.ssh)
 
-DRACUT_SYSTEMD_EXTRAS = [
-    "/usr/bin/systemd-ask-password",
-    "/usr/bin/systemd-repart",
-    "/usr/bin/systemd-tty-ask-password-agent",
-    "/usr/lib/systemd/system-generators/systemd-veritysetup-generator",
-    "/usr/lib/systemd/system/initrd-root-fs.target.wants/systemd-repart.service",
-    "/usr/lib/systemd/system/initrd-usr-fs.target",
-    "/usr/lib/systemd/system/initrd.target.wants/systemd-pcrphase-initrd.service",
-    "/usr/lib/systemd/system/sysinit.target.wants/veritysetup.target",
-    "/usr/lib/systemd/system/systemd-pcrphase-initrd.service",
-    "/usr/lib/systemd/system/systemd-repart.service",
-    "/usr/lib/systemd/system/systemd-volatile-root.service",
-    "/usr/lib/systemd/system/veritysetup.target",
-    "/usr/lib/systemd/systemd-pcrphase",
-    "/usr/lib/systemd/systemd-veritysetup",
-    "/usr/lib/systemd/systemd-volatile-root",
-    "/usr/lib64/libtss2-esys.so.0",
-    "/usr/lib64/libtss2-mu.so.0",
-    "/usr/lib64/libtss2-rc.so.0",
-    "/usr/lib64/libtss2-tcti-device.so.0",
-]
-
 
 T = TypeVar("T")
 
@@ -177,35 +155,6 @@ def configure_hostname(state: MkosiState) -> None:
             etc_hostname.write_text(state.config.hostname + "\n")
 
 
-def configure_dracut(state: MkosiState, cached: bool) -> None:
-    if not state.config.bootable or state.config.initrds:
-        return
-
-    if not state.config.cache_initrd and state.for_cache:
-        return
-
-    if state.config.cache_initrd and cached:
-        return
-
-    dracut_dir = state.root / "etc/dracut.conf.d"
-    dracut_dir.mkdir(mode=0o755, exist_ok=True)
-
-    dracut_dir.joinpath("30-mkosi-qemu.conf").write_text('add_dracutmodules+=" qemu "\n')
-
-    with dracut_dir.joinpath("30-mkosi-systemd-extras.conf").open("w") as f:
-        for extra in DRACUT_SYSTEMD_EXTRAS:
-            f.write(f'install_optional_items+=" {extra} "\n')
-        f.write('install_optional_items+=" /etc/systemd/system.conf "\n')
-        if state.root.joinpath("etc/systemd/system.conf.d").exists():
-            for conf in state.root.joinpath("etc/systemd/system.conf.d").iterdir():
-                f.write(f'install_optional_items+=" {Path("/") / conf.relative_to(state.root)} "\n')
-
-    # efivarfs must be present in order to GPT root discovery work
-    dracut_dir.joinpath("30-mkosi-efivarfs.conf").write_text(
-        '[[ $(modinfo -k "$kernel" -F filename efivarfs 2>/dev/null) == /* ]] && add_drivers+=" efivarfs "\n'
-    )
-
-
 def prepare_tree_root(state: MkosiState) -> None:
     if state.config.output_format == OutputFormat.subvolume:
         with complete_step("Setting up OS tree root…"):
@@ -523,17 +472,19 @@ def run_finalize_script(state: MkosiState) -> None:
 
 
 def install_boot_loader(state: MkosiState) -> None:
-    if not state.config.bootable or state.for_cache:
+    if state.for_cache:
+        return
+
+    directory = state.root / "usr/lib/systemd/boot/efi"
+    if not directory.exists():
         return
 
     if state.config.secure_boot:
         assert state.config.secure_boot_key
         assert state.config.secure_boot_certificate
 
-        p = state.root / "usr/lib/systemd/boot/efi"
-
         with complete_step("Signing systemd-boot binaries…"):
-            for f in itertools.chain(p.glob('*.efi'), p.glob('*.EFI')):
+            for f in itertools.chain(directory.glob('*.efi'), directory.glob('*.EFI')):
                 run(
                     [
                         "sbsign",
@@ -755,9 +706,6 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None:
     # benefit that they can be signed like normal EFI binaries, and can encode everything necessary to boot a
     # specific root device, including the root hash.
 
-    if not state.config.bootable:
-        return
-
     # The roothash is specific to the final image so we cannot cache this step.
     if state.for_cache:
         return
@@ -1159,14 +1107,13 @@ def load_args(args: argparse.Namespace) -> MkosiConfig:
     if args.cmdline and args.verb not in MKOSI_COMMANDS_CMDLINE:
         die(f"Parameters after verb are only accepted for {list_to_string(verb.name for verb in MKOSI_COMMANDS_CMDLINE)}.")
 
-    if args.bootable:
-        if args.verb == Verb.qemu and args.output_format in (
-            OutputFormat.directory,
-            OutputFormat.subvolume,
-            OutputFormat.tar,
-            OutputFormat.cpio,
-        ):
-            die("Directory, subvolume, tar, cpio, and plain squashfs images cannot be booted.", MkosiNotSupportedException)
+    if args.verb == Verb.qemu and args.output_format in (
+        OutputFormat.directory,
+        OutputFormat.subvolume,
+        OutputFormat.tar,
+        OutputFormat.cpio,
+    ):
+        die("Directory, subvolume, tar, cpio, and plain squashfs images cannot be booted in qemu.", MkosiNotSupportedException)
 
     if shutil.which("bsdtar") and args.distribution == Distribution.openmandriva and args.tar_strip_selinux_context:
         die("Sorry, bsdtar on OpenMandriva is incompatible with --tar-strip-selinux-context", MkosiNotSupportedException)
@@ -1267,9 +1214,6 @@ def load_args(args: argparse.Namespace) -> MkosiConfig:
         if not args.output_format == OutputFormat.disk:
             die("Sorry, can't boot non-disk images with qemu.", MkosiNotSupportedException)
 
-    if needs_build(args) and args.verb == Verb.qemu and not args.bootable:
-        die("Images built without the --bootable option cannot be booted using qemu", MkosiNotSupportedException)
-
     if args.repo_dirs and not (is_dnf_distribution(args.distribution) or args.distribution == Distribution.arch):
         die("--repo-dir is only supported on DNF based distributions and Arch")
 
@@ -1478,11 +1422,8 @@ def print_summary(config: MkosiConfig) -> None:
     print("               Incremental:", yes_no(config.incremental))
     print("               Compression:", should_compress_output(config) or "no")
 
-    print("                  Bootable:", yes_no(config.bootable))
-
-    if config.bootable:
-        print("       Kernel Command Line:", " ".join(config.kernel_command_line))
-        print("           UEFI SecureBoot:", yes_no(config.secure_boot))
+    print("       Kernel Command Line:", " ".join(config.kernel_command_line))
+    print("           UEFI SecureBoot:", yes_no(config.secure_boot))
 
     if config.secure_boot_key:
         print("       SecureBoot Sign Key:", config.secure_boot_key)
@@ -1643,15 +1584,15 @@ def configure_initrd(state: MkosiState) -> None:
 
 
 def run_kernel_install(state: MkosiState, cached: bool) -> None:
-    if not state.config.bootable:
-        return
-
     if not state.config.cache_initrd and state.for_cache:
         return
 
     if state.config.cache_initrd and cached:
         return
 
+    if state.config.initrds:
+        return
+
     # CentOS Stream 8 has an old version of kernel-install that unconditionally writes initrds to
     # /boot/<machine-id>/<kver>, so let's detect that and move them to the correct location.
 
@@ -1660,16 +1601,14 @@ def run_kernel_install(state: MkosiState, cached: bool) -> None:
     else:
         machine_id = None
 
-    # Fedora unconditionally pulls in dracut when installing a kernel and upstream dracut refuses to skip
-    # running when implement KERNEL_INSTALL_INITRD_GENERATOR support so let's disable it manually here if the
-    # user provided initrds.
-
-    if state.config.initrds:
-        for p in state.root.joinpath("usr/lib/kernel/install.d").iterdir():
-            if "dracut" in p.name:
-                install = state.root.joinpath("etc/kernel/install.d")
-                install.mkdir(parents=True, exist_ok=True)
-                install.joinpath(p.name).symlink_to("/dev/null")
+    # kernel-install on Debian/Ubuntu does not rebuild the dracut initrd, so we do it manually here.
+    if (state.root.joinpath("usr/bin/dracut").exists() and
+        state.config.distribution in (Distribution.ubuntu, Distribution.debian) and
+        not state.root.joinpath("usr/lib/kernel/install.d/50-dracut.install").exists() and
+        not state.root.joinpath("etc/kernel/install.d/50-dracut.install").exists()):
+        with complete_step("Running dpkg-reconfigure dracut…"):
+            run_workspace_command(state, ["dpkg-reconfigure", "dracut"], env=dict(hostonly_l="no"))
+            return
 
     with complete_step("Running kernel-install…"):
         for kver, kimg in gen_kernel_images(state):
@@ -1678,16 +1617,12 @@ def run_kernel_install(state: MkosiState, cached: bool) -> None:
             if ARG_DEBUG:
                 cmd += ["--verbose"]
 
-            run_workspace_command(state, cmd)
+            # Make dracut think --no-host-only was passed via the CLI.
+            run_workspace_command(state, cmd, env=dict(hostonly_l="no"))
 
             if machine_id and (p := state.root / "boot" / machine_id / kver / "initrd").exists():
                 shutil.move(p, state.root / state.installer.initrd_path(kver))
 
-    if state.config.initrds:
-        for p in state.root.joinpath("etc/kernel/install.d").iterdir():
-            if "dracut" in p.name:
-                os.unlink(p)
-
     if machine_id and (p := state.root / "boot" / machine_id).exists():
         shutil.rmtree(p)
 
@@ -1764,8 +1699,6 @@ def invoke_repart(state: MkosiState, skip: Sequence[str] = [], split: bool = Fal
         cmdline += ["--private-key", state.config.secure_boot_key]
     if state.config.secure_boot_certificate:
         cmdline += ["--certificate", state.config.secure_boot_certificate]
-    if not state.config.bootable:
-        cmdline += ["--exclude-partitions=esp,xbootldr"]
     if skip:
         cmdline += ["--defer-partitions", ",".join(skip)]
     if split and state.config.split_artifacts:
@@ -1778,18 +1711,23 @@ def invoke_repart(state: MkosiState, skip: Sequence[str] = [], split: bool = Fal
         definitions = state.workspace / "repart-definitions"
         if not definitions.exists():
             definitions.mkdir()
-            definitions.joinpath("00-esp.conf").write_text(
-                dedent(
-                    """\
-                    [Partition]
-                    Type=esp
-                    Format=vfat
-                    CopyFiles=/boot:/
-                    SizeMinBytes=1024M
-                    SizeMaxBytes=1024M
-                    """
+            bootdir = state.root.joinpath("boot/EFI/BOOT")
+
+            if bootdir.exists() and any(bootdir.iterdir()) and any(gen_kernel_images(state)):
+                # If we have at least one kernel images and a bootloader, let's generate an ESP partition.
+                definitions.joinpath("00-esp.conf").write_text(
+                    dedent(
+                        """\
+                        [Partition]
+                        Type=esp
+                        Format=vfat
+                        CopyFiles=/boot:/
+                        SizeMinBytes=1024M
+                        SizeMaxBytes=1024M
+                        """
+                    )
                 )
-            )
+
             definitions.joinpath("10-root.conf").write_text(
                 dedent(
                     f"""\
@@ -1843,7 +1781,6 @@ def build_image(state: MkosiState, *, manifest: Optional[Manifest] = None) -> No
         configure_hostname(state)
         configure_root_password(state)
         configure_autologin(state)
-        configure_dracut(state, cached)
         configure_initrd(state)
         run_build_script(state)
         install_build_dest(state)
index b37a52b2c5c4edbdc215fbab2f9491d2939fe607..49c3d28da50271ad760dcd095a9ed8eea2017ad9 100644 (file)
@@ -216,7 +216,6 @@ class MkosiConfig:
     manifest_format: list[ManifestFormat]
     output: Path
     output_dir: Optional[Path]
-    bootable: bool
     kernel_command_line: list[str]
     secure_boot: bool
     secure_boot_key: Optional[Path]
index 82d7ce6d209a7489b5dc2ccc15c6e214d0a46f9d..0c4487f8a6aa0dddebceaa28ae2bf0814cee02e8 100644 (file)
@@ -380,11 +380,6 @@ class MkosiConfigParser:
             parse=config_make_path_parser(required=False),
             paths=("mkosi.workspace",),
         ),
-        MkosiConfigSetting(
-            dest="bootable",
-            section="Output",
-            parse=config_parse_boolean,
-        ),
         MkosiConfigSetting(
             dest="kernel_command_line",
             section="Output",
@@ -932,13 +927,6 @@ class MkosiConfigParser:
             help="Workspace directory",
             action=action,
         )
-        group.add_argument(
-            "-b", "--bootable",
-            metavar="BOOL",
-            help="Make image bootable on EFI",
-            nargs="?",
-            action=action,
-        )
         group.add_argument(
             "--kernel-command-line",
             metavar="OPTIONS",
index 02a19e739a20ccdcd93e202392250981f6a7a5cc..2efabf041add932cb288c990a2f68ded7bc60a6e 100644 (file)
@@ -89,28 +89,11 @@ def install_arch(state: MkosiState) -> None:
     packages = state.config.packages.copy()
     add_packages(state.config, packages, "filesystem")
 
-    if state.config.bootable and not state.config.initrds:
-        add_packages(state.config, packages, "dracut")
-
-    official_kernel_packages = {
-        "linux",
-        "linux-lts",
-        "linux-hardened",
-        "linux-zen",
-    }
-
-    has_kernel_package = official_kernel_packages.intersection(state.config.packages)
-    if state.config.bootable and not has_kernel_package:
-        # No user-specified kernel
-        add_packages(state.config, packages, "linux")
-
     if state.config.ssh:
         add_packages(state.config, packages, "openssh")
 
     invoke_pacman(state, packages)
 
-    state.root.joinpath("etc/pacman.d/mirrorlist").write_text(f"Server = {state.config.mirror}/$repo/os/$arch\n")
-
 
 def invoke_pacman(state: MkosiState, packages: Sequence[str]) -> None:
     cmdline: list[PathString] = [
index 43260c74fcd12c12b7e64dcc49cce26af17ac3ba..ae83a3417891b5ac92e7606eb1147a78290a144c 100644 (file)
@@ -70,7 +70,7 @@ class CentosInstaller(DistributionInstaller):
         # systemd-gpt-auto-generator only started applying the GPT partition read-only flag to gpt-auto
         # mounts from v240 onwards, while CentOS Stream 8 ships systemd v239, so we have to nudge gpt-auto to
         # mount the root partition rw by default.
-        if state.config.bootable and int(state.config.release) <= 8:
+        if int(state.config.release) <= 8:
             kcl += ["rw"]
 
         return kcl + DistributionInstaller.kernel_command_line(state)
@@ -96,13 +96,6 @@ class CentosInstaller(DistributionInstaller):
 
         packages = state.config.packages.copy()
         add_packages(state.config, packages, "filesystem")
-        if state.config.bootable:
-            add_packages(state.config, packages, "kernel")
-            if not state.config.initrds:
-                add_packages(state.config, packages, "dracut", "dracut-config-generic")
-            add_packages(state.config, packages, "systemd-udev", conditional="systemd")
-            if release >= 9:
-                add_packages(state.config, packages, "systemd-boot", conditional="systemd")
         if state.config.ssh:
             add_packages(state.config, packages, "openssh-server")
 
index 50e4dc2340c739a592112b6dc7093c46e984087f..51cad582c8dd08bf0f04fdbe0f6a942b9171830a 100644 (file)
@@ -9,21 +9,13 @@ from textwrap import dedent
 
 from mkosi.backend import MkosiState, add_packages
 from mkosi.distributions import DistributionInstaller
-from mkosi.install import install_skeleton_trees, write_resource
+from mkosi.install import install_skeleton_trees
 from mkosi.run import run, run_with_apivfs
 from mkosi.types import _FILE, CompletedProcess, PathString
 
 
 class DebianInstaller(DistributionInstaller):
     needs_skeletons_after_bootstrap = True
-    repositories_for_boot: set[str] = set()
-
-    @classmethod
-    def _add_default_kernel_package(cls, state: MkosiState, packages: list[str]) -> None:
-        # Don't pull in a kernel if users specify one, but otherwise try to pick a default
-        # one - try to infer from the architecture.
-        if not any(package.startswith("linux-image") for package in packages):
-            add_packages(state.config, packages, f"linux-image-{DEBIAN_KERNEL_ARCHITECTURES[state.config.architecture]}")
 
     @classmethod
     def filesystem(cls) -> str:
@@ -46,9 +38,6 @@ class DebianInstaller(DistributionInstaller):
         dpkg_io_conf.write_text("force-unsafe-io\n")
 
         repos = {"main", *state.config.repositories}
-        # Ubuntu needs the 'universe' repo to install 'dracut'
-        if state.config.bootable:
-            repos |= cls.repositories_for_boot
 
         # debootstrap fails if a base image is used with an already populated root, so skip it.
         if state.config.base_image is None:
@@ -84,11 +73,6 @@ class DebianInstaller(DistributionInstaller):
         packages = state.config.packages.copy()
         add_packages(state.config, packages, "base-files")
 
-        if state.config.bootable:
-            if not state.config.initrds:
-                add_packages(state.config, packages, "dracut", "dracut-config-generic")
-            cls._add_default_kernel_package(state, packages)
-
         if state.config.ssh:
             add_packages(state.config, packages, "openssh-server")
 
@@ -122,7 +106,7 @@ class DebianInstaller(DistributionInstaller):
             with dpkg_nodoc_conf.open("w") as f:
                 f.writelines(f"path-exclude {d}/*\n" for d in doc_paths)
 
-        if state.config.bootable and state.config.base_image is None:
+        if state.config.base_image is None:
             # systemd-boot won't boot unified kernel images generated without a BUILD_ID or VERSION_ID in
             # /etc/os-release. Build one with the mtime of os-release if we don't find them.
             with state.root.joinpath("etc/os-release").open("r+") as f:
@@ -140,12 +124,8 @@ class DebianInstaller(DistributionInstaller):
 
         invoke_apt(state, "get", "update", ["--assume-yes"])
 
-        if state.config.bootable:
-            # Ensure /efi exists so that the ESP is mounted there, and we never run dpkg -i on vfat
-            state.root.joinpath("efi").mkdir(mode=0o755)
-
-        if state.config.bootable:
-            add_apt_package_if_exists(state, packages, "systemd-boot")
+        # Ensure /efi exists so that the ESP is mounted there, and we never run dpkg -i on vfat
+        state.root.joinpath("efi").mkdir(mode=0o755, exist_ok=True)
 
         invoke_apt(state, "get", "install", ["--assume-yes", "--no-install-recommends", *packages])
 
@@ -172,10 +152,6 @@ class DebianInstaller(DistributionInstaller):
         presetdir.mkdir(exist_ok=True, mode=0o755)
         presetdir.joinpath("99-mkosi-disable.preset").write_text("disable *")
 
-        if state.config.bootable and not state.config.initrds:
-            write_resource(state.root / "etc/kernel/install.d/50-mkosi-dpkg-reconfigure-dracut.install",
-                           "mkosi.resources", "dpkg-reconfigure-dracut.install", executable=True)
-
     @classmethod
     def install_packages(cls, state: MkosiState, packages: Sequence[str]) -> None:
         invoke_apt(state, "get", "install", ["--assume-yes", "--no-install-recommends", *packages])
@@ -288,6 +264,7 @@ def invoke_apt(
         APT_CONFIG=config_file,
         DEBIAN_FRONTEND="noninteractive",
         DEBCONF_INTERACTIVE_SEEN="true",
+        KERNEL_INSTALL_BYPASS="1",
         INITRD="No",
     )
 
index df9c46e48ae285f548941aee4bad7de8b316326c..cf6993b5c5380aeaab40123846b477cdc6bffd3e 100644 (file)
@@ -99,11 +99,6 @@ def install_fedora(state: MkosiState) -> None:
     packages = state.config.packages.copy()
     add_packages(state.config, packages, "filesystem")
 
-    if state.config.bootable:
-        add_packages(state.config, packages, "kernel-core", "kernel-modules")
-        add_packages(state.config, packages, "systemd-udev", conditional="systemd")
-        if not state.config.initrds:
-            add_packages(state.config, packages, "dracut", "dracut-config-generic")
     if state.config.ssh:
         add_packages(state.config, packages, "openssh-server")
 
index 3da42679953cacfb114ebb23adb5c874c83a450c..c7009bcd08bbd67f0f65a4247adc9a08d712fd6b 100644 (file)
@@ -36,7 +36,6 @@ class Gentoo:
     profile_path: Path
     root: Path
     pkgs: dict[str, list[str]] = {}
-    dracut_atom = "sys-kernel/dracut"
 
     EMERGE_UPDATE_OPTS = [
         "--update",
index 597556d043f40843a5b1e63390d9728409c4711e..14a8200bccfd1f4bffb7f8cf805b3eeee49de885 100644 (file)
@@ -59,14 +59,6 @@ def install_mageia(state: MkosiState) -> None:
 
     packages = state.config.packages.copy()
     add_packages(state.config, packages, "filesystem")
-    if state.config.bootable and not state.config.initrds:
-        add_packages(state.config, packages, "dracut")
-        # Mageia ships /etc/50-mageia.conf that omits systemd from the initramfs and disables hostonly.
-        # We override that again so our defaults get applied correctly on Mageia as well.
-        state.root.joinpath("etc/dracut.conf.d/51-mkosi-override-mageia.conf").write_text(
-            'hostonly=no\n'
-            'omit_dracutmodules=""\n'
-        )
     if state.config.ssh:
         add_packages(state.config, packages, "openssh-server")
 
index 987038fc047ab784d59fef675b48bb96741137bd..ea0d143bb25b58eb324823cc11b2659b7775c92e 100644 (file)
@@ -61,11 +61,6 @@ def install_openmandriva(state: MkosiState) -> None:
     packages = state.config.packages.copy()
     # well we may use basesystem here, but that pulls lot of stuff
     add_packages(state.config, packages, "filesystem")
-    if state.config.bootable:
-        add_packages(state.config, packages, "systemd-boot", "systemd-cryptsetup", conditional="systemd")
-        add_packages(state.config, packages, "kernel-release-server", "timezone")
-        if not state.config.initrds:
-            add_packages(state.config, packages, "dracut")
     if state.config.ssh:
         add_packages(state.config, packages, "openssh-server")
 
index 5710907acfc7f3c1e7ed81513270f406bf0f19cb..197295551c662330a0c2e78d56a243f21197dae1 100644 (file)
@@ -62,7 +62,7 @@ def invoke_zypper(state: MkosiState,
                   with_apivfs: bool = False) -> None:
 
     cmdline: list[PathString] = ["zypper", "--root", state.root, *global_opts, verb, *verb_opts, *args]
-    env={"ZYPP_CONF": state.root.joinpath("etc/zypp/zypp.conf")}
+    env = dict(ZYPP_CONF=str(state.root / "etc/zypp/zypp.conf"), KERNEL_INSTALL_BYPASS="1")
 
     if with_apivfs:
         run_with_apivfs(state, cmdline, env=env)
@@ -171,11 +171,6 @@ def install_opensuse(state: MkosiState) -> None:
     if state.config.base_image is None:
         add_packages(state.config, packages, "filesystem")
 
-        if state.config.bootable:
-            add_packages(state.config, packages, "kernel-default")
-            if not state.config.initrds:
-                add_packages(state.config, packages, "dracut")
-
         if state.config.ssh:
             add_packages(state.config, packages, "openssh-server")
 
@@ -198,8 +193,3 @@ def install_opensuse(state: MkosiState) -> None:
             return line
 
         patch_file(state.root / "etc/pam.d/common-auth", jj)
-
-    if state.config.bootable and not state.config.initrds:
-        dracut_dir = state.root / "etc/dracut.conf.d"
-        dracut_dir.mkdir(mode=0o755, exist_ok=True)
-        dracut_dir.joinpath("30-mkosi-opensuse.conf").write_text('hostonly=no\n')
index 6b49418d7adb5ac1f7e71f7a3dcf1c6a43aa8fa7..0cb89573246c56dd34460db8f85460b2a4f309e7 100644 (file)
@@ -1,21 +1,10 @@
 # SPDX-License-Identifier: LGPL-2.1+
 
-from collections.abc import Sequence
-
-from mkosi.backend import MkosiState, add_packages
+from mkosi.backend import MkosiState
 from mkosi.distributions.debian import DebianInstaller
 
 
 class UbuntuInstaller(DebianInstaller):
-    repositories_for_boot = {"universe"}
-
-    @classmethod
-    def _add_default_kernel_package(cls, state: MkosiState, packages: list[str]) -> None:
-        # use the global metapckage linux-generic if the user didn't pick one
-        if ("linux-generic" not in packages and
-            not any(package.startswith("linux-image") for package in packages)):
-            add_packages(state.config, packages, "linux-generic")
-
     @classmethod
     def _add_apt_auxiliary_repos(cls, state: MkosiState, repos: set[str]) -> None:
         if state.config.release in ("unstable", "sid"):
diff --git a/mkosi/resources/dpkg-reconfigure-dracut.install b/mkosi/resources/dpkg-reconfigure-dracut.install
deleted file mode 100644 (file)
index daadefe..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-set -e
-
-COMMAND="${1:?}"
-ENTRY_DIR_ABS="${3:?}"
-
-case "$COMMAND" in
-    add)
-        # Make sure the directory the kernel image and initrd will be written to exists.
-        mkdir -p "$ENTRY_DIR_ABS"
-
-        if [ "$#" -ge 5 ]; then
-            # An explicit initrd path was passed so no need to regenerate the default initrd.
-            exit 0
-        fi
-
-        # Running kernel-install on Debian/Ubuntu doesn't regenerate the initramfs. Instead, we can trigger
-        # regeneration of the initramfs via "dpkg-reconfigure dracut".
-        dpkg-reconfigure dracut
-        ;;
-    *)
-        exit 0
-        ;;
-esac
index f18cc5b1ddc59b70a35962a91a7e2ff09a5ceb73..18a51b8881d864eb76de4509249b95d08077d7f5 100644 (file)
@@ -43,7 +43,7 @@ def test_parse_load_verb() -> None:
         assert parse(["build"]).verb == Verb.build
         assert parse(["shell"]).verb == Verb.shell
         assert parse(["boot"]).verb == Verb.boot
-        assert parse(["--bootable", "qemu"]).verb == Verb.qemu
+        assert parse(["qemu"]).verb == Verb.qemu
         with pytest.raises(SystemExit):
             parse(["invalid"])