Merge pull request #27 from kairos-io/changes_v4

This commit is contained in:
Itxaka 2023-02-08 16:50:06 +01:00 committed by GitHub
commit 7416a49e21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 75 deletions

View File

@ -28,7 +28,7 @@ install() {
# Add missing elemental binary, drop once we get yip lib inside immucore as its only needed to run the stages
inst_multiple immucore elemental
# add utils used by elemental or stages
inst_multiple partprobe sync udevadm parted mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.vfat mkfs.fat blkid e2fsck resize2fs mount umount sgdisk
inst_multiple partprobe sync udevadm parted mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.vfat mkfs.fat blkid e2fsck resize2fs mount umount sgdisk rsync
# missing mkfs.xfs xfs_growfs in image?
inst_script "${moddir}/generator.sh" "${systemdutildir}/system-generators/immucore-generator"
inst_simple "${moddir}/immucore.service" "${systemdsystemunitdir}/immucore.service"

View File

@ -30,7 +30,7 @@ Sends a generic event payload with the configuration found in the scanned direct
},
},
Action: func(c *cli.Context) (err error) {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
g := herd.DAG()
s := &mount.State{
Logger: log.Logger,
@ -64,7 +64,9 @@ Sends a generic event payload with the configuration found in the scanned direct
}
log.Print("Calling dag")
return g.Run(context.Background())
err = g.Run(context.Background())
log.Print(s.WriteDAG(g))
return err
},
},
}

View File

