From 3e4693d6974bcc018737512fe3a48bcf5ca1276b Mon Sep 17 00:00:00 2001 From: Itxaka Date: Fri, 15 Sep 2023 15:40:27 +0200 Subject: [PATCH] Workaround for bundle install in new /var/lib/extensions directory (#147) --- internal/agent/hooks/bundles.go | 44 +++++++++++++++++++++++++++++---- internal/agent/hooks/hook.go | 4 +-- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/internal/agent/hooks/bundles.go b/internal/agent/hooks/bundles.go index 194314e..a8ab45e 100644 --- a/internal/agent/hooks/bundles.go +++ b/internal/agent/hooks/bundles.go @@ -5,24 +5,57 @@ import ( v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1" "github.com/kairos-io/kairos-sdk/bundles" "github.com/kairos-io/kairos-sdk/machine" + "os" + "os/exec" + "syscall" ) -type BundleOption struct{} +// BundlePostInstall install bundles just after installation +type BundlePostInstall struct{} -func (b BundleOption) Run(c config.Config, _ v1.Spec) error { +func (b BundlePostInstall) Run(c config.Config, _ v1.Spec) error { + // system extension are now installed to /var/lib/extensions + // https://github.com/kairos-io/kairos/issues/1821 + // so if we want them to work as expected we need to mount the persistent dir and the bind dir that will + // then end up in the system as /usr/lib/extensions is not valid anymore + // So after the install from livecd we need to: + // - mount persistent in /usr/local + // - create the dir that will be binded into /var/lib/extensions after reboot in /usr/local/.state/var-lib-extensions.bind + // - rsync whatever is in the /var/lib/extensions to /usr/local/.state/var-lib-extensions.bind so we dont lost thing shipped with the install media + // - bind the dir so the extension gets persistent after reboots + // - umount the bind dir + // Note that the binding of /usr/local/.state/var-lib-extensions.bind to /var/lib/extensions on active/passive its done by inmmucore based on the + // 00_rootfs.yaml config which sets the bind and ephemeral paths. machine.Mount("COS_PERSISTENT", "/usr/local") //nolint:errcheck defer func() { machine.Umount("/usr/local") //nolint:errcheck }() + err := os.MkdirAll("/usr/local/.state/var-lib-extensions.bind", os.ModeDir|os.ModePerm) + if c.FailOnBundleErrors && err != nil { + return err + } + cmd := exec.Command("rsync -aqAX /var/lib/extensions /usr/local/.state/var-lib-extensions.bind") + _, err = cmd.CombinedOutput() + if c.FailOnBundleErrors && err != nil { + return err + } + err = syscall.Mount("/usr/local/.state/var-lib-extensions.bind", "/var/lib/extensions", "", syscall.MS_BIND, "") + if c.FailOnBundleErrors && err != nil { + return err + } + defer func() { + _ = syscall.Unmount("/var/lib/extensions", 0) + }() + machine.Mount("COS_OEM", "/oem") //nolint:errcheck defer func() { machine.Umount("/oem") //nolint:errcheck }() opts := c.Install.Bundles.Options() - err := bundles.RunBundles(opts...) + err = bundles.RunBundles(opts...) if c.FailOnBundleErrors && err != nil { return err } @@ -30,9 +63,10 @@ func (b BundleOption) Run(c config.Config, _ v1.Spec) error { return nil } -type BundlePostInstall struct{} +// BundleFirstBoot installs bundles during the first boot of the machine +type BundleFirstBoot struct{} -func (b BundlePostInstall) Run(c config.Config, _ v1.Spec) error { +func (b BundleFirstBoot) Run(c config.Config, _ v1.Spec) error { opts := c.Bundles.Options() err := bundles.RunBundles(opts...) if c.FailOnBundleErrors && err != nil { diff --git a/internal/agent/hooks/hook.go b/internal/agent/hooks/hook.go index 925f469..3a5b5bf 100644 --- a/internal/agent/hooks/hook.go +++ b/internal/agent/hooks/hook.go @@ -11,7 +11,7 @@ type Interface interface { var AfterInstall = []Interface{ &GrubOptions{}, // Set custom GRUB options - &BundleOption{}, + &BundlePostInstall{}, &CustomMounts{}, &Kcrypt{}, &Lifecycle{}, // Handles poweroff/reboot by config options @@ -26,7 +26,7 @@ var AfterUpgrade = []Interface{ } var FirstBoot = []Interface{ - &BundlePostInstall{}, + &BundleFirstBoot{}, &GrubPostInstallOptions{}, }