From 1b81b183b7cb6ff09961b01ed6c2a9c9030b616a Mon Sep 17 00:00:00 2001 From: Itxaka Date: Fri, 25 Mar 2022 15:26:48 +0100 Subject: [PATCH] Add a eject-cd flag for install (#156) --- cmd/install.go | 1 + pkg/action/action_test.go | 40 ++++++++++++++++++++++++++++++++++++++ pkg/action/install.go | 9 +++++++++ pkg/constants/constants.go | 3 +++ pkg/types/v1/config.go | 1 + 5 files changed, 54 insertions(+) diff --git a/cmd/install.go b/cmd/install.go index daeb20c3..f3ff8812 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -89,5 +89,6 @@ func init() { installCmd.Flags().BoolP("force-gpt", "", false, "Forces a GPT partition table") installCmd.Flags().BoolP("tty", "", false, "Add named tty to grub") installCmd.Flags().BoolP("force", "", false, "Force install") + installCmd.Flags().BoolP("eject-cd", "", false, "Try to eject the cd on reboot, only valid if booting from iso") addSharedInstallUpgradeFlags(installCmd) } diff --git a/pkg/action/action_test.go b/pkg/action/action_test.go index 7c28443a..b38afab7 100644 --- a/pkg/action/action_test.go +++ b/pkg/action/action_test.go @@ -354,6 +354,7 @@ var _ = Describe("Actions", func() { Describe("Install Action", Label("install"), func() { var device, cmdFail string var err error + var cmdline func() ([]byte, error) BeforeEach(func() { device = "/some/device" @@ -395,6 +396,11 @@ var _ = Describe("Actions", func() { {"label": "COS_PERSISTENT", "type": "part", "path": "/some/device4"} ] }`), nil + case "cat": + if args[0] == "/proc/cmdline" { + return cmdline() + } + return []byte{}, nil default: return []byte{}, nil } @@ -411,6 +417,11 @@ var _ = Describe("Actions", func() { Expect(err).To(BeNil()) _, err = fs.Create(grubCfg) Expect(err).To(BeNil()) + + // Set default cmdline function so we dont panic :o + cmdline = func() ([]byte, error) { + return []byte{}, nil + } }) It("Successfully installs", func() { @@ -420,6 +431,35 @@ var _ = Describe("Actions", func() { Expect(runner.IncludesCmds([][]string{{"reboot", "-f"}})) }) + It("Sets the executable /run/cos/ejectcd so systemd can eject the cd on restart", func() { + _ = utils.MkdirAll(fs, "/usr/lib/systemd/system-shutdown", constants.DirPerm) + _, err := fs.Stat("/usr/lib/systemd/system-shutdown/eject") + Expect(err).To(HaveOccurred()) + // Override cmdline to return like we are booting from cd + cmdline = func() ([]byte, error) { + return []byte("cdroot"), nil + } + config.Target = device + config.EjectCD = true + Expect(action.InstallRun(config)).To(BeNil()) + _, err = fs.Stat("/usr/lib/systemd/system-shutdown/eject") + Expect(err).ToNot(HaveOccurred()) + file, err := fs.ReadFile("/usr/lib/systemd/system-shutdown/eject") + Expect(err).ToNot(HaveOccurred()) + Expect(file).To(ContainSubstring(constants.EjectScript)) + }) + + It("ejectcd does nothing if we are not booting from cd", func() { + _ = utils.MkdirAll(fs, "/usr/lib/systemd/system-shutdown", constants.DirPerm) + _, err := fs.Stat("/usr/lib/systemd/system-shutdown/eject") + Expect(err).To(HaveOccurred()) + config.Target = device + config.EjectCD = true + Expect(action.InstallRun(config)).To(BeNil()) + _, err = fs.Stat("/usr/lib/systemd/system-shutdown/eject") + Expect(err).To(HaveOccurred()) + }) + It("Successfully installs despite hooks failure", Label("hooks"), func() { cloudInit.Error = true config.Target = device diff --git a/pkg/action/install.go b/pkg/action/install.go index b404167e..3ee9a6ef 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -249,6 +249,15 @@ func InstallRun(config *v1.RunConfig) (err error) { //nolint:gocyclo return err } + // If we want to eject the cd, create the required executable so the cd is ejected at shutdown + if config.EjectCD && utils.BootedFrom(config.Runner, "cdroot") { + config.Logger.Infof("Writing eject script") + err = config.Fs.WriteFile("/usr/lib/systemd/system-shutdown/eject", []byte(cnst.EjectScript), 0744) + if err != nil { + config.Logger.Warnf("Could not write eject script, cdrom wont be ejected automatically: %s", err) + } + } + // Reboot, poweroff or nothing if config.Reboot { config.Logger.Infof("Rebooting in 5 seconds") diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 769093e3..683bf93f 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -92,6 +92,9 @@ const ( // Default directory and file fileModes DirPerm = os.ModeDir | os.ModePerm FilePerm = 0666 + + // Eject script + EjectScript = "#!/bin/sh\n/usr/bin/eject -rmF" ) func GetCloudInitPaths() []string { diff --git a/pkg/types/v1/config.go b/pkg/types/v1/config.go index 689d1c93..ce4179e3 100644 --- a/pkg/types/v1/config.go +++ b/pkg/types/v1/config.go @@ -66,6 +66,7 @@ type RunConfig struct { ImgSize uint `yaml:"DEFAULT_IMAGE_SIZE,omitempty" mapstructure:"DEFAULT_IMAGE_SIZE"` Directory string `yaml:"directory,omitempty" mapstructure:"directory"` ResetPersistent bool `yaml:"reset-persistent,omitempty" mapstructure:"reset-persistent"` + EjectCD bool `yaml:"eject-cd,omitempty" mapstructure:"eject-cd"` // Internally used to track stuff around PartTable string BootFlag string