mkosi+tests: fix handling and tests for Path arguments
This should have been done in 5a24a9fd9e9eea4c1a9cf2e9c1980697fd9b922b.
The code is getting more and more complex, because previously we
relied on having a string which could be both multiple items with
a separator, or just a single thing… With Path() this doesn't work
nearly so nicely.
mkosi: do not expand globs in manager metadata removal twice
We would do globbing internally in clean_*_metadata(), and then again
in remove_glob(). We want to do globbing early to only emit the
message when there's anything to remove. So let's stop calling
remove_glob().
While at it, make the internal variable names a bit shorter.
The idea is to allow specifing "--finalize-script=" to override the finalize
script to not be invoked, even in "mkosi.finalize" is present.
Right now, if there's a mkosi.build/mkosi.finalize/… file present, the
only way to prevent the script from running is to specify something
like --build-script=/bin/true (or move the script out of the way).
Sometimes it's useful to be able to skip the script. The code is changed
to convert '' to a placeholder value that is taken to mean that no script
should be executed. (None is already used to mean "no config", and implies
autodetection, so we can't use it for this purpose.)
Allow overriding autodetection of package manager metadata cleanup
There are cases where the package metadata should be removed, even
though the manager is present. For example, when the manager is pulled
in through dependencies or needs to be present in the image for
whatever other reasons. Similarly, there are cases where the metadata
should remain in the image, even though the package manager is
provided externally.
In particular, it is useful when building an image which will later on
be used as a "sysext base". Without the metadata, we will try to
install all packages again. So we want to keep the dnf/rpm metadata.
Later, when building a "sysext", dnf/rpm will be visible from the base
layer, even though it will not be present in the sysext layer being built.
We want to remove the dnf/rpm metadata.
The Path object generally works better for the kind of operations that
we need to do. In some cases it can be a bit awkward — for example just
appending a suffix requires some annoying gyrations. But overall, the
amount of code text is reduced and I think it's easier to read.
Some bugs were fixed on the way: in particular dedent() was missed in
when writing some configuration files (90-mkosi-vmlinuz-add.hook,
60-mkosi-vmlinuz-remove.hook).
The intent is to have no functional change, though with this amount of
churn some regression is likely… I tested this by building a bunch
of different projects with diverse configurations, and at least mkosi
doesn't crash, though I didn't check the produced images in detail.
An additional advantage is that we have stronger typing: before many
functions took a bunch of 'str' arguments, and now the paths at least
have a distinct type.
The code was modifing the passed argv array internally. And in fact,
parse_args_distribution_group() only worked correctly if
parse_args_file_group() was previously used to modify the argv array. Let's
drop all this, and never modify the input arguments. In the few cases where
it's appropriate, a copy is made internally.
Also shorten names of internal variables. defaults_file vs. default_file vs.
all_defaults_files was only making the code harder to read.
I also added older keys: we might want to build images with
older Fedora, and it's better to have the key hashes than
not to have them. The list now includes all keys listed by
fedora-gpg-keys-34-2.noarch.
Surprisingly, none of the standard tools complain about tabs in the
code, at least in some locations. I expected that python3 would always
complain, or at least tabnanny, or pyflakes… Let's roll a simple custom
check.
Use '-P' to request perl-compatible regular expressions even the user
has a different default configures so that '\t' works as expected.
Replace contextlib.ExitStack by direct cm invocations
I think it's nicer to keep things simple. Unfortunately black
turns the first chunk into a complete mess, so it needs to be disabled.
With python 3.9+ we will be able to drop the line continuations.
With this change, ARG_DEBUG is always the same (mutable) object.
Before it was first a tuple, and then a list, so the object (and type)
changed. When we did 'from backend import ARG_DEBUG', we would get a
reference to the tuple, and then when ARG_DEBUG was adjusted in backend,
the import wasn't properly updated. ('backend.ARG_DEBUG' would refer
to one object, and '__init__.ARG_DEBUG' to a different one.)
man: refer to settings primarily by their config file name
This implements the first part of #769: the structure of the man page
is changed from:
Command Line Parameters
--foo
...
Command Line Parameters and their Settings File Counterparts
--foo Output Foo=
...
to:
Settings
[Output] section
Foo=
--foo
...
I think the new order is both easier to read _and_ easier to maintain.
E.g. the table with option name mappings was missing a few entries.
I dropped "(see above)" and "(see below)" in various places. The user
knows that they can search for a given option name, and we don't need
to tell them. And since the target of this "anchor" usually isn't right
below or right above, they will need to use search _anyway_.
An exception is when we wanted to refer to a description of a file
in the Files section. In those cases I changed "(see below)" to
"(see "Files" section below)" so the user actually knows what to look
for.
I inserted FIXMEs for various issues. Trying to fix everything at once
would lead to an unreviable commit…
The regeneration of man/ is not included in the commits, because it's
annoying to constantly fix this up when rebasing patches. I'll do it
one go at the end.
dnf: when runnning with --network=never, use package metadata cache
This implements the ability to rebuild packages from cache that was requested
in #700. I don't think it can be said to resolve the issue, since this is
only a partial solution, but useful nonetheless.
Daan De Meyer [Fri, 20 Aug 2021 13:33:13 +0000 (14:33 +0100)]
Don't let dracut generate implicit devices in hostonly mode
If hostonly_default_device is enabled, details from the host system devices
leak into the initrd which we want to avoid. For example, this caused the
seclabel mount option to leak into the mount options of my mkosi generated
BTRFS mount options rendering the image unbootable in QEMU.
Daan De Meyer [Sun, 8 Aug 2021 12:58:25 +0000 (13:58 +0100)]
Fix pyright typing errors
pyright is an alternative type checker for Python. It's main advantage
over mypy is that it's a lot faster than mypy which makes it a lot more
pleasant to use in VSCode for in-editor type checking.
This commit fixes the typing errors flagged by pyright.
mkosi: only print the summary when explicitly requested
Originally, the summary was printed whenever a build was done.
With 1f9a758fad3debbdddd2947a19978de3909aabf7, it is only printed
for cached builds. But that is surprising: when I turn on caching,
I suddently get extra output. Let's just print the summary when
requested.
mkosi: print paths relative to the current working directory
We would print a bunch of paths, and they tend to be quite long,
especially if 'mkosi.output' is used. The output on the console is
supposed to be pretty and easy to read. The user is most likely to
use the path to interact with the file in the same terminal, e.g.
'less mkosi.output/something.manifest', so let's just print the
paths that are underneath the current directory as relative to it.
This makes the output more readable while the paths can still be
used directly in subsequent commands most of the time.
Also, drop "Successfully" from messages: it is a long word, and
superfluous, since we either print an error message or this.
* Tue Mar 16 2021 Kamil Dudka <kdudka@redhat.com> - 2.3.1-1
- new upstream release
...
"""
The idea is that it's easy to diff such files. When the changes are
relatively small, for example between the same distro on different days,
we can easily see what changed, and why. For example, between F34 and F35
I get the following diff:
So when the package changed, we know *why* it changed, and can often
jump directly to the related bugs and such. For example, we now get
cracklib-dicts (yes, very useful), but the package itself didn't change.
Something else pulls it in [1]. Such a diff is useful when trying to
see debug regressions between related builds or minimizing the package
set.
mkosi: call dracut/unified kernel image on the final image, not the cached image
We need to invoke dracut on the final image, not on the cached image.
Currently, it's done the other way round, in light of the fact that
dracut is the slowest part of the build. However that doesn't really
work, since the generated unified kernel image depends on the final
build.
The generated image after all will:
1. when verity is enabled receives the root hash which depends on the
final fs image to be complete
2. when the image id/version logic is enabled the unified kernel image
name will change with every build
3. we want to base the initrd on the resources installed in the OS
during the build. Besides configuration this prominently includes a
freshly build systemd. After all, one of the major usecases for mkosi
was to be useful to build test images for systemd development. There
we really want to ensure the systemd we just built is included in the
initrd, and not an old version that happened to be around when the
cache image was first created.
I would like to set environment variables for other scripts. But I
don't think adding separate options make sense: it should be fine to
just set the same environment variable for all scripts that are
invoked… After all, variables are best for "global" settings. Scripts
already get positional arguments that allow them to distinguish build
phases, so they don't need to use variables for this.
mkosi: pull in envvar value from the environment if no value specified
This makes --build-env=FOO behave like --build-env=FOO=$FOO. This is a
common case, and it makes some invocations more convenient. In
particular, we avoid exposing the variable on the commandline.
mkosi: define NamedTuple to hold luks_setup_all() output
I'm using a NamedTuple here, instead of a dataclass, because the
dataclass does not support indexing and iteration. It certainly would
be possible to define those, but with typing it becomes quite a lot of
code (and typing of __iter__() that supports both indexing and slicing
is tricky and verbose).
BuildOutput has no inherent ordering — it's a bunch of completely
different objects. But here we have a list of partitions, so it's
reasonable to use a tuple for this.
mkosi: create cache copy also for non-raw output formats
I don't quite grok the logic to skip the creation of the cache copy.
I'm using Format=directory, and I expected the cache copy to be there.
Since we can't overwrite one directory with another, unlink the output
when copying. (For raw output, which is a file, we don't need to unlink
because we can replace the file atomically.)
With this change, it is created and everything seems to work fine.
mkosi: do not suppress non-Exception exceptions in unlink_try_hard()
In 01eac0078a06334ed938b68a09db8799b490dfe0 annotations to suppress
warnings about this were added, sadly without any explanation, so we
can only guess what the author had in mind. But it doesn't seem
appropriate… If I press ^C while removing some files, it seems quite
wrong to continue execution. Also, if those operations fail on
permission errors, we also don't want to continue.
("except:" catches BaseException, which includes KeyboardInterrupt and
other things which should only be caught in very special
circumstances, like interactive shells.)
mkosi: include the ellipsis+dot in complete_step() in the format string
complete_step() already added an ellipsis and dot on its own (to the
opening message and to the cloing message, respectively), but in some
places we had "..." or "." in the format string anyway, so we eneded
up with six dots or four dots in output. But instead of fixing those
places, I think it's better to go in the opposite direction, and include
the terminator in the format string.
This is nicer because:
- It's just easier to see the complete format string including the
terminator. The "saving" of a few characters by including it
automatically isn't very important.
- If the line ends in a path, we should skip the terminator to make
the path easier to select-and-paste. This is now trivial: just skip
the terminator in the format string.
- If the step is "immediate" and we expect it to finish quickly and
without any further output (like calling os.unlink() or such), we
can skip the ellipsis.
While at it, let's change "..." to "…", it looks nicer and saves some
screen real estate.
mkosi: de-emphasize completion of steps after an exception has occured
I had the following failure:
...
‣ Unmounting API VFS...
‣ Unmounting Package Cache...
‣ Removing random seed...
‣ Unmounting image...
‣ Running second (final) stage...
‣ Mounting image...
‣ Setting up basic OS tree...
‣ Unmounting image...
Traceback (most recent call last):
...
FileExistsError: [Errno 17] File exists: '/home/zbyszek/src/mkosi-initrd/.mkosi-5jv7jtu2/root/etc'
The error is generated in the block "Setting up basic OS tree...", but
the exception traceback is not printed immediately, so it seems like
it was generated in the "Unmounting image..." block. There could be
multiple lines of such cleanup, and it's hard to tell where the error
occurred without knowledge of mkosi internals. Let's de-bold and
parenthesize the steps that happen when we are in exception handling
blocks, so the reader can discern this more easily.
‣ Unmounting API VFS...
‣ Unmounting Package Cache...
‣ Removing random seed...
‣ Unmounting image...
‣ Running second (final) stage...
‣ Mounting image...
‣ Setting up basic OS tree...
‣ (Unmounting image...)
Traceback (most recent call last):
...
FileExistsError: [Errno 17] File exists: '/home/zbyszek/src/mkosi-initrd/.mkosi-3legjys3/root/etc'
We said that all files are optional *before* starting the list of files,
then for each individual file, and then again *after* the list. Let's
simplify this by describing files without mentioning that is is optional.
Similarly, we don't need to emphasize the fact that scripts are executable
for each script… readers generally know that.
Let's also make the terms bold, so it's easier to find the interesting
paragraph in this wall of text.
Also break into paragraphs more; remove underlining from "OS" — it's a
normal abbreviation and the markup was confusing; use "/" at the end
of directories; use more markup for paths; move the description of
mkosi.skeleton above mkosi.extra.
Luca Boccassi [Fri, 18 Jun 2021 12:14:42 +0000 (13:14 +0100)]
qemu: revert back to virtio from virtio-scsi-pci on Debian
Debian images on qemu fails to boot with virtio-scsi-pci. Reverting back to
virtio does not show issues with the EFI shell, everything boots correctly,
so do that when running Debian images.