Commit Graph

59 Commits

Author SHA1 Message Date
Colin Walters
e47b370963 bootloader/grub2: Don't do anything if we have static configs
This builds on top of fa9924e4fe
(But in a very hacky way because we don't currently link to a JSON library)

Basically, bootupd supports injecting static configs, and this
is the currently least hacky way for us to detect this and understand
that we shouldn't try to run `grub2-mkconfig`.

A further patch I'd like to do here is also change the probing
logic to gracefully no-op if `grub2-mkconfig` doesn't exist,
but that has a bit more risk and involvement.
2024-02-27 14:21:26 -05:00
Colin Walters
87dcc801a2 ostree-tmpfiles.conf: Drop var entry
We are backing away from this semantic, and moving towards
`/var` only being initialized at initial provisioning.
2024-02-12 13:12:09 -05:00
Colin Walters
f81b9fa166 sysroot: Rework /var handling to act like Docker VOLUME /var
We've long struggled with semantics for `/var`.  Our stance of
"/var should start out empty and be managed by the OS" is a strict
one, that pushes things closer to the original systemd upstream
ideal of the "OS state is in /usr".

However...well, a few things.  First, we had some legacy bits
here which were always populating the deployment `/var`.  I don't
think we need that if systemd is in use, so detect if the tree
has `usr/lib/tmpfiles.d`, and don't create that stuff at
`ostree admin stateroot-init` time if so.

Building on that then, we have the stateroot `var` starting out
actually empty.

When we do a deployment, if the stateroot `var` is empty,
make a copy (reflink if possible of course) of the commit's `/var`
into it.

This matches the semantics that Docker created with volumes,
and this is sufficiently simple and easy to explain that I think
it's closer to the right thing to do.

Crucially...it's just really handy to have some pre-existing
directories in `/var` in container images, because Docker (and podman/kube/etc)
don't run systemd and hence don't run `tmpfiles.d` on startup.

I really hit on the fact that we need `/var/tmp` in our container
images by default for example.

So there's still some overlap here with e.g. `/usr/lib/tmpfiles.d/var.conf`
as shipped by systemd, but that's fine - they don't actually conflict
per se.
2024-02-09 17:46:12 -05:00
Jonathan Lebon
92b1a27202 Add concept of state overlays
In the OSTree model, executables go in `/usr`, state in `/var` and
configuration in `/etc`. Software that lives in `/opt` however messes
this up because it often mixes code *and* state, making it harder to
manage.

More generally, it's sometimes useful to have the OSTree commit contain
code under a certain path, but still allow that path to be writable by
software and the sysadmin at runtime (`/usr/local` is another instance).

Add the concept of state overlays. A state overlay is an overlayfs
mount whose upper directory, which contains unmanaged state, is carried
forward on top of a lower directory, containing OSTree-managed files.

In the example of `/usr/local`, OSTree commits can ship content there,
all while allowing users to e.g. add scripts in `/usr/local/bin` when
booted into that commit.

Some reconciliation logic is executed whenever the base is updated so
that newer files in the base are never shadowed by a copied up version
in the upper directory. This matches RPM semantics when upgrading
packages whose files may have been modified.

For ease of integration, this is exposed as a systemd template unit which
any downstream distro/user can enable. The instance name is the mountpath
in escaped systemd path notation (e.g.
`ostree-state-overlay@usr-local.service`).

See discussions in https://github.com/ostreedev/ostree/issues/3113 for
more details.
2024-01-09 23:20:41 -05:00
Jonathan Lebon
4982306e67 lib/deploy: Round to block size in early prune space check
When we estimate how much space a new bootcsum dir will use, we
weren't accounting for the space overhead from files not using the
last filesystem block completely. This doesn't matter much if counting
a few files, but e.g. on FCOS aarch64, we include lots of small
devicetree blobs in the bootfs. That loss can add up to enough for the
`fallocate()` check to pass but copying still hitting `ENOSPC` later on.

I think a better fix here is to change approach entirely and instead
refactor `install_deployment_kernel()` so that we can call just the
copying bits of it as part of the early prune logic. We'll get a more
accurate assessment and it's not lost work since we won't need to
recopy later on. Also this would not require having to keep in sync the
estimator and the install bits.

That said, this is blocking FCOS releases, so I went with a more tactical
fix for now.

Fixes: https://github.com/coreos/fedora-coreos-tracker/issues/1637
2024-01-04 12:57:43 -05:00
Colin Walters
c3dff62e1c commit: Try reflinks for local commits by default
I think we originally used to do this, but at some point in a
code refactoring, this optimization got lost.

It's a quite important optimization for the case of writing content
generated by an external system into an ostree repository.
2023-12-04 20:45:08 -05:00
Colin Walters
bab87cbd9d tests: Drop bare-user on tmpfs negative test
As of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2daf18a7884dc03d5164ab9c7dc3f2ea70638469
the restriction is lifted, FINALLY.
2023-12-03 09:32:36 -05:00
Colin Walters
66064d960d tmpfiles: Copy /usr/share/factory/var to /var
This is a pattern we want to encourage.  It's honestly just
way simpler than what rpm-ostree is doing today in auto-synthesizing
individual tmpfiles.d snippets.
2023-11-30 18:11:33 -05:00
Colin Walters
d3de3a0a88 tests: Add a dedicated finalization test
This one covers `admin lock-finalization --unlock`.
2023-11-28 18:45:11 -05:00
Colin Walters
28cc761806 sysroot: Stabilize deployment finalization, add API and CLI
It's about time we do this; deployment finalization locking
is a useful feature.  An absolutely key thing here is that
we've slowly been moving towards the deployments as the primary
"source of truth".

Specifically in bootc for example, we will GC container images
not referenced by a deployment.

This is then neecessary to support a "pull but don't apply automatically" model.

This stabilizes the existing `ostree admin deploy --lock-finalization`
CLI, and adds a new `ostree admin unlock-finalization`.

We still check the old lock file path, but there's a new boolean
value as part of the staged deployment data which is intended
to be the source of truth in the future.  At some point then we
can drop the rpm-ostree lockfile handling.

Closes: https://github.com/ostreedev/ostree/issues/3025
2023-11-27 10:59:56 -05:00
Colin Walters
b6f435fe11 tests: Turn off gpg verification for dev builds
Right now `ostree admin status` errors out in this case, but
`rpm-ostree status` doesn't.  The former behavior is probably
more of a bug, work around it for now.
2023-11-27 10:59:56 -05:00
Colin Walters
bc62fd5196 unlock: Don't pass options again to overlayfs
There seems to be a tricky regression here with the util-linux
support for the new mount API, plus overlays support for it.

```
[2023-11-09T21:05:30.633Z] Nov 09 21:05:26 qemu0 kola-runext-unlock-transient.sh[2108]: + unshare -m -- /bin/sh -c 'mount -o remount,rw /usr && echo hello from transient unlock >/usr/share/writable-usr-test'
[2023-11-09T21:05:30.633Z] Nov 09 21:05:26 qemu0 kola-runext-unlock-transient.sh[2148]: mount: /usr: mount point not mounted or bad option.
[2023-11-09T21:05:30.633Z] Nov 09 21:05:26 qemu0 kola-runext-unlock-transient.sh[2148]:        dmesg(1) may have more information after failed mount system call.
```

OK this seems related to the new mount API support in util-linux and overlayfs.  From a strace:

```
2095  open_tree(AT_FDCWD, "/usr", OPEN_TREE_CLOEXEC) = 3
2095  mount_setattr(-1, NULL, 0, NULL, 0) = -1 EINVAL (Invalid argument)
...
2095  fspick(3, "", FSPICK_NO_AUTOMOUNT|FSPICK_EMPTY_PATH) = 4
2095  fsconfig(4, FSCONFIG_SET_FLAG, "seclabel", NULL, 0) = 0
2095  fsconfig(4, FSCONFIG_SET_STRING, "lowerdir", "usr", 0) = -1 EINVAL (Invalid argument)
```

I think the core problem here is it's trying to reconfigure the mount with existing options,
but in the new mount namespace we can't see the lowerdir.

Here we really really just want to remount writable.  Telling
util-linux to not pass existing options fixes it.
2023-11-09 20:53:52 -05:00
Colin Walters
c668a8c531 tests: Work around systemd regression for boot id parsing
cc https://github.com/systemd/systemd/issues/29275
2023-11-09 15:10:33 -05:00
Colin Walters
ac69c70750 deploy: Remove lock when re-staging
This closes the biggest foot-gun when doing e.g.
`rpm-ostree rebase` when zincati is running on a FCOS system.

Previously if zincati happened to have staged + locked a deployment,
we'd keep around the lock which is definitely not what is desired.
2023-10-13 13:45:04 -04:00
Colin Walters
81c08746c6 repo: Add an option to label /usr/etc as /etc
This will be very useful for enabling a "transient /etc" option
because we won't have to do hacks relabling in the initramfs, or
forcing it on just for composefs.
2023-10-11 13:25:08 -04:00
Colin Walters
d5cfbed5bc sysroot: Promote the "early prune" behavior to default
I think we have enough testing for this, let's default it to
on, and change the variable to allow opt-out in case it does
introduce a regression.
2023-08-31 10:25:59 -04:00
Jonathan Lebon
193ef29f3f lib/deploy: Use fallocate for early prune space check
The `f_bfree` member of the `statvfs` struct is documented as the
"number of free blocks". However, different filesystems have different
interpretations of this. E.g. on XFS, this is truly the number of blocks
free for allocating data. On ext4 however, it includes blocks that
are actually reserved by the filesystem and cannot be used for file
data. (Note this is separate from the distinction between `f_bfree` and
`f_bavail` which isn't relevant to us here since we're privileged.)

If a kernel and initrd is sized just right so that it's still within the
`f_bfree` limit but above what we can actually allocate, the early prune
code won't kick in since it'll think that there is enough space. So we
end up hitting `ENOSPC` when we actually copy the files in.

Rework the early prune code to instead use `fallocate` which guarantees
us that a file of a certain size can fit on the filesystem. `fallocate`
requires filesystem support, but all the filesystems we care about for
the bootfs support it (including even FAT).

(There's technically a TOCTOU race here that existed also with the
`statvfs` code where free space could change between when we check
and when we copy. Ideally we'd be able to pass down that fd to the
copying bits, but anyway in practice the bootfs is pretty much owned by
libostree and one doesn't expect concurrent writes during a finalization
operation.)
2023-05-29 12:17:05 -04:00
Jonathan Lebon
a3c0d6a3fe lib/deploy: Log case when auto-pruning is hopeless
For easier diagnostics.
2023-05-28 18:38:53 -04:00
Jonathan Lebon
c561e6179e lib/sysroot-deploy: Add experimental support for automatic early prune
During the early design of FCOS and RHCOS, we chose a value of 384M
for the boot partition. This turned out to be too small: some arches
other than x86_64 have larger initrds, kernel binaries, or additional
artifacts (like device tree blobs). We'll likely bump the boot partition
size in the future, but we don't want to abandon all the nodes deployed
with the current size.[[1]]

Because stale entries in `/boot` are cleaned up after new entries are
written, there is a window in the update process during which the bootfs
temporarily must host all the `(kernel, initrd)` pairs for the union of
current and new deployments.

This patch determines if the bootfs is capable of holding all the
pairs. If it can't but it could hold all the pairs from just the new
deployments, the outgoing deployments (e.g. rollbacks) are deleted
*before* new deployments are written. This is done by updating the
bootloader in two steps to maintain atomicity.

Since this is a lot of new logic in an important section of the
code, this feature is gated for now behind an environment variable
(`OSTREE_ENABLE_AUTO_EARLY_PRUNE`). Once we gain more experience with
it, we can consider turning it on by default.

This strategy increases the fallibility of the update system since one
would no longer be able to rollback to the previous deployment if a bug
is present in the bootloader update logic after auto-pruning (see [[2]]
and following). This is however mitigated by the fact that the heuristic
is opportunistic: the rollback is pruned *only if* it's the only way for
the system to update.

[1]: https://github.com/coreos/fedora-coreos-tracker/issues/1247
[2]: https://github.com/ostreedev/ostree/issues/2670#issuecomment-1179341883

Closes: #2670
2023-05-01 12:12:03 -04:00
Jonathan Lebon
fd3304e987 tests/kolainst: Add make localinstall
When hacking and testing locally with `cosa build-fast` and `kola run`,
I prefer to leave testing framework stuff within the work directory
rather than installed in my pet container. Add a `localinstall` target
for this which puts the tests in `tests/kola`. Then a simple `kola run`
will pick it up.
2023-04-14 15:19:17 -04:00
Colin Walters
e8fbc756cb itest-pull-space: Use mkfs.ext4, align to at least 512b
XFS now seems to want filesystems larger than 300MB, so switch
to ext4.  Also use `20MiB` so we align to 512b sectors to squash
a `losetup` warning.
Also tweak some of the numbers to still work.
2023-03-14 17:07:01 -04:00
Miguel Angel Ajo
e234b630f8 Support overlayfs whiteouts on checkout
Introduces an intermediate format for overlayfs storage, where
.wh-ostree. prefixed files will be converted into char 0:0
whiteout devices used by overlayfs to mark deletions across layers.

The CI scripts now uses a volume for the scratch directories
previously in /var/tmp otherwise we cannot create whiteout
devices into an overlayfs mounted filesystem.

Related-Issue: #2712
2022-09-28 12:26:31 +02:00
Colin Walters
6651b72a7a
Merge pull request #2544 from dbnicholson/finalize-block
finalize-staged: Ensure /boot and /sysroot automounts don't expire
2022-08-30 15:12:32 -04:00
Dan Nicholson
f3db79e7fa finalize-staged: Ensure /boot automount doesn't expire
If `/boot` is an automount, then the unit will be stopped as soon as the
automount expires. That's would defeat the purpose of using systemd to
delay finalizing the deployment until shutdown. This is not uncommon as
`systemd-gpt-auto-generator` will create an automount unit for `/boot`
when it's the EFI System Partition and there's no fstab entry.

To ensure that systemd doesn't stop the service early when the `/boot`
automount expires, introduce a new unit that holds `/boot` open until
it's sent `SIGTERM`. This uses a new `--hold` option for
`finalize-staged` that loads but doesn't lock the sysroot. A separate
unit is used since we want the process to remain active throughout the
finalization run in `ExecStop`. That wouldn't work if it was specified
in `ExecStart` in the same unit since it would be killed before the
`ExecStop` action was run.

Fixes: #2543
2022-08-30 09:16:39 -06:00
Huijing Hei
37aa2ac287 Fix ostree admin kargs edit-in-place assertion when deployments
are pending

This is to support pending deployments instead of rasing assertion.
For example:
```
$ sudo rpm-ostree kargs --append=foo=bar
$ sudo ostree admin kargs edit-in-place --append-if-missing=foobar
```
After reboot we get both `foo=bar foobar`.

Fix https://github.com/ostreedev/ostree/issues/2679
2022-08-29 11:31:32 +08:00
Jonathan Lebon
84670a0070 tests/kolainst/staged-deploy: parse rpm-ostree status --json instead
Don't parse `rpm-ostree status` output, it's not meant for that. Use
`--json` output instead.

While we're here, fix an obsolete reference to Ansible.

Related: https://github.com/coreos/rpm-ostree/pull/3938
2022-08-15 17:50:11 -04:00
Huijing Hei
8f24e0826a Add test to verify ostree admin kargs edit-in-place working 2022-07-12 20:56:18 +08:00
Colin Walters
52d6f4e790 tests/staged-deploy.sh: Hack around cosa systemd unit check
https://github.com/coreos/coreos-assembler/pull/2921 broke this
test which is intentionally causing a systemd unit to fail.

As they say, necessity is the mother of invention.  They don't
say though that need always causes particularly *beautiful* things
to be invented...
2022-06-24 10:18:53 -04:00
Colin Walters
558d966420 tests/inst: Fix install rules for ostree-rs merger
`tests/inst` became its own workspace.
2022-05-09 12:57:40 -04:00
Colin Walters
d3d3e4ea13 Add an ostree-boot-complete.service to propagate staging failures
Quite a while ago we added staged deployments, which solved
a bunch of issues around the `/etc` merge.  However...a persistent
problem since then is that any failures in that process that
happened in the *previous* boot are not very visible.

We ship custom code in `rpm-ostree status` to query the previous
journal.  But that has a few problems - one is that on systems
that have been up a while, that failure message may even get
rotated out.  And second, some systems may not even have a persistent
journal at all.

A general thing we do in e.g. Fedora CoreOS testing is to check
for systemd unit failures.  We do that both in our automated tests,
and we even ship code that displays them on ssh logins.  And beyond
that obviously a lot of other projects do the same; it's easy via
`systemctl --failed`.

So to make failures more visible, change our `ostree-finalize-staged.service`
to have an internal wrapper around the process that "catches" any
errors, and copies the error message into a file in `/boot/ostree`.

Then, a new `ostree-boot-complete.service` looks for this file on
startup and re-emits the error message, and fails.

It also deletes the file.  The rationale is to avoid *continually*
warning.  For example we need to handle the case when an upgrade
process creates a new staged deployment.  Now, we could change the
ostree core code to delete the warning file when that happens instead,
but this is trying to be a conservative change.

This should make failures here much more visible as is.
2022-04-26 13:02:46 -04:00
Colin Walters
b92dbc49f0 ci: Mask zincati for synthetic update
Our CI started falling over because coreos-assembler checks
for units stuck activating as of https://github.com/coreos/coreos-assembler/pull/2810

Really need to centralize the code for this and fix the root
problem, but...not today.

xref https://github.com/coreos/coreos-assembler/pull/2814
2022-04-20 20:23:10 -04:00
Jonathan Lebon
5bf57ec062 tests/kolainst: Avoid recursive symlinks
`kola` now follows symlinks when archiving an external test's `data/`
dir. So the recursive `data` symlink we have here breaks it.

Let's just move the shared files in its own directory and update the
symlinks.
2022-01-25 16:44:39 -05:00
Jonathan Lebon
baf838de22 ostree/deploy: Test finalization locking
Support for that file was added previously, but the testing lived in
rpm-ostree only. Let's add it here too.

In the process add a hidden `--lock-finalization` to `ostree admin
deploy` to make testing easier (though it could also be useful to update
managers driving OSTree via the CLI).
2022-01-21 13:48:35 -05:00
Colin Walters
998154f8ff main: Also support CLI extensions in /usr/libexec/libostree/ext
In fixing https://github.com/coreos/rpm-ostree/pull/3323
I felt that it was a bit ugly we're installing `/usr/bin/ostree-container`.

It's kind of an implementation detail.  We want users to use
`ostree container`.

Let's support values outside of $PATH too.

For example, this also ensures that TAB completion for `ost` expands
to `ostree ` with a space.
2022-01-11 20:13:33 -05:00
Joseph Marrero
581a58067b Update FSF license notices to use URL instead of address 2021-12-07 08:34:25 -05:00
Luca BRUNO
f93d96620c
tests/var-mount: tweak test setup
This reworks the var-mount destructive test in order to properly use
the datadir for the current stateroot instead of a duplicated one.
In turn, it ensures that the resulting `var.mount` after reboot is
correctly pointing to the same location which hosted `/var` on the
previous boot.
2021-10-19 08:03:09 +00:00
Colin Walters
e6a560b407 deploy: Ignore sockets, fifos in /etc during merge
https://bugzilla.redhat.com/show_bug.cgi?id=1945274 is an issue where a privileged
kubernetes daemonset is writing a socket into `/etc`.  This makes ostree upgrades barf.

Now, they should clearly move it to `/run`.  However, one option is for us to
just ignore it instead of erroring out.  Some brief investigation shows that
e.g. `git add somesocket` is a silent no-op, which is an argument in favor of ignoring it.

Closes: https://github.com/ostreedev/ostree/issues/2446
2021-10-01 11:28:11 -04:00
Colin Walters
ab12e380fc bin/commit: Fix --tree=tar with --selinux-policy
The logic for `--selinux-policy` ended up in the `--tree=dir`
path, but there's no reason for that.  Fix the imported
labeling with `--tree=tar`.  Prep for use with containers.

We had this bug because the previous logic was trying to avoid
duplicating the code for generic `--selinux-policy` and
the case of `--selinux-policy-from-base --tree=dir`.

It's a bit more code, but it's cleaner if we dis-entangle them.
2021-09-30 11:44:27 -04:00
Colin Walters
bc30806c6e tests: Add new TAP APIs
Having to touch a global test counter when adding tests is
a recipe for conflicts between PRs.

The TAP protocol allows *ending* with the expected number of
tests, so the best way to do this is to have an explicit
API like our `tap_ok` which bumps a counter, then end with `tap_end`.

I ported one test as a demo.
2021-09-10 17:07:42 -04:00
Colin Walters
8821ec6e56 upgrade: Stabilize deployment staging
We're waaay overdue for this, it's been the default
in rpm-ostree for years, and solves several important bugs
around not capturing `/etc` while things are running.

Also, `ostree admin upgrade --stage` (should) become idempotent.

Closes: https://github.com/ostreedev/ostree/issues/2389
2021-09-07 16:12:43 -04:00
Colin Walters
7ff848f101
Merge pull request #2377 from smcv/libtest-core
libtest-core: Add some improvements from bubblewrap
2021-06-21 10:12:40 -04:00
Simon McVittie
14d6e75752 libtest-core: Mention bubblewrap as a user of this file
Signed-off-by: Simon McVittie <smcv@collabora.com>
2021-06-18 10:14:01 +01:00
Simon McVittie
c0157f96b2 libtest-core: Update URL of rpm-ostree
Signed-off-by: Simon McVittie <smcv@collabora.com>
2021-06-18 10:13:38 +01:00
Simon McVittie
d7cdde5d34 libtest-core: On failure, make it clearer what has happened
If we fail as a result of `set -x`, It's often not completely obvious
which command failed or how. Use a trap on ERR to show the command that
failed, and its exit status.

Signed-off-by: Simon McVittie <smcv@collabora.com>
2021-06-18 09:49:53 +01:00
Alexander Larsson
c934fc8f99 libtest-core: Add assert_files_equal
[Originally from bubblewrap commits c5c999a7 "tests: test --userns"
and 3e5fe1bf "tests: Better error message if assert_files_equal fails";
separated into this commit by Simon McVittie.]
2021-06-18 09:46:31 +01:00
Colin Walters
73e3ccc401 Use generator to enable ostree-remount.service and ostree-finalize-staged.path
We struggled for a long time with enablement of our "internal units",
trying to follow the philosophy that units should only be enabled
by explicit preset.

See https://bugzilla.redhat.com/show_bug.cgi?id=1451458
and https://github.com/coreos/rpm-ostree/pull/1482
etc.

And I just saw chat (RH internal on a proprietary system sadly) where
someone hit `ostree-remount.service` not being enabled in CentOS8.

Thinking about this more, I realized we've shipped a systemd generator
for a long time and while its only role until now was to generate `var.mount`,
but by using it to force on our internal units, we don't require
people to deal with presets anymore.

Basically we're inverting things so that "if ostree= is on the kernel
cmdline, then enable our units" and not "enable our units, but have
them use ConditionKernelCmdline=ostree to skip".

Drop the weird gyrations we were doing around `ostree-finalize-staged.path`
too; forking `systemctl start` is just asking for bugs.

So after this, hopefully we won't ever again have to think about
distribution presets and our units.
2021-06-16 09:40:28 -04:00
Colin Walters
edf7477ee9 deploy: Warn if we find content in the deployment's /var
This will be ignored, so let's make it very clear
people are doing something wrong.  Motivated by a bug
in a build pipeline that injected `/var/lib/rpm` into an ostree
commit which ended up crashing rpm-ostree because it was an empty db
which it wasn't expecting.

It *also* turns out rpm-ostree is incorrectly dumping content in the
deployment `/var` today, which is another bug.
2021-06-10 07:33:17 -04:00
Colin Walters
6664ee4ed4 ci: Fix staged-delay to work with newer systemd
Yeah, we should stop parsing the text; I need to dig at that
at some point.
2021-05-25 16:28:32 -04:00
Colin Walters
46a0911c6d build-sys: Add toplevel workspace Cargo.toml
rust-analyzer is happier with this because it understands
the project structure out of the box.

We aren't actually again adding a dependency on Rust/cargo in the core,
this is only used to make `cargo build` work out of the box to build
the Rust test code.
2021-04-15 12:33:34 -04:00
Colin Walters
6d0bb10bf0 cci: Update for buildroot changes
See latest in https://github.com/coreos/fedora-coreos-tracker/blob/master/docs/ci-and-builds.md
2021-03-31 15:11:34 -04:00