Skip to content

Commit

Permalink
Load mount-layout from .env-files (#1885)
Browse files Browse the repository at this point in the history
* Load mount-layout from .env-files

Adds code to load environment variables OVERLAY, RW_PATHS,
PERSISTENT_STATE_PATHS and PERSISTENT_STATE_BINDS during mounting.

The variables are read from /run/cos/cos-layout.env and
/run/elemental/mount-layout.env if they exist.

Signed-off-by: Fredrik Lönnegren <[email protected]>
  • Loading branch information
frelon authored Dec 14, 2023
1 parent 48966fa commit b33f303
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 7 deletions.
74 changes: 74 additions & 0 deletions cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ func ReadMountSpec(r *v1.RunConfig, flags *pflag.FlagSet) (*v1.MountSpec, error)
return mount, err
}

if err := applyMountEnvVars(r, mount); err != nil {
r.Logger.Errorf("Error reading mount env-vars: %s", err.Error())
return mount, err
}

if err := applyKernelCmdline(r, mount); err != nil {
r.Logger.Errorf("Error reading kernel cmdline: %s", err.Error())
return mount, err
Expand Down Expand Up @@ -312,6 +317,11 @@ func applyKernelCmdline(r *v1.RunConfig, mount *v1.MountSpec) error {
r.Logger.Errorf("Error parsing cmdline %s", cmd)
return errors.New("Unknown image path")
}
case "elemental.overlay", "rd.cos.overlay":
err := applyMountOverlay(mount, val)
if err != nil {
return err
}
case "elemental.oemlabel", "rd.cos.oemlabel":
mount.Partitions.OEM.FilesystemLabel = val
}
Expand All @@ -320,6 +330,70 @@ func applyKernelCmdline(r *v1.RunConfig, mount *v1.MountSpec) error {
return nil
}

func applyMountEnvVars(r *v1.RunConfig, mount *v1.MountSpec) error {
r.Logger.Debugf("Applying mount env-vars")

overlay := os.Getenv("OVERLAY")
if overlay != "" {
r.Logger.Debugf("Setting ephemeral settings based on OVERLAY")

err := applyMountOverlay(mount, overlay)
if err != nil {
return err
}
}

rwPaths := os.Getenv("RW_PATHS")
if rwPaths != "" {
r.Logger.Debugf("Setting ephemeral paths based on RW_PATHS")
mount.Ephemeral.Paths = strings.Split(rwPaths, " ")
}

persistentPaths := os.Getenv("PERSISTENT_STATE_PATHS")
if persistentPaths != "" {
r.Logger.Debugf("Setting persistent paths based on PERSISTENT_STATE_PATHS")
mount.Persistent.Paths = strings.Split(persistentPaths, " ")
}

persistentBind := os.Getenv("PERSISTENT_STATE_BIND")
if persistentBind != "" {
r.Logger.Debugf("Setting persistent bind based on PERSISTENT_STATE_BIND")
mount.Persistent.Mode = constants.BindMode
}

return nil
}

func applyMountOverlay(mount *v1.MountSpec, overlay string) error {
split := strings.Split(overlay, ":")

if len(split) == 2 && split[0] == constants.Tmpfs {
mount.Ephemeral.Device = ""
mount.Ephemeral.Type = split[0]
mount.Ephemeral.Size = split[1]
return nil
}

mount.Ephemeral.Type = constants.Block
mount.Ephemeral.Size = ""

blockSplit := strings.Split(overlay, "=")
if len(blockSplit) != 2 {
return fmt.Errorf("Unknown block overlay '%s'", overlay)
}

switch blockSplit[0] {
case "LABEL":
mount.Ephemeral.Device = fmt.Sprintf("/dev/disk/by-label/%s", blockSplit[1])
case "UUID":
mount.Ephemeral.Device = fmt.Sprintf("/dev/disk/by-uuid/%s", blockSplit[1])
default:
return fmt.Errorf("Unknown block overlay '%s'", overlay)
}

return nil
}

func ReadResetSpec(r *v1.RunConfig, flags *pflag.FlagSet) (*v1.ResetSpec, error) {
reset, err := config.NewResetSpec(r.Config)
if err != nil {
Expand Down
29 changes: 28 additions & 1 deletion cmd/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ var _ = Describe("Config", Label("config"), func() {
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{})
Expect(err).Should(BeNil())

err = fs.Mkdir("/proc", constants.DirPerm)
Expect(err).Should(BeNil())
err = fs.WriteFile("/proc/cmdline", []byte("root=LABEL=COS_STATE elemental.image=active elemental.overlay=tmpfs:30%"), 0444)
Expect(err).Should(BeNil())

cfg, err = ReadConfigRun("fixtures/config/", nil, mounter)
Expect(err).Should(BeNil())

Expand Down Expand Up @@ -449,6 +454,28 @@ var _ = Describe("Config", Label("config"), func() {
Expect(spec.RecoveryUpgrade).To(BeTrue())
})
})

Describe("Read MountSpec", Label("mount"), func() {
It("inits a mount spec according to given configs", func() {
err := os.Setenv("ELEMENTAL_MOUNT_SYSROOT", "/newroot")
spec, err := ReadMountSpec(cfg, nil)
Expect(err).ShouldNot(HaveOccurred())
Expect(spec.Mode).To(Equal("active"))
Expect(spec.Sysroot).To(Equal("/newroot"))
})
It("picks kernel cmdline first then env-vars", func() {
err := os.Setenv("ELEMENTAL_MOUNT_IMAGE", "passive")
spec, err := ReadMountSpec(cfg, nil)
Expect(err).ShouldNot(HaveOccurred())
// Set by kernel cmdline
Expect(spec.Mode).To(Equal("active"))
})
It("picks kernel cmdline first then env-vars", func() {
err := os.Setenv("OVERLAY", "UUID=1234")
spec, err := ReadMountSpec(cfg, nil)
Expect(err).ShouldNot(HaveOccurred())
Expect(spec.Ephemeral.Type).To(Equal("tmpfs"))
Expect(spec.Ephemeral.Size).To(Equal("30%"))
})
})
})
})
6 changes: 2 additions & 4 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,8 @@ func GetInitKeyEnvMap() map[string]string {
// GetMountKeyEnvMap returns environment variable bindings to MountSpec data
func GetMountKeyEnvMap() map[string]string {
return map[string]string{
"write-fstab": "WRITE_FSTAB",
"write-sentinel": "WRITE_SENTINEL",
"sysroot": "SYSROOT",
"read-kernel-cmdline": "READ_KERNEL_CMDLINE",
"write-fstab": "WRITE_FSTAB",
"sysroot": "SYSROOT",
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ stages:
providers: ["aws", "gcp", "openstack", "cdrom"]
path: "/oem"
rootfs:
- if: '[ ! -f "/run/cos/recovery_mode" ]'
- if: '[ ! -f "/run/elemental/recovery_mode" ]'
name: "Layout configuration"
environment_file: /run/cos/cos-layout.env
environment:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Conflicts=initrd-switch-root.target
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/run/cos/cos-layout.env
EnvironmentFile=-/run/elemental/mount-layout.env
ExecStart=/usr/bin/elemental mount --debug

[Install]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ After=sysroot.mount
Requires=sysroot.mount
After=oem.mount
Wants=oem.mount
Before=initrd-fs.target
Before=initrd-root-fs.target
Conflicts=initrd-switch-root.target

[Service]
Expand Down

0 comments on commit b33f303

Please sign in to comment.