Allow setting root to RW (#53)

This patch allows setting the root mount as RW indicated by setting
rd.cos.debugrw in the cmdline

Signed-off-by: Itxaka <itxaka.garcia@spectrocloud.com>
This commit is contained in:
Itxaka 2023-02-17 09:54:23 +01:00 committed by GitHub
parent 794d658f5e
commit 88df028e6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 43 deletions

View File

@ -43,34 +43,26 @@ Sends a generic event payload with the configuration found in the scanned direct
v := version.Get() v := version.Get()
log.Logger.Info().Str("commit", v.GitCommit).Str("compiled with", v.GoVersion).Str("version", v.Version).Msg("Immucore") log.Logger.Info().Str("commit", v.GitCommit).Str("compiled with", v.GoVersion).Str("version", v.Version).Msg("Immucore")
cmdline, _ := os.ReadFile("/proc/cmdline")
log.Logger.Debug().Msg(string(cmdline))
g := herd.DAG(herd.EnableInit) g := herd.DAG(herd.EnableInit)
// You can pass rd.cos.disable in the cmdline to disable the whole immutable stuff // Get targets and state
cosDisable := len(utils.ReadCMDLineArg("rd.cos.disable")) > 0 targetLabel, targetDevice := utils.GetTarget(c.Bool("dry-run"))
img := utils.ReadCMDLineArg("cos-img/filename=")
if len(img) == 0 {
// If we boot from LIVE media or are using dry-run, we use a fake img as we still want to do things
if c.Bool("dry-run") || cosDisable {
img = []string{"fake"}
} else {
log.Logger.Fatal().Msg("Could not get the image name from cmdline (i.e. cos-img/filename=/cOS/active.img)")
}
}
log.Debug().Strs("TargetImage", img).Msg("Target image")
s := &mount.State{ s := &mount.State{
Logger: log.Logger, Logger: log.Logger,
Rootdir: utils.GetRootDir(), Rootdir: utils.GetRootDir(),
MountRoot: true, TargetLabel: targetDevice,
TargetLabel: utils.BootStateToLabel(), TargetImage: targetLabel,
TargetImage: img[0], RootMountMode: utils.RootRW(),
} }
if cosDisable { if utils.DisableImmucore() {
log.Logger.Info().Msg("Stanza rd.cos.disable on the cmdline.") log.Logger.Info().Msg("Stanza rd.cos.disable on the cmdline or booting from CDROM/Netboot/recovery. Disabling immucore.")
err = s.RegisterLiveMedia(g) err = s.RegisterLiveMedia(g)
} else { } else {
log.Logger.Info().Msg("Booting on active/passive.")
err = s.RegisterNormalBoot(g) err = s.RegisterNormalBoot(g)
} }
@ -81,6 +73,7 @@ Sends a generic event payload with the configuration found in the scanned direct
log.Info().Msg(s.WriteDAG(g)) log.Info().Msg(s.WriteDAG(g))
// Once we print the dag we can exit already
if c.Bool("dry-run") { if c.Bool("dry-run") {
return nil return nil
} }

View File

@ -3,6 +3,7 @@ package utils
import ( import (
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/kairos-io/kairos/sdk/state" "github.com/kairos-io/kairos/sdk/state"
"github.com/rs/zerolog/log"
"os" "os"
"strings" "strings"
) )
@ -18,8 +19,6 @@ func BootStateToLabel() string {
return "COS_ACTIVE" return "COS_ACTIVE"
case "passive_boot": case "passive_boot":
return "COS_PASSIVE" return "COS_PASSIVE"
case "recovery_boot":
return "COS_SYSTEM"
default: default:
return "" return ""
} }
@ -108,3 +107,44 @@ func CleanupSlice(slice []string) []string {
} }
return cleanSlice return cleanSlice
} }
// GetTarget gets the target image and device to mount in /sysroot
func GetTarget(dryRun bool) (string, string) {
var img, label string
label = BootStateToLabel()
// If dry run, or we are disabled return whatever values, we won't go much further
if dryRun || DisableImmucore() {
return "fake", label
}
img = ReadCMDLineArg("cos-img/filename=")[0]
// If no image just panic here, we cannot longer continue
if img == "" {
log.Logger.Fatal().Msg("Could not get the image name from cmdline (i.e. cos-img/filename=/cOS/active.img)")
}
log.Debug().Str("what", img).Msg("Target device")
log.Debug().Str("what", label).Msg("Target label")
return img, label
}
// DisableImmucore identifies if we need to be disabled
// We disable if we boot from CD, netboot, recovery or have the rd.cos.disable stanza in cmdline
func DisableImmucore() bool {
cmdline, _ := os.ReadFile("/proc/cmdline")
cmdlineS := string(cmdline)
return strings.Contains(cmdlineS, "live:LABEL") || strings.Contains(cmdlineS, "live:CDLABEL") || strings.Contains(cmdlineS, "netboot") || strings.Contains(cmdlineS, "rd.cos.disable")
}
// RootRW tells us if the mode to mount root
func RootRW() string {
if len(ReadCMDLineArg("rd.cos.debugrw")) > 0 {
log.Logger.Warn().Msg("Mounting root as RW")
return "rw"
}
return "ro"
}

