Repository navigation
Conversation
7b61907 to
e41bfc2
Compare
e41bfc2 to
bb305fc
Compare
The /var copy needs careful filtering around exclusions and nested mounts, and must avoid publishing partial entries or overwriting existing data. Isolating the copy engine and its tests makes these filesystem guarantees reviewable before adding installer orchestration. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
Stored images should be validated before target mutations. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
Users converting an existing package-mode root need an opt-in path to move its state into the new OSTree deployment before reboot. Keep migration behind the existing-root install option and defer destructive cleanup until the copy succeeds, while preserving the established install behavior for other callers. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
Large /var trees are expensive to duplicate when the source and deployment filesystems support copy-on-write clones. Probe the actual source/destination pair, use reflinks when available, and retain a full-copy fallback for unsupported filesystems. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
Users converting package-mode systems need to understand the copy strategy, required backend, exclusions, and lack of snapshot consistency before opting in. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
A /var migration is useful only if copied data remains available after the first reboot. Add a single-guest plan that invokes --preserve-var and verifies a host marker after boot, while keeping TMT workdirs accessible when /var/tmp is excluded. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
The package-mode host's /etc is not migrated by to-existing-root, so a tmpfiles rule written there disappears on reboot. Write and verify the rule in the mounted deployment's persistent /etc before reboot instead. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
The split package-mode test no longer exercised how preserve-var handles a nested bind mount. Add a derived image with an enabled mount and verify copied data and the rebooted mount behavior. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
Reject wipe mode before installation can mutate the running source tree. Make no-clobber collisions visible and clarify the copy, staging, and crash-durability guarantees. Assisted-by: AI Signed-off-by: ckyrouac <ckyrouac@redhat.com>
jmarrero-bot
left a comment
There was a problem hiding this comment.
Not ready yet for hosts with mounts under /var. In Fedora 44 and CentOS Stream 10 VMs, a host with nothing (or just rpc_pipefs) mounted under /var migrates fine: PostgreSQL data and app state in /var/lib survive the reboot. But a separate /var/log disk, or a tmpfs below /var, makes the copy fail after Installation complete!. By then the host's boot entries are already gone, so it boots the image without the host's /var or with only part of it. Details are inline. jmarrero-forge#11 has fixes on top of this head, and with them both of those scenarios pass.
Also:
- On these cloud-init hosts the migrated system had no SSH host keys, so sshd fails (see the inline comment on the docs). The package-mode Testing Farm jobs here stop the same way:
Failed to start sshd.serviceafter the reboot, thenSSH master process failed to start(e.g. https://artifacts.dev.testing-farm.io/0791d950-98ff-4a8e-9de6-b24531a9e433/). - I reproduced two of Copilot's tmt comments with
just test-tmt-package-mode. package-mode.fmf:133: the install fails withresolving bound image registry.access.redhat.com/ubi9/podman:9.8-1793032728: ... does not resolve to an image ID. Test L313: the trace showsprintf %sn, so the tmpfiles rule is written as one line. - Composefs:
--preserve-var --composefs-backendis refused before anything is touched, so ostree is the only backend this supports.
VM matrix, exact errors, unit/tmt results: https://gist.github.com/jmarrero-bot/16d461d0ed7a43ab4086d24e17152e17
Generated-by: https://github.com/jmarrero-bot#llms
| ) | ||
| .await?; | ||
|
|
||
| if preserve_var { |
There was a problem hiding this comment.
Every failure I hit came from this block, after clean_boot_directories and bootupd had already replaced the host's boot entries (only ostree-1.conf left). The host then boots the image without its /var (mountinfo error) or with part of it (placeholder errors). The data is still on disk in the old /var, but the new system doesn't look there. Opening the source, reading mountinfo and checking each nested mount could all happen before install_to_filesystem; 637e8d1 in jmarrero-forge#11 does that. It catches the mountinfo case, but the other two depend on the destination. The copy itself can still fail late, e.g. a full copy running out of space, so a free-space check would fit there too.
| format!("Malformed mountinfo line {}: missing separator", index + 1) | ||
| })?; | ||
| anyhow::ensure!( | ||
| separator >= 6 && fields.len() == separator + 4, |
There was a problem hiding this comment.
This rejects valid records with an empty source: mount -t tmpfs "" /var/lib/x shows up as ... - tmpfs rw,..., which has only three fields after -. Any such record anywhere in the installer's mountinfo fails the migration, not just ones below /var. F44 and CS10 VMs: Post-install /var preservation: Malformed mountinfo line 42: invalid field count (line 36 on CS10). Only the mountpoint (field 5) is used, so parsing just that avoids it.
| let mut entries = destination.read_dir(".")?; | ||
| anyhow::ensure!( | ||
| entries.next().transpose()?.is_none(), | ||
| "Mountpoint placeholder {} is not empty", |
There was a problem hiding this comment.
ostree seeds the new stateroot's /var from the image, so a nested mountpoint where the image has content lands here. A Fedora 44 host with /var/log on its own disk and a fedora-bootc:44 image fails with Reflink-copying /var into new deployment (Strategy C): Mountpoint placeholder log is not empty. Keeping the image's content (the mount covers it at boot) and rejecting only a type mismatch works on the same host image.
| .collect::<BTreeSet<_>>(); | ||
| for name in destination_names { | ||
| if !source_names.contains(name.as_os_str()) { | ||
| fremovexattr(&destination, &name).with_context(|| { |
There was a problem hiding this comment.
On CentOS Stream 10 the root of a tmpfs mounted below /var has no security.selinux, so this tries to strip the label from the new placeholder and SELinux refuses: restoring directory metadata failed: xattrs: Removing destination xattr security.selinux: Permission denied (os error 13). Keeping the destination's label when the source has none fixes it.
|
|
||
| /// Relative paths below `/var` to leave out while preserving `/var`. | ||
| #[clap(long = "preserve-var-skip", value_name = "PATH")] | ||
| pub(crate) preserve_var_skip: Vec<String>, |
There was a problem hiding this comment.
Nothing ties this to --preserve-var, so without it the paths are silently ignored. And install_to_existing_root now loads and validates preserve-var-skip from the install config on every run (L3185-3190), so a bad entry there breaks to-existing-root even without --preserve-var. Maybe requires = "preserve_var", and validate only when it's set?
| useful for preserving network settings, user accounts, or application data from the | ||
| previous installation. | ||
|
|
||
| With the OSTree backend, `--preserve-var` copies the old `/var` into the new |
There was a problem hiding this comment.
This could use a sentence on SSH, or a default exclusion. fedora-bootc:44 and centos-bootc:stream10 both ship cloud-init, and where cloud-init is active sshd-keygen@ stands down for it. The host's /var/lib/cloud is carried over, so cloud-init sees the same instance and doesn't create host keys, and the old keys stay in the old /etc. After each successful migration I could check (F44 and CS10, NoCloud), there were no host keys, so sshd fails and the host is unreachable over SSH. In the one run where nothing was copied, cloud-init generated new keys.
Check source /var and nested mountpoint types before installation can replace the old bootable state. Reuse the resulting plan for the post-install copy, while documenting that copy and capacity failures can still occur late. Assisted-by: AI
The new deployment's /var can already contain image data at nested mount destinations. Retain those entries when their types match, preserve policy-provided SELinux labels, and let cp fall back for individual files that cannot be reflinked. Assisted-by: AI
Skip paths only affect preserve-var installs. Require the CLI option to be paired with --preserve-var and defer reading and validating config exclusions until that mode is active. Assisted-by: AI
HostDisabled installs can skip physical-root relabeling of old /var, leaving preserved data with source labels. Relabel staged migration entries against the installed deployment's logical /var paths before publication, without changing seeded collision winners or unrelated metadata. Assisted-by: AI
The migration test needs to exercise source preflight, separate and temporary mounts, persistent application data, and a complete reboot without losing TMT state. Keep the TMT run directory at a real path under preserved /var/lib and pass the configured test image through guest preparation. Assisted-by: AI
The install guide distinguishes preserved root authorized keys from host keys in the old /etc, and warns that retained cloud-init state can suppress host-key generation. The TMT guide documents the Fedora 44 and CentOS Stream 10 VM commands and the durable local workdir prerequisite. Assisted-by: AI
GNU cp -a can preserve aliases whose logical paths map to different SELinux labels. Applying those labels in traversal order would leave the shared inode mislabeled, so validate every staged alias before changing labels or publishing the staged entries. Assisted-by: AI
Local package-mode tests should run without root access. Keep TMT workdirs in the developer cache, verify the guest mirror is preserved across migration, and encode the LBI list in a TMT-compatible environment file. Assisted-by: AI
The Packit artifact workdir path needs the same preservation safeguards as local TMT workdirs, and a failed migration must not leave /var/log frozen. Validate the artifact directory and make freeze cleanup run on normal exits and signals while retaining existing traps and exit status. Assisted-by: AI
A signal or failed fsfreeze could leave /var/log frozen because the cleanup handlers were installed afterward. Install traps before the freeze attempt and use one EXIT cleanup path that preserves the original status. Assisted-by: AI
The package-mode runner currently asks TMT to discover directly from a large checkout, which makes TMT 1.69 traverse ignored build output. Discover from a temporary sanitized snapshot instead, and retain the local OCI archive for guest sync. Assisted-by: AI
The local package-mode test image must use OSTree regardless of the caller's variant. Forward the other configured build settings and override the variant only on the nested build. Assisted-by: AI
Keep root-level Podman build secrets out of the guest snapshot and clean them up if the build or test setup fails. Assisted-by: AI
The package-mode test currently removes every root build-secret pathname, including files that were present before the test began. Snapshot matching pathnames before installing cleanup and remove only new matches while preserving command status. Assisted-by: AI
Podman build secret paths are shared temporary paths, so cleanup from this runner could delete files owned by concurrent builds or users. Leave lifecycle management to Podman and exclude stale artifacts from the test snapshot. Assisted-by: AI
Fedora package-mode guests can keep /home outside /var, so preserve the complete lexical TMT run tree under /var/home before migration. Boot the source with SELinux disabled and verify the target relabels fresh application and PostgreSQL state when it starts enforcing. Assisted-by: AI
The package-mode VM can expose /home as a real directory, so the lexical controller workdir may not be preserved by migration. Derive the destination from the resolved TMT root and run ID, and assert test SSH key labels against target policy in both SELinux phases. Assisted-by: AI
The Fedora package-mode test mounts /var/lib/pgsql from the source guest, but that path is not guaranteed to exist. Create it before running the target-image PostgreSQL initializer. Assisted-by: AI
The guest creates the PostgreSQL mountpoint as root, but initdb needs it to be writable by postgres. Set its numeric ownership from the target image and restrict its mode before database setup. Assisted-by: AI
The PostgreSQL data directory must be a normal directory beneath the bind mount, not the mountpoint itself. Seed it through the target image as its postgres user so the preserved data uses the target UID/GID and remains compatible with the post-migration service. Assisted-by: AI
The one-shot target-image container does not start systemd, so PostgreSQL's default socket directory may be unavailable. Configure a /tmp socket and connect the seed queries over loopback TCP. Assisted-by: AI
The target image already provides /var/lib/pgsql, while /mnt may not exist. Seed in the mounted data directory so the state survives preserve-var and is available to the target service. Assisted-by: AI
Check that the target image already contains /var/lib/pgsql before attaching a bind mount there. This ensures the seed run cannot pass by relying on Podman's bind-mount behavior to create a missing destination. Assisted-by: AI
The full /boot tar snapshot is sensitive to incidental metadata changes, which can make a rejected preflight appear to mutate boot configuration. Compare only the paths and contents of boot-critical files instead. Assisted-by: AI
The rejected preflight check should detect changes to all active EFI loader entries, including the architecture-independent fallback path. Record symlink targets alongside referent content digests so retargeting links is visible. Assisted-by: AI
The package-mode guest has a normal BLS entry before migration, so the preflight snapshot must not require an OSTree-prefixed name. Assisted-by: AI
A leftover OSTree BLS entry must not satisfy the package-mode baseline check. Assisted-by: AI
Splitting
--preserve-varoff of #2384