@ -99,44 +99,44 @@ func mountToStab(m mount.Mount) *fstab.Mount {
}
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L183
func mountBind(mountpoint, root, stateTarget string) (mountOperation, error) {
func mountBind(mountpoint, root, stateTarget string) mountOperation {
mountpoint = strings.TrimLeft(mountpoint, "/") // normalize, remove / upfront as we are going to re-use it in subdirs
rootMount := filepath.Join(root, mountpoint)
bindMountPath := strings.ReplaceAll(mountpoint, "/", "-")
stateDir := filepath.Join(root, stateTarget, fmt.Sprintf("%s.bind", bindMountPath))
if mounted, _ := mountinfo.Mounted(rootMount); !mounted {
tmpMount := mount.Mount{
Type: "overlay",
Source: stateDir,
Options: []string{
"defaults",
"bind",
},
}
tmpFstab := mountToStab(tmpMount)
tmpFstab.File = fmt.Sprintf("/%s", mountpoint)
tmpFstab.Spec = strings.ReplaceAll(tmpFstab.Spec, root, "")
return mountOperation{
MountOption: tmpMount,
FstabEntry: *tmpFstab,
Target: rootMount,
PrepareCallback: func() error {
if err := createIfNotExists(rootMount); err != nil {
return err
}
if err := createIfNotExists(stateDir); err != nil {
return err
}
return syncState(appendSlash(rootMount), appendSlash(stateDir))
},
}, nil
tmpMount := mount.Mount{
Type: "overlay",
Source: stateDir,
Options: []string{
//"defaults",
"bind",
},
}
tmpFstab := mountToStab(tmpMount)
tmpFstab.File = fmt.Sprintf("/%s", mountpoint)
tmpFstab.Spec = strings.ReplaceAll(tmpFstab.Spec, root, "")
return mountOperation{
MountOption: tmpMount,
FstabEntry: *tmpFstab,
Target: rootMount,
PrepareCallback: func() error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
if err := createIfNotExists(rootMount); err != nil {
log.Logger.Err(err).Str("what", rootMount).Msg("create if not exists")
return err
}
if err := createIfNotExists(stateDir); err != nil {
log.Logger.Err(err).Str("what", stateDir).Msg("create if not exists")
return err
}
log.Logger.Debug().Str("what", tmpMount.Source).Str("where", rootMount).Str("type", tmpMount.Type).Strs("options", tmpMount.Options).Msg("create if not exists")
return syncState(appendSlash(rootMount), appendSlash(stateDir))
},
}
return mountOperation{}, fmt.Errorf("already mounted")
}
func syncState(src, dst string) error {
@ -145,7 +145,7 @@ func syncState(src, dst string) error {
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L145
func mountWithBaseOverlay(mountpoint, root, base string) (mountOperation, error) {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
log.Debug().Str("mountpoint", mountpoint).Str("root", root).Str("base", base).Msg("mount with base overlay")
mountpoint = strings.TrimLeft(mountpoint, "/") // normalize, remove / upfront as we are going to re-use it in subdirs
rootMount := filepath.Join(root, mountpoint)
@ -160,7 +160,7 @@ func mountWithBaseOverlay(mountpoint, root, base string) (mountOperation, error)
Type: "overlay",
Source: "overlay",
Options: []string{
"defaults",
//"defaults",
fmt.Sprintf("lowerdir=%s", rootMount),
fmt.Sprintf("upperdir=%s", upperdir),
fmt.Sprintf("workdir=%s", workdir),

View File

@ -59,7 +59,7 @@ func (s *State) path(p ...string) string {
}
func (s *State) WriteFstab(fstabFile string) func(context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
return func(ctx context.Context) error {
for _, fst := range s.fstabs {
select {
@ -72,12 +72,14 @@ func (s *State) WriteFstab(fstabFile string) func(context.Context) error {
return err
}
defer f.Close()
toWrite := fmt.Sprintf("%s\n", fst.String())
s.Logger.Debug().Str("fstab", toWrite)
// As we mount on /sysroot during initramfs but the fstab file is for the real init process, we need to remove
// Any mentions to /sysroot from the fstab lines, otherwise they wont work
fstCleaned := strings.ReplaceAll(fst.String(), "/sysroot", "")
toWrite := fmt.Sprintf("%s\n", fstCleaned)
if _, err := f.WriteString(toWrite); err != nil {
return err
}
log.Logger.Debug().Str("fstabline", litter.Sdump(fst)).Str("fstabfile", fstabFile).Msg("Done fstab line")
log.Logger.Debug().Str("fstabline", fstCleaned).Str("fstabfile", fstabFile).Msg("Done fstab line")
}
}
return nil
@ -86,12 +88,15 @@ func (s *State) WriteFstab(fstabFile string) func(context.Context) error {
func (s *State) RunStageOp(stage string) func(context.Context) error {
return func(ctx context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
if stage == "rootfs" {
err := os.Symlink("/sysroot/system", "/system")
if err != nil {
s.Logger.Err(err).Msg("creating symlink")
return err
if _, err := os.Stat("/system"); os.IsNotExist(err) {
s.Logger.Debug().Str("from", "/sysroot/system").Str("to", "/system").Msg("Creating symlink")
err = os.Symlink("/sysroot/system", "/system")
if err != nil {
s.Logger.Err(err).Msg("creating symlink")
return err
}
}
}
@ -104,7 +109,7 @@ func (s *State) RunStageOp(stage string) func(context.Context) error {
}
func (s *State) MountOP(what, where, t string, options []string, timeout time.Duration) func(context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
return func(c context.Context) error {
cc := time.After(timeout)
@ -112,10 +117,10 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
select {
default:
if _, err := os.Stat(where); os.IsNotExist(err) {
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Str("options", litter.Sdump(options)).Msg("Mount point does not exist, creating")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Msg("Mount point does not exist, creating")
err = os.MkdirAll(where, os.ModeDir|os.ModePerm)
if err != nil {
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Str("options", litter.Sdump(options)).Err(err).Msg("")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Err(err).Msg("Creating dir")
continue
}
}
@ -135,20 +140,20 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
err := op.run()
if err != nil {
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Str("options", litter.Sdump(options)).Err(err).Msg("")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Err(err).Msg("mounting")
continue
}
s.fstabs = append(s.fstabs, tmpFstab)
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Str("options", litter.Sdump(options)).Msg("Mounted")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Msg("Mounted")
return nil
case <-c.Done():
e := fmt.Errorf("context canceled")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Str("options", litter.Sdump(options)).Err(e).Msg("")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Err(e).Msg("mount canceled")
return e
case <-cc:
e := fmt.Errorf("timeout exhausted")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Str("options", litter.Sdump(options)).Err(e).Msg("")
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Err(e).Msg("Mount timeout")
return e
}
}
@ -200,9 +205,6 @@ func (s *State) Register(g *herd.Graph) error {
// TODO: add hooks, fstab (might have missed some), systemd compat
// TODO: We should also set tmpfs here (not -related)
// symlink
// execute the rootfs hook
// All of this below need to run after rootfs stage runs (so the layout file is created)
// This is legacy - in UKI we don't need to found the img, this needs to run in a conditional
if s.MountRoot {
@ -212,7 +214,7 @@ func (s *State) Register(g *herd.Graph) error {
herd.WithDeps(opMountState),
herd.WithCallback(
func(ctx context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
cmd := fmt.Sprintf("losetup --show -f %s", s.path("/run/initramfs/cos-state", s.TargetImage))
log.Logger.Debug().Str("targetImage", s.TargetImage).Str("path", s.Rootdir).Str("fullcmd", cmd).Msg("Mounting image")
_, err := utils.SH(cmd)
@ -273,6 +275,7 @@ func (s *State) Register(g *herd.Graph) error {
// depending on /run/cos-layout.env
// This is building the mountRoot dependendency if it was enabled
mountRootCondition := herd.ConditionalOption(func() bool { return s.MountRoot }, herd.WithDeps(opMountRoot))
s.Logger.Debug().Bool("mountRootCondition", s.MountRoot).Msg("condition")
// TODO: this needs to be run after sysroot so we can link to /sysroot/system/oem and after /oem mounted
s.Logger.Debug().Str("what", opRootfsHook).Msg("Add operation")
@ -287,7 +290,7 @@ func (s *State) Register(g *herd.Graph) error {
err = g.Add(opLoadConfig,
herd.WithDeps(opRootfsHook),
herd.WithCallback(func(ctx context.Context) error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
if s.CustomMounts == nil {
s.CustomMounts = map[string]string{}
}
@ -302,6 +305,8 @@ func (s *State) Register(g *herd.Graph) error {
// TODO: PERSISTENT_STATE_TARGET /usr/local/.state
s.BindMounts = strings.Split(env["PERSISTENT_STATE_PATHS"], " ")
log.Logger.Debug().Strs("paths", s.BindMounts).Msg("persistent paths")
log.Logger.Debug().Str("pathsraw", env["PERSISTENT_STATE_PATHS"]).Msg("persistent paths")
s.StateDir = env["PERSISTENT_STATE_TARGET"]
if s.StateDir == "" {
@ -357,6 +362,7 @@ func (s *State) Register(g *herd.Graph) error {
}
overlayCondition := herd.ConditionalOption(func() bool { return rootFSType(s.Rootdir) != "overlay" }, herd.WithDeps(opMountBaseOverlay))
s.Logger.Debug().Bool("overlaycondition", rootFSType(s.Rootdir) != "overlay").Msg("condition")
// TODO: Add fsck
// mount overlay
s.Logger.Debug().Str("what", opOverlayMount).Msg("Add operation")
@ -391,22 +397,33 @@ func (s *State) Register(g *herd.Graph) error {
overlayCondition,
herd.WithDeps(opLoadConfig),
herd.WithCallback(func(ctx context.Context) error {
var err error
for id, mountpoint := range s.CustomMounts {
s.Logger.Debug().Msg("Start" + opCustomMounts)
var err *multierror.Error
for what, where := range s.CustomMounts {
// TODO: scan for the custom mount disk to know the underlying fs and set it proper
fstype := "auto"
mountOptions := []string{"ro"}
// Translate label to disk for COS_PERSISTENT
// Persistent needs to be RW
if strings.Contains(what, "COS_PERSISTENT") {
fstype = runtime.Persistent.Type
mountOptions = []string{"rw"}
}
s.Logger.Debug().Str("what", what).Str("where", s.path(where)).Str("type", fstype).Msg("mounting custom mounts")
err = multierror.Append(err, s.MountOP(
id,
s.path(mountpoint),
"auto",
[]string{
"ro", // or rw
},
what,
s.path(where),
fstype,
mountOptions,
10*time.Second,
)(ctx))
}
return err
s.Logger.Debug().Msg("End" + opCustomMounts)
s.Logger.Err(err).Str("error", err.Error()).Send()
return err.ErrorOrNil()
}),
)
if err != nil {
@ -423,16 +440,42 @@ func (s *State) Register(g *herd.Graph) error {
herd.WithCallback(
func(ctx context.Context) error {
var err error
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
log.Logger.Debug().Strs("binds", s.BindMounts).Msg("Mounting bind")
for _, p := range s.BindMounts {
op, err := mountBind(p, s.Rootdir, s.StateDir)
if err != nil {
return err
// TODO: Check why p can be empty, Example:
/*
3:12PM DBG Mounting bind binds=[
"/etc/systemd","/etc/modprobe.d",
"/etc/rancher","/etc/sysconfig",
"/etc/runlevels","/etc/ssh",
"/etc/ssl/certs","/etc/iscsi",
"", <----- HERE
"/etc/cni","/etc/kubernetes",
"/home","/opt","/root","/snap",
"/var/snap","/usr/libexec",
"/var/log","/var/lib/rancher",
"/var/lib/kubelet","/var/lib/snapd"
,"/var/lib/wicked","/var/lib/longhorn"
,"/var/lib/cni","/usr/share/pki/trust"
,"/usr/share/pki/trust/anchors",
"/var/lib/ca-certificates"]
*/
if p == "" {
continue
}
log.Logger.Debug().Str("what", p).Str("where", s.StateDir).Msg("Mounting bind")
op := mountBind(p, s.Rootdir, s.StateDir)
err2 := op.run()
if err2 != nil {
log.Logger.Err(err2).Send()
err = multierror.Append(err, err2)
} else {
// Only append to fstabs if there was no error, otherwise we will try to mount it after switch_root
s.fstabs = append(s.fstabs, &op.FstabEntry)
}
s.fstabs = append(s.fstabs, &op.FstabEntry)
err = multierror.Append(err, op.run())
}
log.Logger.Err(err).Send()
return err
},
),

View File

@ -17,8 +17,9 @@ type mountOperation struct {
}
func (m mountOperation) run() error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
if m.PrepareCallback != nil {
log.Logger.Debug().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("executing mount callback")
if err := m.PrepareCallback(); err != nil {
log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("executing mount callback")
return err