View File

@ -33,22 +33,16 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
if err != nil { if err != nil {
s.Logger.Debug().Err(err).Msg("runtime") s.Logger.Debug().Err(err).Msg("runtime")
} }
stateName := runtime.State.Name
stateFs := runtime.State.Type
// Recovery is a different partition
if internalUtils.IsRecovery() {
stateName = runtime.Recovery.Name
stateFs = runtime.Recovery.Type
}
// 1 - mount the state partition to find the images (active/passive/recovery) // 1 - mount the state partition to find the images (active/passive/recovery)
err = g.Add(cnst.OpMountState, err = g.Add(cnst.OpMountState,
herd.WithCallback( herd.WithCallback(
s.MountOP( s.MountOP(
stateName, runtime.State.Name,
s.path("/run/initramfs/cos-state"), s.path("/run/initramfs/cos-state"),
stateFs, runtime.State.Type,
[]string{ []string{
"ro", // or rw s.RootMountMode,
}, 60*time.Second), }, 60*time.Second),
), ),
) )
@ -74,8 +68,9 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
// On some systems the COS_ACTIVE/PASSIVE label is automatically shown as soon as we mount the device // On some systems the COS_ACTIVE/PASSIVE label is automatically shown as soon as we mount the device
// But on other it seems like it won't trigger which causes the sysroot to not be mounted as we cant find // But on other it seems like it won't trigger which causes the sysroot to not be mounted as we cant find
// the block device by the target label. Make sure we run this after mounting so we refresh the devices. // the block device by the target label. Make sure we run this after mounting so we refresh the devices.
sh, _ := utils.SH("udevadm trigger --settle") sh, _ := utils.SH("udevadm trigger")
s.Logger.Debug().Str("output", sh).Msg("udevadm trigger") s.Logger.Debug().Str("output", sh).Msg("udevadm trigger")
log.Logger.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("TargetLabel", s.TargetLabel).Msg("mount done")
return err return err
}, },
)) ))
@ -93,7 +88,7 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
s.Rootdir, s.Rootdir,
"ext4", // are images always ext2? "ext4", // are images always ext2?
[]string{ []string{
"ro", // or rw s.RootMountMode,
"suid", "suid",
"dev", "dev",
"exec", "exec",

View File

@ -19,19 +19,19 @@ import (
) )
type State struct { type State struct {
Logger zerolog.Logger Logger zerolog.Logger
Rootdir string // e.g. /sysroot inside initrd with pivot, / with nopivot Rootdir string // where to mount the root partition e.g. /sysroot inside initrd with pivot, / with nopivot
TargetImage string // e.g. /cOS/active.img TargetImage string // image from the state partition to mount as loop device e.g. /cOS/active.img
TargetLabel string // e.g. COS_ACTIVE TargetLabel string // e.g. COS_ACTIVE
RootMountMode string // How to mount the root partition e.g. ro or rw
// /run/cos-layout.env (different!) // /run/cos-layout.env (different!)
OverlayDirs []string // e.g. /var OverlayDirs []string // e.g. /var
BindMounts []string // e.g. /etc/kubernetes BindMounts []string // e.g. /etc/kubernetes
CustomMounts map[string]string // e.g. diskid : mountpoint CustomMounts map[string]string // e.g. diskid : mountpoint
StateDir string // e.g. "/usr/local/.state" StateDir string // e.g. "/usr/local/.state"
MountRoot bool // e.g. if true, it tries to find the image to loopback mount fstabs []*fstab.Mount
fstabs []*fstab.Mount
} }
func (s *State) path(p ...string) string { func (s *State) path(p ...string) string {

View File

@ -28,7 +28,6 @@ var _ = Describe("mounting immutable setup", func() {
Rootdir: "/", Rootdir: "/",
TargetImage: "/cOS/myimage.img", TargetImage: "/cOS/myimage.img",
TargetLabel: "COS_LABEL", TargetLabel: "COS_LABEL",
MountRoot: true,
} }
err := s.RegisterNormalBoot(g) err := s.RegisterNormalBoot(g)
@ -40,7 +39,7 @@ var _ = Describe("mounting immutable setup", func() {
}) })
It("generates normal dag with extra dirs", func() { It("generates normal dag with extra dirs", func() {
s := &mount.State{Rootdir: "/", MountRoot: true, s := &mount.State{Rootdir: "/",
OverlayDirs: []string{"/etc"}, OverlayDirs: []string{"/etc"},
BindMounts: []string{"/etc/kubernetes"}, BindMounts: []string{"/etc/kubernetes"},
CustomMounts: map[string]string{"COS_PERSISTENT": "/usr/local"}} CustomMounts: map[string]string{"COS_PERSISTENT": "/usr/local"}}