Revert "Uki support" (#66

This reverts commit 985b8c9401.
This commit is contained in:
Itxaka
2023-02-28 19:46:15 +01:00
committed by GitHub
parent 4cbff2d8d4
commit 3a52112b91
15 changed files with 127 additions and 372 deletions

4
go.mod
View File

@@ -9,13 +9,11 @@ require (
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/kairos-io/kairos v1.5.0 github.com/kairos-io/kairos v1.5.0
github.com/moby/sys/mountinfo v0.6.2 github.com/moby/sys/mountinfo v0.6.2
github.com/mudler/go-kdetect v0.0.0-20210802130128-dd92e121bed8
github.com/onsi/ginkgo/v2 v2.8.3 github.com/onsi/ginkgo/v2 v2.8.3
github.com/onsi/gomega v1.27.1 github.com/onsi/gomega v1.27.1
github.com/rs/zerolog v1.29.0 github.com/rs/zerolog v1.29.0
github.com/spectrocloud-labs/herd v0.4.2 github.com/spectrocloud-labs/herd v0.4.2
github.com/urfave/cli/v2 v2.24.4 github.com/urfave/cli/v2 v2.24.4
golang.org/x/sys v0.5.0
) )
require ( require (
@@ -51,7 +49,6 @@ require (
github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pilebones/go-udev v0.0.0-20210126000448-a3c2a7a4afb7 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pterm/pterm v0.12.54 // indirect github.com/pterm/pterm v0.12.54 // indirect
github.com/qeesung/image2ascii v1.0.1 // indirect github.com/qeesung/image2ascii v1.0.1 // indirect
@@ -65,6 +62,7 @@ require (
go.opencensus.io v0.23.0 // indirect go.opencensus.io v0.23.0 // indirect
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 // indirect golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 // indirect
golang.org/x/net v0.7.0 // indirect golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect golang.org/x/text v0.7.0 // indirect
golang.org/x/tools v0.6.0 // indirect golang.org/x/tools v0.6.0 // indirect

4
go.sum
View File

@@ -539,8 +539,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/mudler/go-kdetect v0.0.0-20210802130128-dd92e121bed8 h1:+g0budy5fEFMX5+ChzEhXbb7YnNWNveQgHF/iQ/UXmE=
github.com/mudler/go-kdetect v0.0.0-20210802130128-dd92e121bed8/go.mod h1:826dAJvIa3X5kfBoxSupdQbIFO4egt+hoUiw4BfPKdI=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -600,8 +598,6 @@ github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xA
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pilebones/go-udev v0.0.0-20210126000448-a3c2a7a4afb7 h1:1If5vu3Qy1ZL3NshlsrSQMsdRhujenaVFbHcFM9XQUk=
github.com/pilebones/go-udev v0.0.0-20210126000448-a3c2a7a4afb7/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

View File

@@ -10,22 +10,22 @@ func DefaultRWPaths() []string {
var ErrAlreadyMounted = errors.New("already mounted") var ErrAlreadyMounted = errors.New("already mounted")
const ( const (
OpCustomMounts = "custom-mount" OpCustomMounts = "custom-mount"
OpDiscoverState = "discover-state" OpDiscoverState = "discover-state"
OpMountState = "mount-state" OpMountState = "mount-state"
OpMountBind = "mount-bind" OpMountBind = "mount-bind"
OpMountRoot = "mount-root"
OpOverlayMount = "overlay-mount" OpMountRoot = "mount-root"
OpWriteFstab = "write-fstab" OpOverlayMount = "overlay-mount"
OpMountBaseOverlay = "mount-base-overlay" OpWriteFstab = "write-fstab"
OpMountOEM = "mount-oem" OpMountBaseOverlay = "mount-base-overlay"
OpRootfsHook = "rootfs-hook" OpMountOEM = "mount-oem"
OpInitramfsHook = "initramfs-hook"
OpLoadConfig = "load-config" OpRootfsHook = "rootfs-hook"
OpMountTmpfs = "mount-tmpfs" OpLoadConfig = "load-config"
OpRemountRootRO = "remount-ro" OpMountTmpfs = "mount-tmpfs"
OpUkiInit = "uki-init"
OpSentinel = "create-sentinel" OpSentinel = "create-sentinel"
OpUkiUdev = "uki-udev"
PersistentStateTarget = "/usr/local/.state" PersistentStateTarget = "/usr/local/.state"
) )

View File

@@ -3,8 +3,8 @@ 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"
"os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
) )
@@ -32,7 +32,7 @@ func BootStateToLabelDevice() string {
func GetRootDir() string { func GetRootDir() string {
cmdline, _ := os.ReadFile("/proc/cmdline") cmdline, _ := os.ReadFile("/proc/cmdline")
switch { switch {
case strings.Contains(string(cmdline), "rd.immucore.uki"): case strings.Contains(string(cmdline), "IMMUCORE_NOPIVOT"):
return "/" return "/"
default: default:
// Default is sysroot for normal no-pivot boot // Default is sysroot for normal no-pivot boot
@@ -99,7 +99,7 @@ func CleanupSlice(slice []string) []string {
// GetTarget gets the target image and device to mount in /sysroot // GetTarget gets the target image and device to mount in /sysroot
func GetTarget(dryRun bool) (string, string) { func GetTarget(dryRun bool) (string, string) {
var label string var img, label string
label = BootStateToLabelDevice() label = BootStateToLabelDevice()
@@ -108,20 +108,16 @@ func GetTarget(dryRun bool) (string, string) {
return "fake", label return "fake", label
} }
imgs := ReadCMDLineArg("cos-img/filename=") img = ReadCMDLineArg("cos-img/filename=")[0]
// If no image just panic here, we cannot longer continue // If no image just panic here, we cannot longer continue
if len(imgs) == 0 { if img == "" {
if IsUKI() { log.Logger.Fatal().Msg("Could not get the image name from cmdline (i.e. cos-img/filename=/cOS/active.img)")
imgs = []string{""}
} else {
Log.Fatal().Msg("could not get the image name from cmdline (i.e. cos-img/filename=/cOS/active.img)")
}
} }
Log.Debug().Str("what", imgs[0]).Msg("Target device") log.Debug().Str("what", img).Msg("Target device")
Log.Debug().Str("what", label).Msg("Target label") log.Debug().Str("what", label).Msg("Target label")
return imgs[0], label return img, label
} }
// DisableImmucore identifies if we need to be disabled // DisableImmucore identifies if we need to be disabled
@@ -136,7 +132,7 @@ func DisableImmucore() bool {
// RootRW tells us if the mode to mount root // RootRW tells us if the mode to mount root
func RootRW() string { func RootRW() string {
if len(ReadCMDLineArg("rd.cos.debugrw")) > 0 { if len(ReadCMDLineArg("rd.cos.debugrw")) > 0 {
Log.Warn().Msg("Mounting root as RW") log.Logger.Warn().Msg("Mounting root as RW")
return "rw" return "rw"
} }
return "ro" return "ro"
@@ -156,24 +152,6 @@ func GetState() string {
case state.Recovery: case state.Recovery:
label = filepath.Join("/dev/disk/by-label/", runtime.Recovery.Label) label = filepath.Join("/dev/disk/by-label/", runtime.Recovery.Label)
} }
Log.Debug().Str("what", label).Msg("Get state label") log.Logger.Debug().Str("what", label).Msg("Get state label")
return label return label
} }
func IsUKI() bool {
if len(ReadCMDLineArg("rd.immucore.uki")) > 0 {
return true
}
return false
}
// CommandWithPath runs a command adding the usual PATH to environment
// Useful under UKI as there is nothing setting the PATH
func CommandWithPath(c string) (string, error) {
cmd := exec.Command("/bin/sh", "-c", c)
cmd.Env = os.Environ()
// TODO: extract PATH from env and append to existing instead of overwriting
cmd.Env = append(cmd.Env, "PATH=/usr/bin:/usr/sbin")
o, err := cmd.CombinedOutput()
return string(o), err
}

View File

@@ -1,47 +0,0 @@
package utils
import (
"fmt"
"github.com/rs/zerolog"
"golang.org/x/sys/unix"
"io"
"os"
)
var Log zerolog.Logger
func SetLogger() {
var loggers []io.Writer
devKmsg, err := os.OpenFile("/dev/kmsg", unix.O_WRONLY, 0o600)
if err == nil {
err := os.WriteFile("/proc/sys/kernel/printk_ratelimit", []byte("100"), os.ModeType)
if err != nil {
fmt.Println(err)
}
err = os.WriteFile("/proc/sys/kernel/printk_ratelimit_burst", []byte("1000"), os.ModeType)
if err != nil {
fmt.Println(err)
}
loggers = append(loggers, zerolog.ConsoleWriter{Out: devKmsg})
}
logFile, err := os.Create("/run/immucore.log")
if err == nil {
loggers = append(loggers, zerolog.ConsoleWriter{Out: logFile})
}
// No loggers? Then stdout ¯\_(ツ)_/¯
if len(loggers) == 0 {
loggers = append(loggers, zerolog.ConsoleWriter{Out: os.Stdout})
}
multi := zerolog.MultiLevelWriter(loggers...)
Log = zerolog.New(multi).With().Logger()
Log.WithLevel(zerolog.InfoLevel)
// Set debug logger
debug := len(ReadCMDLineArg("rd.immucore.debug")) > 0
debugFromEnv := os.Getenv("IMMUCORE_DEBUG") != ""
if debug || debugFromEnv {
Log = zerolog.New(multi).With().Caller().Logger()
Log.WithLevel(zerolog.DebugLevel)
}
}

View File

@@ -4,9 +4,11 @@ import (
"fmt" "fmt"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/deniswernert/go-fstab" "github.com/deniswernert/go-fstab"
"github.com/kairos-io/kairos/pkg/utils"
"github.com/rs/zerolog/log"
"os" "os"
"os/exec"
"strings" "strings"
"syscall"
) )
// https://github.com/kairos-io/packages/blob/7c3581a8ba6371e5ce10c3a98bae54fde6a505af/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L58 // https://github.com/kairos-io/packages/blob/7c3581a8ba6371e5ce10c3a98bae54fde6a505af/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L58
@@ -52,7 +54,7 @@ func ReadCMDLineArg(arg string) []string {
// IsMounted lets us know if the given device is currently mounted // IsMounted lets us know if the given device is currently mounted
func IsMounted(dev string) bool { func IsMounted(dev string) bool {
_, err := CommandWithPath(fmt.Sprintf("findmnt %s", dev)) _, err := utils.SH(fmt.Sprintf("findmnt %s", dev))
return err == nil return err == nil
} }
@@ -60,19 +62,18 @@ func IsMounted(dev string) bool {
// Does NOT need to be mounted // Does NOT need to be mounted
// Needs full path so either /dev/sda1 or /dev/disk/by-{label,uuid}/{label,uuid} // Needs full path so either /dev/sda1 or /dev/disk/by-{label,uuid}/{label,uuid}
func DiskFSType(s string) string { func DiskFSType(s string) string {
out, e := CommandWithPath(fmt.Sprintf("blkid %s -s TYPE -o value", s)) out, e := utils.SH(fmt.Sprintf("blkid %s -s TYPE -o value", s))
if e != nil { if e != nil {
Log.Err(e).Msg("blkid") log.Logger.Err(e).Msg("blkid")
} }
out = strings.Trim(strings.Trim(out, " "), "\n") out = strings.Trim(strings.Trim(out, " "), "\n")
Log.Debug().Str("what", s).Str("type", out).Msg("Partition FS type") log.Logger.Debug().Str("what", s).Str("type", out).Msg("Partition FS type")
return out return out
} }
// SyncState will rsync source into destination. Useful for Bind mounts. // SyncState will rsync source into destination. Useful for Bind mounts.
func SyncState(src, dst string) error { func SyncState(src, dst string) error {
_, err := CommandWithPath(fmt.Sprintf("rsync -aqAX %s %s", src, dst)) return exec.Command("rsync", "-aqAX", src, dst).Run()
return err
} }
// AppendSlash it's in the name. Appends a slash. // AppendSlash it's in the name. Appends a slash.
@@ -112,9 +113,6 @@ func MountToFstab(m mount.Mount) *fstab.Mount {
// Special care for the root (/sysroot) path as we can't just simple remove that path and call it a day // Special care for the root (/sysroot) path as we can't just simple remove that path and call it a day
// as that will return an empty mountpoint which will break fstab mounting // as that will return an empty mountpoint which will break fstab mounting
func CleanSysrootForFstab(path string) string { func CleanSysrootForFstab(path string) string {
if IsUKI() {
return path
}
cleaned := strings.ReplaceAll(path, "/sysroot", "") cleaned := strings.ReplaceAll(path, "/sysroot", "")
if cleaned == "" { if cleaned == "" {
cleaned = "/" cleaned = "/"
@@ -163,34 +161,11 @@ func Fsck(device string) error {
args = append(args, "-n") args = append(args, "-n")
} }
cmd := strings.Join(args, " ") cmd := strings.Join(args, " ")
Log.Debug().Str("cmd", cmd).Msg("fsck command") log.Logger.Debug().Str("cmd", cmd).Msg("fsck command")
out, e := CommandWithPath(cmd) out, e := utils.SH(cmd)
Log.Debug().Str("output", out).Msg("fsck output") log.Logger.Debug().Str("output", out).Msg("fsck output")
if e != nil { if e != nil {
Log.Warn().Str("error", e.Error()).Str("what", device).Msg("fsck") log.Logger.Warn().Str("error", e.Error()).Str("what", device).Msg("fsck")
} }
return e return e
} }
// MinimalMounts will set the minimal mounts needed for immucore
// For now only proc is needed to read the cmdline fully in uki mode
// in normal modes this should already be done by the initramfs process, so we can ignore errors
// Just mount dev, tmp and sys just in case
func MinimalMounts() {
type m struct {
source string
target string
t string
}
toMount := []m{
{"dev", "/dev", "devtmpfs"},
{"proc", "/proc", "proc"},
{"sys", "/sys", "sysfs"},
{"tmp", "/tmp", "tmpfs"},
{"run", "/run", "tmpfs"},
}
for _, mnt := range toMount {
_ = os.MkdirAll(mnt.target, 0755)
_ = syscall.Mount(mnt.source, mnt.target, mnt.t, 0, "")
}
}

View File

@@ -5,7 +5,7 @@ import "runtime"
var ( var (
version = "v0.0.1" version = "v0.0.1"
// gitCommit is the git sha1 + dirty if build from a dirty git // gitCommit is the git sha1 + dirty if build from a dirty git
gitCommit = "none" gitCommit = ""
) )
func GetVersion() string { func GetVersion() string {

44
main.go
View File

@@ -6,6 +6,8 @@ import (
"github.com/kairos-io/immucore/internal/utils" "github.com/kairos-io/immucore/internal/utils"
"github.com/kairos-io/immucore/internal/version" "github.com/kairos-io/immucore/internal/version"
"github.com/kairos-io/immucore/pkg/mount" "github.com/kairos-io/immucore/pkg/mount"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spectrocloud-labs/herd" "github.com/spectrocloud-labs/herd"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"os" "os"
@@ -18,23 +20,27 @@ func main() {
app.Authors = []*cli.Author{{Name: "Kairos authors"}} app.Authors = []*cli.Author{{Name: "Kairos authors"}}
app.Copyright = "kairos authors" app.Copyright = "kairos authors"
app.Action = func(c *cli.Context) (err error) { app.Action = func(c *cli.Context) (err error) {
var targetDevice, targetImage string debug := len(utils.ReadCMDLineArg("rd.immucore.debug")) > 0
var state *mount.State log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
zerolog.SetGlobalLevel(zerolog.InfoLevel)
utils.MinimalMounts() debugFromEnv := os.Getenv("IMMUCORE_DEBUG") != ""
utils.SetLogger() if debug || debugFromEnv {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
v := version.Get() v := version.Get()
utils.Log.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") cmdline, _ := os.ReadFile("/proc/cmdline")
utils.Log.Debug().Str("content", string(cmdline)).Msg("cmdline") log.Logger.Debug().Msg(string(cmdline))
g := herd.DAG(herd.EnableInit) g := herd.DAG(herd.EnableInit)
// Get targets and state // Get targets and state
targetImage, targetDevice = utils.GetTarget(c.Bool("dry-run")) targetImage, targetDevice := utils.GetTarget(c.Bool("dry-run"))
state = &mount.State{ s := &mount.State{
Logger: log.Logger,
Rootdir: utils.GetRootDir(), Rootdir: utils.GetRootDir(),
TargetDevice: targetDevice, TargetDevice: targetDevice,
TargetImage: targetImage, TargetImage: targetImage,
@@ -42,21 +48,19 @@ func main() {
} }
if utils.DisableImmucore() { if utils.DisableImmucore() {
utils.Log.Info().Msg("Stanza rd.cos.disable on the cmdline or booting from CDROM/Netboot/Squash recovery. Disabling immucore.") log.Logger.Info().Msg("Stanza rd.cos.disable on the cmdline or booting from CDROM/Netboot/Squash recovery. Disabling immucore.")
err = state.RegisterLiveMedia(g) err = s.RegisterLiveMedia(g)
} else if utils.IsUKI() {
utils.Log.Info().Msg("UKI booting!")
err = state.RegisterUKI(g)
} else { } else {
utils.Log.Info().Msg("Booting on active/passive/recovery.") log.Logger.Info().Msg("Booting on active/passive/recovery.")
err = state.RegisterNormalBoot(g) err = s.RegisterNormalBoot(g)
} }
if err != nil { if err != nil {
s.Logger.Err(err)
return err return err
} }
utils.Log.Info().Msg(state.WriteDAG(g)) log.Info().Msg(s.WriteDAG(g))
// Once we print the dag we can exit already // Once we print the dag we can exit already
if c.Bool("dry-run") { if c.Bool("dry-run") {
@@ -64,7 +68,7 @@ func main() {
} }
err = g.Run(context.Background()) err = g.Run(context.Background())
utils.Log.Info().Msg(state.WriteDAG(g)) log.Info().Msg(s.WriteDAG(g))
return err return err
} }
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
@@ -77,8 +81,10 @@ func main() {
Name: "version", Name: "version",
Usage: "version", Usage: "version",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
zerolog.SetGlobalLevel(zerolog.InfoLevel)
v := version.Get() v := version.Get()
utils.Log.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")
return nil return nil
}, },
}, },

View File

@@ -31,7 +31,7 @@ func (s *State) RegisterNormalBoot(g *herd.Graph) error {
// Populate state bind mounts, overlay mounts, custom-mounts from /run/cos/cos-layout.env // Populate state bind mounts, overlay mounts, custom-mounts from /run/cos/cos-layout.env
// Requires stage rootfs to have run, which usually creates the cos-layout.env file // Requires stage rootfs to have run, which usually creates the cos-layout.env file
s.LogIfError(s.LoadEnvLayoutDagStep(g, cnst.OpRootfsHook), "loading cos-layout.env") s.LogIfError(s.LoadEnvLayoutDagStep(g), "loading cos-layout.env")
// Mount base overlay under /run/overlay // Mount base overlay under /run/overlay
s.LogIfError(s.MountBaseOverlayDagStep(g), "base overlay mount") s.LogIfError(s.MountBaseOverlayDagStep(g), "base overlay mount")

View File

@@ -9,13 +9,12 @@ import (
internalUtils "github.com/kairos-io/immucore/internal/utils" internalUtils "github.com/kairos-io/immucore/internal/utils"
"github.com/kairos-io/kairos/pkg/utils" "github.com/kairos-io/kairos/pkg/utils"
"github.com/kairos-io/kairos/sdk/state" "github.com/kairos-io/kairos/sdk/state"
"github.com/mudler/go-kdetect" "github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spectrocloud-labs/herd" "github.com/spectrocloud-labs/herd"
"golang.org/x/sys/unix"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall"
"time" "time"
) )
@@ -44,7 +43,7 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
), ),
) )
if err != nil { if err != nil {
internalUtils.Log.Err(err).Send() s.Logger.Err(err).Send()
} }
// 2 - mount the image as a loop device // 2 - mount the image as a loop device
@@ -54,7 +53,7 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
func(ctx context.Context) error { func(ctx context.Context) error {
// Check if loop device is mounted already // Check if loop device is mounted already
if internalUtils.IsMounted(s.TargetDevice) { if internalUtils.IsMounted(s.TargetDevice) {
internalUtils.Log.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("TargetDevice", s.TargetDevice).Msg("Not mounting loop, already mounted") log.Logger.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("TargetDevice", s.TargetDevice).Msg("Not mounting loop, already mounted")
return nil return nil
} }
_ = internalUtils.Fsck(s.path("/run/initramfs/cos-state", s.TargetImage)) _ = internalUtils.Fsck(s.path("/run/initramfs/cos-state", s.TargetImage))
@@ -66,13 +65,13 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
// 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") sh, _ := utils.SH("udevadm trigger")
internalUtils.Log.Debug().Str("output", sh).Msg("udevadm trigger") s.Logger.Debug().Str("output", sh).Msg("udevadm trigger")
internalUtils.Log.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("TargetDevice", s.TargetDevice).Msg("mount done") log.Logger.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("TargetDevice", s.TargetDevice).Msg("mount done")
return err return err
}, },
)) ))
if err != nil { if err != nil {
internalUtils.Log.Err(err).Send() s.Logger.Err(err).Send()
} }
// 3 - Mount the labels as Rootdir // 3 - Mount the labels as Rootdir
@@ -95,7 +94,7 @@ func (s *State) MountRootDagStep(g *herd.Graph) error {
), ),
) )
if err != nil { if err != nil {
internalUtils.Log.Err(err).Send() s.Logger.Err(err).Send()
} }
return err return err
} }
@@ -105,23 +104,19 @@ func (s *State) RootfsStageDagStep(g *herd.Graph, deps ...string) error {
return g.Add(cnst.OpRootfsHook, herd.WithDeps(deps...), herd.WithCallback(s.RunStageOp("rootfs"))) return g.Add(cnst.OpRootfsHook, herd.WithDeps(deps...), herd.WithCallback(s.RunStageOp("rootfs")))
} }
// InitramfsStageDagStep will add the rootfs stage.
func (s *State) InitramfsStageDagStep(g *herd.Graph, deps ...string) error {
return g.Add(cnst.OpInitramfsHook, herd.WithDeps(deps...), herd.WeakDeps, herd.WithCallback(s.RunStageOp("initramfs")))
}
// LoadEnvLayoutDagStep will add the stage to load from cos-layout.env and fill the proper CustomMounts, OverlayDirs and BindMounts // LoadEnvLayoutDagStep will add the stage to load from cos-layout.env and fill the proper CustomMounts, OverlayDirs and BindMounts
func (s *State) LoadEnvLayoutDagStep(g *herd.Graph, deps ...string) error { func (s *State) LoadEnvLayoutDagStep(g *herd.Graph) error {
return g.Add(cnst.OpLoadConfig, return g.Add(cnst.OpLoadConfig,
herd.WithDeps(deps...), herd.WithDeps(cnst.OpRootfsHook),
herd.WithCallback(func(ctx context.Context) error { herd.WithCallback(func(ctx context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
if s.CustomMounts == nil { if s.CustomMounts == nil {
s.CustomMounts = map[string]string{} s.CustomMounts = map[string]string{}
} }
env, err := internalUtils.ReadEnv("/run/cos/cos-layout.env") env, err := internalUtils.ReadEnv("/run/cos/cos-layout.env")
if err != nil { if err != nil {
internalUtils.Log.Err(err).Msg("Reading env") log.Logger.Err(err).Msg("Reading env")
return err return err
} }
// populate from env here // populate from env here
@@ -167,7 +162,7 @@ func (s *State) LoadEnvLayoutDagStep(g *herd.Graph, deps ...string) error {
func (s *State) MountOemDagStep(g *herd.Graph, deps ...string) error { func (s *State) MountOemDagStep(g *herd.Graph, deps ...string) error {
runtime, err := state.NewRuntime() runtime, err := state.NewRuntime()
if err != nil { if err != nil {
internalUtils.Log.Debug().Err(err).Msg("runtime") s.Logger.Debug().Err(err).Msg("runtime")
} }
return g.Add(cnst.OpMountOEM, return g.Add(cnst.OpMountOEM,
herd.WithDeps(deps...), herd.WithDeps(deps...),
@@ -225,13 +220,13 @@ func (s *State) MountCustomOverlayDagStep(g *herd.Graph) error {
herd.WithCallback( herd.WithCallback(
func(ctx context.Context) error { func(ctx context.Context) error {
var multierr *multierror.Error var multierr *multierror.Error
internalUtils.Log.Debug().Strs("dirs", s.OverlayDirs).Msg("Mounting overlays") s.Logger.Debug().Strs("dirs", s.OverlayDirs).Msg("Mounting overlays")
for _, p := range s.OverlayDirs { for _, p := range s.OverlayDirs {
op := mountWithBaseOverlay(p, s.Rootdir, "/run/overlay") op := mountWithBaseOverlay(p, s.Rootdir, "/run/overlay")
err := op.run() err := op.run()
// Append to errors only if it's not an already mounted error // Append to errors only if it's not an already mounted error
if err != nil && !errors.Is(err, cnst.ErrAlreadyMounted) { if err != nil && !errors.Is(err, cnst.ErrAlreadyMounted) {
internalUtils.Log.Err(err).Msg("overlay mount") log.Logger.Err(err).Msg("overlay mount")
multierr = multierror.Append(multierr, err) multierr = multierror.Append(multierr, err)
continue continue
} }
@@ -254,25 +249,20 @@ func (s *State) MountCustomMountsDagStep(g *herd.Graph) error {
// TODO: scan for the custom mount disk to know the underlying fs and set it proper // TODO: scan for the custom mount disk to know the underlying fs and set it proper
fstype := "ext4" fstype := "ext4"
mountOptions := []string{"ro"} mountOptions := []string{"ro"}
// TODO: Are custom mounts always rw?ro?depends? Clarify.
// Persistent needs to be RW // Persistent needs to be RW
if strings.Contains(what, "COS_PERSISTENT") { if strings.Contains(what, "COS_PERSISTENT") {
mountOptions = []string{"rw"} mountOptions = []string{"rw"}
} }
err2 := s.MountOP( err = multierror.Append(err, s.MountOP(
what, what,
s.path(where), s.path(where),
fstype, fstype,
mountOptions, mountOptions,
3*time.Second, 10*time.Second,
)(ctx) )(ctx))
// If its COS_OEM and it fails then we can safely ignore, as it's not mandatory to have COS_OEM
if err2 != nil && !strings.Contains(what, "COS_OEM") {
err = multierror.Append(err, err2)
}
} }
internalUtils.Log.Err(err.ErrorOrNil()).Send() s.Logger.Err(err.ErrorOrNil()).Send()
return err.ErrorOrNil() return err.ErrorOrNil()
}), }),
@@ -287,7 +277,7 @@ func (s *State) MountCustomBindsDagStep(g *herd.Graph) error {
herd.WithCallback( herd.WithCallback(
func(ctx context.Context) error { func(ctx context.Context) error {
var err *multierror.Error var err *multierror.Error
internalUtils.Log.Debug().Strs("mounts", s.BindMounts).Msg("Mounting binds") s.Logger.Debug().Strs("mounts", s.BindMounts).Msg("Mounting binds")
for _, p := range s.BindMounts { for _, p := range s.BindMounts {
op := mountBind(p, s.Rootdir, s.StateDir) op := mountBind(p, s.Rootdir, s.StateDir)
@@ -298,11 +288,11 @@ func (s *State) MountCustomBindsDagStep(g *herd.Graph) error {
} }
// Append to errors only if it's not an already mounted error // Append to errors only if it's not an already mounted error
if err2 != nil && !errors.Is(err2, cnst.ErrAlreadyMounted) { if err2 != nil && !errors.Is(err2, cnst.ErrAlreadyMounted) {
internalUtils.Log.Err(err2).Send() log.Logger.Err(err2).Send()
err = multierror.Append(err, err2) err = multierror.Append(err, err2)
} }
} }
internalUtils.Log.Err(err.ErrorOrNil()).Send() log.Logger.Err(err.ErrorOrNil()).Send()
return err.ErrorOrNil() return err.ErrorOrNil()
}, },
), ),
@@ -355,110 +345,11 @@ func (s *State) WriteSentinelDagStep(g *herd.Graph) error {
sentinel = "live_mode" sentinel = "live_mode"
} }
internalUtils.Log.Info().Str("to", sentinel).Msg("Setting sentinel file") s.Logger.Info().Str("to", sentinel).Msg("Setting sentinel file")
err = os.WriteFile(filepath.Join("/run/cos/", sentinel), []byte("1"), os.ModePerm) err = os.WriteFile(filepath.Join("/run/cos/", sentinel), []byte("1"), os.ModePerm)
if err != nil { if err != nil {
return err return err
} }
// Lets add a uki sentinel as well!
if strings.Contains(cmdlineS, "rd.immucore.uki") {
err = os.WriteFile("/run/cos/uki_mode", []byte("1"), os.ModePerm)
if err != nil {
return err
}
}
return nil return nil
})) }))
} }
// UKIBootInitDagStep tries to launch /sbin/init in root and pass over the system
// booting to the real init process
// Drops to emergency if not able to. Panic if it cant even launch emergency
func (s *State) UKIBootInitDagStep(g *herd.Graph, deps ...string) error {
return g.Add(cnst.OpUkiInit,
herd.WithDeps(deps...),
herd.WeakDeps,
herd.WithCallback(func(ctx context.Context) error {
// Print dag before exit, otherwise its never printed as we never exit the program
internalUtils.Log.Info().Msg(s.WriteDAG(g))
internalUtils.Log.Debug().Msg("Executing init callback!")
if err := unix.Exec("/sbin/init", []string{"/sbin/init", "--system"}, os.Environ()); err != nil {
internalUtils.Log.Err(err).Msg("running init")
// drop to emergency shell
if err := unix.Exec("/bin/bash", []string{"/bin/bash"}, os.Environ()); err != nil {
internalUtils.Log.Fatal().Msg("Could not drop to emergency shell")
}
}
return nil
}))
}
// UKIRemountRootRODagStep remount root read only
func (s *State) UKIRemountRootRODagStep(g *herd.Graph, deps ...string) error {
return g.Add(cnst.OpRemountRootRO,
herd.WithDeps(deps...),
herd.WithCallback(func(ctx context.Context) error {
return syscall.Mount("/", "/", "rootfs", syscall.MS_REMOUNT|syscall.MS_RDONLY, "")
}),
)
}
// UKIUdevDaemon launches the udevd daemon and triggers+settles in order to discover devices
// Needed if we expect to find devices by label...
func (s *State) UKIUdevDaemon(g *herd.Graph) error {
return g.Add(cnst.OpUkiUdev,
herd.WithCallback(func(ctx context.Context) error {
// Should probably figure out other udevd binaries....
var udevBin string
if _, err := os.Stat("/usr/lib/systemd/systemd-udevd"); !os.IsNotExist(err) {
udevBin = "/usr/lib/systemd/systemd-udevd"
}
cmd := fmt.Sprintf("%s --daemon", udevBin)
out, err := internalUtils.CommandWithPath(cmd)
internalUtils.Log.Debug().Str("out", out).Str("cmd", cmd).Msg("Udev daemon")
if err != nil {
internalUtils.Log.Err(err).Msg("Udev daemon")
return err
}
out, err = internalUtils.CommandWithPath("udevadm trigger")
internalUtils.Log.Debug().Str("out", out).Msg("Udev trigger")
if err != nil {
internalUtils.Log.Err(err).Msg("Udev trigger")
return err
}
out, err = internalUtils.CommandWithPath("udevadm settle")
internalUtils.Log.Debug().Str("out", out).Msg("Udev settle")
if err != nil {
internalUtils.Log.Err(err).Msg("Udev settle")
return err
}
return nil
}),
)
}
// LoadKernelModules loads kernel modules needed during uki boot to load the disks for.
// Mainly block devices and net devices
// probably others down the line
func (s *State) LoadKernelModules(g *herd.Graph) error {
return g.Add("kernel-modules",
herd.WithCallback(func(ctx context.Context) error {
drivers, err := kdetect.ProbeKernelModules("")
if err != nil {
internalUtils.Log.Err(err).Msg("Detecting needed modules")
}
internalUtils.Log.Debug().Strs("drivers", drivers).Msg("Detecting needed modules")
for _, driver := range drivers {
cmd := fmt.Sprintf("modprobe %s", driver)
out, err := internalUtils.CommandWithPath(cmd)
if err != nil {
internalUtils.Log.Err(err).Str("out", out).Msg("modprobe")
}
}
return nil
}),
)
}

View File

@@ -1,52 +0,0 @@
package mount
import (
cnst "github.com/kairos-io/immucore/internal/constants"
"github.com/spectrocloud-labs/herd"
)
// RegisterUKI registers the dag for booting from UKI
func (s *State) RegisterUKI(g *herd.Graph) error {
// Write sentinel
s.LogIfError(s.WriteSentinelDagStep(g), "sentinel")
s.LogIfError(s.LoadKernelModules(g), "kernel modules")
// Udev for devices discovery
s.LogIfError(s.UKIUdevDaemon(g), "udev")
// Run rootfs stage
s.LogIfError(s.RootfsStageDagStep(g, cnst.OpSentinel), "uki rootfs")
// Remount root RO
s.LogIfError(s.UKIRemountRootRODagStep(g, cnst.OpRootfsHook), "remount root")
// Mount base overlay under /run/overlay
s.LogIfError(s.MountBaseOverlayDagStep(g), "base overlay")
// Populate state bind mounts, overlay mounts, custom-mounts from /run/cos/cos-layout.env
// Requires stage rootfs to have run, which usually creates the cos-layout.env file
s.LogIfError(s.LoadEnvLayoutDagStep(g, cnst.OpRootfsHook), "loading cos-layout.env")
// Mount custom overlays loaded from the /run/cos/cos-layout.env file
s.LogIfError(s.MountCustomOverlayDagStep(g), "custom overlays mount")
// Mount custom mounts loaded from the /run/cos/cos-layout.env file
s.LogIfError(s.MountCustomMountsDagStep(g), "custom mounts mount")
// Mount custom binds loaded from the /run/cos/cos-layout.env file
// Depends on mount binds as that usually mounts COS_PERSISTENT
s.LogIfError(s.MountCustomBindsDagStep(g), "custom binds mount")
// run initramfs stage
s.LogIfError(s.InitramfsStageDagStep(g, cnst.OpMountBind), "uki initramfs")
s.LogIfError(g.Add(cnst.OpWriteFstab,
herd.WithDeps(cnst.OpLoadConfig, cnst.OpCustomMounts, cnst.OpMountBind, cnst.OpOverlayMount),
herd.WeakDeps,
herd.WithCallback(s.WriteFstab(s.path("/etc/fstab")))), "fstab")
// Handover to /sbin/init
_ = s.UKIBootInitDagStep(g, cnst.OpRemountRootRO, cnst.OpRootfsHook, cnst.OpInitramfsHook)
return nil
}

View File

@@ -62,13 +62,14 @@ func mountBind(mountpoint, root, stateTarget string) mountOperation {
Type: "overlay", Type: "overlay",
Source: stateDir, Source: stateDir,
Options: []string{ Options: []string{
//"defaults",
"bind", "bind",
}, },
} }
internalUtils.Log.Debug().Str("mountpoint", mountpoint).Str("root", root).Str("bindMountPath", bindMountPath).Msg("BIND")
tmpFstab := internalUtils.MountToFstab(tmpMount) tmpFstab := internalUtils.MountToFstab(tmpMount)
tmpFstab.File = internalUtils.CleanSysrootForFstab(fmt.Sprintf("/%s", mountpoint)) tmpFstab.File = internalUtils.CleanSysrootForFstab(fmt.Sprintf("/%s", mountpoint))
tmpFstab.Spec = internalUtils.CleanSysrootForFstab(tmpFstab.Spec) tmpFstab.Spec = strings.ReplaceAll(tmpFstab.Spec, root, "")
return mountOperation{ return mountOperation{
MountOption: tmpMount, MountOption: tmpMount,
FstabEntry: *tmpFstab, FstabEntry: *tmpFstab,

View File

@@ -4,8 +4,10 @@ import (
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/deniswernert/go-fstab" "github.com/deniswernert/go-fstab"
"github.com/kairos-io/immucore/internal/constants" "github.com/kairos-io/immucore/internal/constants"
internalUtils "github.com/kairos-io/immucore/internal/utils"
"github.com/moby/sys/mountinfo" "github.com/moby/sys/mountinfo"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"os"
) )
type mountOperation struct { type mountOperation struct {
@@ -16,23 +18,23 @@ type mountOperation struct {
} }
func (m mountOperation) run() error { func (m mountOperation) run() error {
internalUtils.Log.With().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Logger() log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Logger()
if m.PrepareCallback != nil { if m.PrepareCallback != nil {
if err := m.PrepareCallback(); err != nil { if err := m.PrepareCallback(); err != nil {
internalUtils.Log.Err(err).Msg("executing mount callback") log.Logger.Err(err).Msg("executing mount callback")
return err return err
} }
} }
//TODO: not only check if mounted but also if the type,options and source are the same? //TODO: not only check if mounted but also if the type,options and source are the same?
mounted, err := mountinfo.Mounted(m.Target) mounted, err := mountinfo.Mounted(m.Target)
if err != nil { if err != nil {
internalUtils.Log.Err(err).Msg("checking mount status") log.Logger.Err(err).Msg("checking mount status")
return err return err
} }
if mounted { if mounted {
internalUtils.Log.Debug().Msg("Already mounted") log.Logger.Debug().Msg("Already mounted")
return constants.ErrAlreadyMounted return constants.ErrAlreadyMounted
} }
internalUtils.Log.Debug().Msg("mount ready") log.Logger.Debug().Msg("mount ready")
return mount.All([]mount.Mount{m.MountOption}, m.Target) return mount.All([]mount.Mount{m.MountOption}, m.Target)
} }

View File

@@ -12,11 +12,14 @@ import (
"github.com/deniswernert/go-fstab" "github.com/deniswernert/go-fstab"
"github.com/kairos-io/immucore/internal/constants" "github.com/kairos-io/immucore/internal/constants"
internalUtils "github.com/kairos-io/immucore/internal/utils" internalUtils "github.com/kairos-io/immucore/internal/utils"
"github.com/kairos-io/kairos/pkg/utils"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spectrocloud-labs/herd" "github.com/spectrocloud-labs/herd"
) )
type State struct { type State struct {
Logger zerolog.Logger
Rootdir string // where to mount the root partition 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 // image from the state partition to mount as loop device e.g. /cOS/active.img TargetImage string // image from the state partition to mount as loop device e.g. /cOS/active.img
TargetDevice string // e.g. /dev/disk/by-label/COS_ACTIVE TargetDevice string // e.g. /dev/disk/by-label/COS_ACTIVE
@@ -36,6 +39,7 @@ func (s *State) path(p ...string) string {
} }
func (s *State) WriteFstab(fstabFile string) func(context.Context) error { func (s *State) WriteFstab(fstabFile string) func(context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
return func(ctx context.Context) error { return func(ctx context.Context) error {
for _, fst := range s.fstabs { for _, fst := range s.fstabs {
select { select {
@@ -58,38 +62,37 @@ func (s *State) WriteFstab(fstabFile string) func(context.Context) error {
} }
// RunStageOp runs elemental run-stage stage. If its rootfs its special as it needs som symlinks // RunStageOp runs elemental run-stage stage. If its rootfs its special as it needs som symlinks
// If its uki we don't symlink as we already have everything in the sysroot
func (s *State) RunStageOp(stage string) func(context.Context) error { func (s *State) RunStageOp(stage string) func(context.Context) error {
return func(ctx context.Context) error { return func(ctx context.Context) error {
if stage == "rootfs" && !internalUtils.IsUKI() { if stage == "rootfs" {
if _, err := os.Stat("/system"); os.IsNotExist(err) { if _, err := os.Stat("/system"); os.IsNotExist(err) {
err = os.Symlink("/sysroot/system", "/system") err = os.Symlink("/sysroot/system", "/system")
if err != nil { if err != nil {
internalUtils.Log.Err(err).Msg("creating symlink") s.Logger.Err(err).Msg("creating symlink")
} }
} }
if _, err := os.Stat("/oem"); os.IsNotExist(err) { if _, err := os.Stat("/oem"); os.IsNotExist(err) {
err = os.Symlink("/sysroot/oem", "/oem") err = os.Symlink("/sysroot/oem", "/oem")
if err != nil { if err != nil {
internalUtils.Log.Err(err).Msg("creating symlink") s.Logger.Err(err).Msg("creating symlink")
} }
} }
} }
cmd := fmt.Sprintf("/usr/bin/elemental run-stage %s", stage) cmd := fmt.Sprintf("elemental run-stage %s", stage)
// If we set the level to debug, also call elemental with debug // If we set the level to debug, also call elemental with debug
if internalUtils.Log.GetLevel() == zerolog.DebugLevel { if s.Logger.GetLevel() == zerolog.DebugLevel {
cmd = fmt.Sprintf("%s --debug", cmd) cmd = fmt.Sprintf("%s --debug", cmd)
} }
output, err := internalUtils.CommandWithPath(cmd) output, err := utils.SH(cmd)
internalUtils.Log.Debug().Msg(output) s.Logger.Debug().Msg(output)
return err return err
} }
} }
// MountOP creates and executes a mount operation // MountOP creates and executes a mount operation
func (s *State) MountOP(what, where, t string, options []string, timeout time.Duration) func(context.Context) error { func (s *State) MountOP(what, where, t string, options []string, timeout time.Duration) func(context.Context) error {
internalUtils.Log.With().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Logger() log.Logger.With().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Logger()
return func(c context.Context) error { return func(c context.Context) error {
cc := time.After(timeout) cc := time.After(timeout)
@@ -98,7 +101,7 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
default: default:
err := internalUtils.CreateIfNotExists(where) err := internalUtils.CreateIfNotExists(where)
if err != nil { if err != nil {
internalUtils.Log.Err(err).Msg("Creating dir") log.Logger.Err(err).Msg("Creating dir")
continue continue
} }
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
@@ -127,18 +130,18 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
// only continue the loop if it's an error and not an already mounted error // only continue the loop if it's an error and not an already mounted error
if err != nil && !errors.Is(err, constants.ErrAlreadyMounted) { if err != nil && !errors.Is(err, constants.ErrAlreadyMounted) {
internalUtils.Log.Err(err).Send() s.Logger.Err(err).Send()
continue continue
} }
internalUtils.Log.Debug().Msg("mount done") log.Logger.Debug().Msg("mount done")
return nil return nil
case <-c.Done(): case <-c.Done():
e := fmt.Errorf("context canceled") e := fmt.Errorf("context canceled")
internalUtils.Log.Err(e).Msg("mount canceled") log.Logger.Err(e).Msg("mount canceled")
return e return e
case <-cc: case <-cc:
e := fmt.Errorf("timeout exhausted") e := fmt.Errorf("timeout exhausted")
internalUtils.Log.Err(e).Msg("Mount timeout") log.Logger.Err(e).Msg("Mount timeout")
return e return e
} }
} }
@@ -164,7 +167,7 @@ func (s *State) WriteDAG(g *herd.Graph) (out string) {
// Context can be empty // Context can be empty
func (s *State) LogIfError(e error, msgContext string) { func (s *State) LogIfError(e error, msgContext string) {
if e != nil { if e != nil {
internalUtils.Log.Err(e).Msg(msgContext) s.Logger.Err(e).Msg(msgContext)
} }
} }
@@ -173,7 +176,7 @@ func (s *State) LogIfError(e error, msgContext string) {
// Will also return the error // Will also return the error
func (s *State) LogIfErrorAndReturn(e error, msgContext string) error { func (s *State) LogIfErrorAndReturn(e error, msgContext string) error {
if e != nil { if e != nil {
internalUtils.Log.Err(e).Msg(msgContext) s.Logger.Err(e).Msg(msgContext)
} }
return e return e
} }
@@ -183,7 +186,7 @@ func (s *State) LogIfErrorAndReturn(e error, msgContext string) error {
// Will also panic // Will also panic
func (s *State) LogIfErrorAndPanic(e error, msgContext string) { func (s *State) LogIfErrorAndPanic(e error, msgContext string) {
if e != nil { if e != nil {
internalUtils.Log.Err(e).Msg(msgContext) s.Logger.Err(e).Msg(msgContext)
internalUtils.Log.Fatal().Msg(e.Error()) s.Logger.Fatal().Msg(e.Error())
} }
} }

View File

@@ -2,6 +2,9 @@ package mount_test
import ( import (
"context" "context"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"os"
"time" "time"
"github.com/kairos-io/immucore/pkg/mount" "github.com/kairos-io/immucore/pkg/mount"
@@ -21,6 +24,7 @@ var _ = Describe("mounting immutable setup", func() {
Context("simple invocation", func() { Context("simple invocation", func() {
It("generates normal dag", func() { It("generates normal dag", func() {
s := &mount.State{ s := &mount.State{
Logger: log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger(),
Rootdir: "/", Rootdir: "/",
TargetImage: "/cOS/myimage.img", TargetImage: "/cOS/myimage.img",
TargetDevice: "/dev/disk/by-label/COS_LABEL", TargetDevice: "/dev/disk/by-label/COS_LABEL",