Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 123 additions & 25 deletions cmd/snap-bootstrap/cmd_initramfs_mounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"github.com/snapcore/snapd/seed"
"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/snap/naming"
"github.com/snapcore/snapd/snap/snapdir"
"github.com/snapcore/snapd/snap/squashfs"
"github.com/snapcore/snapd/sysconfig"
"github.com/snapcore/snapd/timings"
Expand Down Expand Up @@ -258,13 +259,27 @@
if err != nil {
return nil, err
}
// Comes from the seed and it might be unasserted, set revision in that case
if info.Revision.Unset() {
info.Revision = snap.R(-1)
}
return info, nil

}

func readComponentInfo(seedComp *seed.Component, mntPt string, snapInfo *snap.Info, csi *snap.ComponentSideInfo) (*snap.ComponentInfo, error) {
container := snapdir.New(mntPt)
ci, err := snap.ReadComponentInfoFromContainer(container, snapInfo, csi)
if err != nil {
return nil, err
}

Check warning on line 275 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L274-L275

Added lines #L274 - L275 were not covered by tests
// Comes from the seed and it might be unasserted, set revision in that case
if ci.Revision.Unset() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what cases are the revision unset? And why does it need to be set to x1?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When reading from the seed, if the component is unasserted. Note that this is the same that was being done for snaps in readSnapInfo. I've added comments to clarify.

ci.Revision = snap.R(-1)
}

Check warning on line 279 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L278-L279

Added lines #L278 - L279 were not covered by tests
return ci, nil
}

func runFDESetupHook(req *fde.SetupRequest) ([]byte, error) {
// TODO: use systemd-run
encoded, err := json.Marshal(req)
Expand Down Expand Up @@ -331,26 +346,77 @@
return fmt.Errorf("cannot use gadget: %v", err)
}

// TODO:COMPS take into account kernel-modules components, see
// DeviceManager,doSetupRunSystem and other parts of
// handlers_install.go.
// Get kernel-modules information to have them ready early on first boot

bootDevice := ""
kernelSnapInfo := &gadgetInstall.KernelSnapInfo{
Name: kernelSnap.SnapName(),
MountPoint: kernelMountDir,
Revision: kernelSnap.Revision,
// Should be true always anyway
IsCore: !model.Classic(),
}
switch model.Base() {
case "core20", "core22", "core22-desktop":
kernelSnapInfo.NeedsDriversTree = false
default:
kernelSnapInfo.NeedsDriversTree = true
kernCompsByName := make(map[string]*snap.Component)
for _, c := range kernelSnap.Components {
kernCompsByName[c.Name] = c
}

kernelSeed := sysSnaps[snap.TypeKernel]
kernCompsMntPts := make(map[string]string)
compSeedInfos := []install.ComponentSeedInfo{}
for _, sc := range kernelSeed.Components {
seedComp := sc
comp, ok := kernCompsByName[seedComp.CompSideInfo.Component.ComponentName]
if !ok {
return fmt.Errorf("component %s in seed but not defined by snap!",
seedComp.CompSideInfo.Component.ComponentName)
}

Check warning on line 365 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L363-L365

Added lines #L363 - L365 were not covered by tests
if comp.Type != snap.KernelModulesComponent {
continue

Check warning on line 367 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L367

Added line #L367 was not covered by tests
}

// Mount ephemerally the kernel-modules components to read
// their metadata and also to make them accessible if building
// the drivers tree.
mntPt := filepath.Join(filepath.Join(boot.InitramfsRunMntDir, "snap-content",
seedComp.CompSideInfo.Component.String()))
if err := doSystemdMount(seedComp.Path, mntPt, &systemdMountOptions{
ReadOnly: true,
Private: true,
Ephemeral: true}); err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a test in this error case to ensure the unmounts are called correctly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a test now

}
kernCompsMntPts[seedComp.CompSideInfo.Component.String()] = mntPt

defer func() {
stdout, stderr, err := osutil.RunSplitOutput("systemd-mount", "--umount", mntPt)
if err != nil {
logger.Noticef("cannot unmount component in %s: %v",
mntPt, osutil.OutputErrCombine(stdout, stderr, err))
}

Check warning on line 388 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L386-L388

Added lines #L386 - L388 were not covered by tests
}()

compInfo, err := readComponentInfo(&seedComp, mntPt, kernelSnap, &seedComp.CompSideInfo)
if err != nil {
return err
}

Check warning on line 394 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L393-L394

Added lines #L393 - L394 were not covered by tests
compSeedInfos = append(compSeedInfos, install.ComponentSeedInfo{
Info: compInfo,
Seed: &seedComp,
})
}

installedSystem, err := gadgetInstallRun(model, gadgetMountDir, kernelSnapInfo, bootDevice, options, installObserver, timings.New(nil))
currentSeed, err := mst.LoadSeed(mst.recoverySystem)
if err != nil {
return err
}

