diff --git a/dracut/28immucore/module-setup.sh b/dracut/28immucore/module-setup.sh index 2eebe41..5c95daf 100755 --- a/dracut/28immucore/module-setup.sh +++ b/dracut/28immucore/module-setup.sh @@ -7,7 +7,7 @@ check() { # called by dracut depends() { - echo rootfs-block dm fs-lib + echo rootfs-block dm fs-lib lvm return 0 } @@ -27,9 +27,11 @@ install() { inst_multiple kcrypt partprobe sync udevadm parted mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.vfat mkfs.fat blkid e2fsck resize2fs mount umount sgdisk rsync # missing mkfs.xfs xfs_growfs in image? inst_script "${moddir}/generator.sh" "${systemdutildir}/system-generators/immucore-generator" + # SERVICES FOR SYSTEMD-BASED SYSTEMS inst_simple "${moddir}/immucore.service" "${systemdsystemunitdir}/immucore.service" mkdir -p "${initdir}/${systemdsystemunitdir}/initrd.target.requires" ln_r "../immucore.service" "${systemdsystemunitdir}/initrd.target.requires/immucore.service" + # END SYSTEMD SERVICES dracut_need_initqueue } diff --git a/internal/constants/constants.go b/internal/constants/constants.go index b988873..ef60b89 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -34,6 +34,7 @@ const ( OpUkiBaseMounts = "uki-base-mounts" OpUkiKernelModules = "uki-kernel-modules" OpWaitForSysroot = "wait-for-sysroot" + OpLvmActivate = "lvm-activation" PersistentStateTarget = "/usr/local/.state" LogDir = "/run/immucore" LinuxFs = "ext4" diff --git a/internal/utils/mounts.go b/internal/utils/mounts.go index cf37212..8756ef2 100644 --- a/internal/utils/mounts.go +++ b/internal/utils/mounts.go @@ -262,3 +262,18 @@ func GetOemLabel() string { } return runtime.OEM.FilesystemLabel } + +func ActivateLVM() error { + // Remove the /etc/lvm/lvm.conf file + // Otherwise, it has a default locking setting which activates the volumes on readonly + // This would be the same as passing rd.lvm.conf=0 in cmdline but rather do it here than add an extra option to cmdline + _, _ = CommandWithPath("rm /etc/lvm/lvm.conf") + out, err := CommandWithPath("lvm vgchange --refresh --sysinit") + Log.Debug().Str("out", out).Msg("vgchange") + if err != nil { + Log.Err(err).Msg("vgchange") + } + + _, _ = CommandWithPath("udevadm --trigger") + return err +} diff --git a/pkg/mount/dag_normal_boot.go b/pkg/mount/dag_normal_boot.go index 34d9487..661823d 100644 --- a/pkg/mount/dag_normal_boot.go +++ b/pkg/mount/dag_normal_boot.go @@ -12,7 +12,8 @@ import ( func (s *State) RegisterNormalBoot(g *herd.Graph) error { var err error - // TODO: add hooks, fstab (might have missed some), systemd compat, fsck + s.LogIfError(s.LVMActivation(g), "lvm activation") + // Maybe LogIfErrorAndPanic ? If no sentinel, a lot of config files are not going to run if err = s.LogIfErrorAndReturn(s.WriteSentinelDagStep(g), "write sentinel"); err != nil { return err @@ -24,7 +25,7 @@ func (s *State) RegisterNormalBoot(g *herd.Graph) error { s.LogIfError(s.MountRootDagStep(g), "running mount root stage") // Mount COS_OEM (After root as it mounts under s.Rootdir/oem) - s.LogIfError(s.MountOemDagStep(g, cnst.OpMountRoot), "oem mount") + s.LogIfError(s.MountOemDagStep(g, cnst.OpMountRoot, cnst.OpLvmActivate), "oem mount") // Run yip stage rootfs. Requires root+oem+sentinel to be mounted s.LogIfError(s.RootfsStageDagStep(g, herd.WithDeps(cnst.OpMountRoot, cnst.OpMountOEM, cnst.OpSentinel)), "running rootfs stage") diff --git a/pkg/mount/dag_steps.go b/pkg/mount/dag_steps.go index 1e31577..acf91c2 100644 --- a/pkg/mount/dag_steps.go +++ b/pkg/mount/dag_steps.go @@ -586,3 +586,10 @@ func (s *State) WaitForSysrootDagStep(g *herd.Graph) error { } })) } + +// LvmActivation will try to activate lvm volumes/groups on the system. +func (s *State) LVMActivation(g *herd.Graph) error { + return g.Add(cnst.OpLvmActivate, herd.WithCallback(func(ctx context.Context) error { + return internalUtils.ActivateLVM() + })) +} diff --git a/pkg/mount/state.go b/pkg/mount/state.go index b02220e..ab03b0d 100644 --- a/pkg/mount/state.go +++ b/pkg/mount/state.go @@ -121,6 +121,7 @@ func (s *State) RunStageOp(stage string) func(context.Context) error { // MountOP creates and executes a mount operation. func (s *State) MountOP(what, where, t string, options []string, timeout time.Duration) func(context.Context) error { + l := internalUtils.Log.With().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Logger().Level(zerolog.InfoLevel) // Not sure why this defaults to debuglevel when creating a sublogger, so make sure we set it properly debug := len(internalUtils.ReadCMDLineArg("rd.immucore.debug")) > 0 @@ -133,6 +134,12 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du for { select { default: + // check fs type just-in-time before running the OP + fsType := internalUtils.DiskFSType(what) + // If not empty and it does not match + if fsType != "" && t != fsType { + t = fsType + } err := internalUtils.CreateIfNotExists(where) if err != nil { l.Err(err).Msg("Creating dir") diff --git a/pkg/mount/state_test.go b/pkg/mount/state_test.go index c5094b3..6d042e3 100644 --- a/pkg/mount/state_test.go +++ b/pkg/mount/state_test.go @@ -86,7 +86,7 @@ func checkLiveCDDag(dag [][]herd.GraphEntry, actualDag string) { func checkDag(dag [][]herd.GraphEntry, actualDag string) { Expect(len(dag)).To(Equal(12), actualDag) Expect(len(dag[0])).To(Equal(1), actualDag) - Expect(len(dag[1])).To(Equal(3), actualDag) + Expect(len(dag[1])).To(Equal(4), actualDag) Expect(len(dag[2])).To(Equal(1), actualDag) Expect(len(dag[3])).To(Equal(1), actualDag) Expect(len(dag[4])).To(Equal(1), actualDag) @@ -103,16 +103,25 @@ func checkDag(dag [][]herd.GraphEntry, actualDag string) { Equal(cnst.OpMountTmpfs), Equal(cnst.OpSentinel), Equal(cnst.OpMountState), + Equal(cnst.OpLvmActivate), ), actualDag) Expect(dag[1][1].Name).To(Or( Equal(cnst.OpMountTmpfs), Equal(cnst.OpSentinel), Equal(cnst.OpMountState), + Equal(cnst.OpLvmActivate), ), actualDag) Expect(dag[1][2].Name).To(Or( Equal(cnst.OpMountTmpfs), Equal(cnst.OpSentinel), Equal(cnst.OpMountState), + Equal(cnst.OpLvmActivate), + ), actualDag) + Expect(dag[1][3].Name).To(Or( + Equal(cnst.OpMountTmpfs), + Equal(cnst.OpSentinel), + Equal(cnst.OpMountState), + Equal(cnst.OpLvmActivate), ), actualDag) Expect(dag[2][0].Name).To(Equal(cnst.OpDiscoverState), actualDag) Expect(dag[3][0].Name).To(Equal(cnst.OpMountRoot), actualDag)