Check warning on line 404 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L403-L404

Added lines #L403 - L404 were not covered by tests
preseedSeed, ok := currentSeed.(seed.PreseedCapable)
preseed := false
if ok && preseedSeed.HasArtifact("preseed.tgz") {
preseed = true
}
// Drivers tree will already be built if using the preseed tarball
needsKernelSetup := kernel.NeedsKernelDriversTree(model) && !preseed

isCore := !model.Classic()
kernelBootInfo := install.BuildKernelBootInfo(
kernelSnap, compSeedInfos, kernelMountDir, kernCompsMntPts,
install.BuildKernelBootInfoOpts{IsCore: isCore, NeedsDriversTree: needsKernelSetup})

bootDevice := ""
installedSystem, err := gadgetInstallRun(model, gadgetMountDir, kernelBootInfo.KSnapInfo, bootDevice, options, installObserver, timings.New(nil))
if err != nil {
return err
}
Expand Down Expand Up @@ -382,6 +448,7 @@
KernelPath: sysSnaps[snap.TypeKernel].Path,
UnpackedGadgetDir: gadgetMountDir,
RecoverySystemLabel: mst.recoverySystem,
KernelMods: kernelBootInfo.BootableKMods,
}

if err := bootMakeRunnableStandaloneSystem(model, bootWith, trustedInstallObserver); err != nil {
Expand All @@ -395,15 +462,27 @@
return err
}

currentSeed, err := mst.LoadSeed(mst.recoverySystem)
if preseed {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment about why different behavior is required for this case would be nice

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

// Extract pre-seed tarball
runMode := false
if err := installApplyPreseededData(preseedSeed,
boot.InitramfsWritableDir(model, runMode)); err != nil {
return err
}

Check warning on line 471 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L470-L471

Added lines #L470 - L471 were not covered by tests
}

// Create drivers tree mount units to make it available before switch root
rootfsDir := filepath.Join(boot.InitramfsDataDir, "system-data")
hasDriversTree, err := createKernelMounts(
rootfsDir, kernelSnap.SnapName(), kernelSnap.Revision, !isCore)
if err != nil {
return err
}
preseedSeed, ok := currentSeed.(seed.PreseedCapable)
if ok && preseedSeed.HasArtifact("preseed.tgz") {
runMode := false
if err := installApplyPreseededData(preseedSeed, boot.InitramfsWritableDir(model, runMode)); err != nil {
return err
if hasDriversTree {
// Unmount the kernel snap mount, we keep it only for UC20/22
stdout, stderr, err := osutil.RunSplitOutput("systemd-mount", "--umount", kernelMountDir)
if err != nil {
return osutil.OutputErrCombine(stdout, stderr, err)

Check warning on line 485 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L485

Added line #L485 was not covered by tests
}
}

Expand Down Expand Up @@ -432,6 +511,25 @@
}

if installAndRun {
kernSnap := snaps[snap.TypeKernel]
// seed is cached at this point
theSeed, err := mst.LoadSeed("")
if err != nil {
return fmt.Errorf("internal error: cannot load seed: %v", err)
}

Check warning on line 519 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L518-L519

Added lines #L518 - L519 were not covered by tests
// Filter by mode, this is relevant only to get the
// kernel-modules components that are used in run mode and
// therefore need to be considered when installing from the
// initramfs to have the modules available early on first boot.
// TODO when running normal install or recover/factory-reset,
// we would need also this if we want the modules to be
// available early.
kernSnap, err = theSeed.ModeSnap(kernSnap.SnapName(), "run")
if err != nil {
return err
}

Check warning on line 530 in cmd/snap-bootstrap/cmd_initramfs_mounts.go

View check run for this annotation

Codecov / codecov/patch

cmd/snap-bootstrap/cmd_initramfs_mounts.go#L529-L530

Added lines #L529 - L530 were not covered by tests
snaps[snap.TypeKernel] = kernSnap

if err := doInstall(mst, model, snaps); err != nil {
return err
}
Expand Down Expand Up @@ -1979,9 +2077,9 @@

// First in modules (we might not have a kernel version subdir if there
// are no kernel modules).
kversion, kverr := kernel.KernelVersionFromModulesDir(filepath.Join(driversDir, "lib"))
kversion, kver := kernel.KernelVersionFromModulesDir(filepath.Join(driversDir, "lib"))
compSet := map[snap.ComponentSideInfo]bool{}
if kverr == nil {
if kver == nil {
modUpdatesDir := filepath.Join(driversDir, "lib", "modules", kversion, "updates")
if err := getCompsFromSymlinks(modUpdatesDir, kernelName, compSet); err != nil {
return err
Expand Down
Loading
Loading