mirror of
https://github.com/kairos-io/immucore.git
synced 2025-09-19 17:26:24 +00:00
8
internal/constants/constants.go
Normal file
8
internal/constants/constants.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
const PersistentStateTarget = "/usr/local/.state"
|
||||||
|
|
||||||
|
func DefaultRWPaths() []string {
|
||||||
|
// Default RW_PATHS to mount if there are none defined
|
||||||
|
return []string{"/etc", "/root", "/home", "/opt", "/srv", "/usr/local", "/var"}
|
||||||
|
}
|
@@ -1,11 +1,13 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/joho/godotenv"
|
||||||
"github.com/kairos-io/kairos/sdk/state"
|
"github.com/kairos-io/kairos/sdk/state"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BootedFromCD tells us if we are currently runnig of the LiveCD
|
||||||
func BootedFromCD() (bool, error) {
|
func BootedFromCD() (bool, error) {
|
||||||
runtime, err := state.NewRuntime()
|
runtime, err := state.NewRuntime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -15,6 +17,7 @@ func BootedFromCD() (bool, error) {
|
|||||||
return runtime.BootState == state.LiveCD, nil
|
return runtime.BootState == state.LiveCD, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BootStateToLabel lets us know the label we need to mount sysroot on
|
||||||
func BootStateToLabel() string {
|
func BootStateToLabel() string {
|
||||||
runtime, err := state.NewRuntime()
|
runtime, err := state.NewRuntime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -32,6 +35,7 @@ func BootStateToLabel() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRecovery lets us know if we are in the recovery
|
||||||
func IsRecovery() bool {
|
func IsRecovery() bool {
|
||||||
runtime, err := state.NewRuntime()
|
runtime, err := state.NewRuntime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,6 +49,8 @@ func IsRecovery() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRootDir returns the proper dir to mount all the stuff
|
||||||
|
// Useful if we want to move to a no-pivot boot
|
||||||
func GetRootDir() string {
|
func GetRootDir() string {
|
||||||
cmdline, _ := os.ReadFile("/proc/cmdline")
|
cmdline, _ := os.ReadFile("/proc/cmdline")
|
||||||
switch {
|
switch {
|
||||||
@@ -68,3 +74,33 @@ func UniqueSlice(slice []string) []string {
|
|||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadEnv will reaed an env file (key=value) and return a nice map
|
||||||
|
func ReadEnv(file string) (map[string]string, error) {
|
||||||
|
var envMap map[string]string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return envMap, err
|
||||||
|
}
|
||||||
|
defer func(f *os.File) {
|
||||||
|
_ = f.Close()
|
||||||
|
}(f)
|
||||||
|
|
||||||
|
envMap, err = godotenv.Parse(f)
|
||||||
|
if err != nil {
|
||||||
|
return envMap, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return envMap, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIfNotExists will check if a path exists and create it if needed
|
||||||
|
func CreateIfNotExists(path string) error {
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return os.MkdirAll(path, os.ModePerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -2,13 +2,17 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/deniswernert/go-fstab"
|
||||||
"github.com/kairos-io/kairos/pkg/utils"
|
"github.com/kairos-io/kairos/pkg/utils"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
|
// ParseMount will return a proper full disk path based on UUID or LABEL given
|
||||||
// input: LABEL=FOO:/mount
|
// input: LABEL=FOO:/mount
|
||||||
// output: /dev/disk...:/mount
|
// output: /dev/disk...:/mount
|
||||||
func ParseMount(s string) string {
|
func ParseMount(s string) string {
|
||||||
@@ -24,6 +28,7 @@ func ParseMount(s string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadCMDLineArg will return the pair of arg=value for a given arg if it was passed on the cmdline
|
||||||
func ReadCMDLineArg(arg string) []string {
|
func ReadCMDLineArg(arg string) []string {
|
||||||
cmdLine, err := os.ReadFile("/proc/cmdline")
|
cmdLine, err := os.ReadFile("/proc/cmdline")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -40,7 +45,51 @@ func ReadCMDLineArg(arg string) []string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMountedByLabel lets us know if the given label is currently mounted
|
||||||
func IsMountedByLabel(label string) bool {
|
func IsMountedByLabel(label string) bool {
|
||||||
_, err := utils.SH(fmt.Sprintf("findmnt /dev/disk/by-label/%s", label))
|
_, err := utils.SH(fmt.Sprintf("findmnt /dev/disk/by-label/%s", label))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiskFSType will return the FS type for a given disk
|
||||||
|
// Needs to be mounted
|
||||||
|
// Needs full path so either /dev/sda1 or /dev/disk/by-{label,uuid}/{label,uuid}
|
||||||
|
func DiskFSType(s string) string {
|
||||||
|
out, _ := utils.SH(fmt.Sprintf("findmnt -rno FSTYPE %s", s))
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncState will rsync source into destination. Useful for Bind mounts.
|
||||||
|
func SyncState(src, dst string) error {
|
||||||
|
return exec.Command("rsync", "-aqAX", src, dst).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendSlash it's in the name. Appends a slash.
|
||||||
|
func AppendSlash(path string) string {
|
||||||
|
if !strings.HasSuffix(path, "/") {
|
||||||
|
return fmt.Sprintf("%s/", path)
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
// MountToFstab transforms a mount.Mount into a fstab.Mount so we can transform existing mounts into the fstab format
|
||||||
|
func MountToFstab(m mount.Mount) *fstab.Mount {
|
||||||
|
opts := map[string]string{}
|
||||||
|
for _, o := range m.Options {
|
||||||
|
if strings.Contains(o, "=") {
|
||||||
|
dat := strings.Split(o, "=")
|
||||||
|
key := dat[0]
|
||||||
|
value := dat[1]
|
||||||
|
opts[key] = value
|
||||||
|
} else {
|
||||||
|
opts[o] = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &fstab.Mount{
|
||||||
|
Spec: m.Source,
|
||||||
|
VfsType: m.Type,
|
||||||
|
MntOps: opts,
|
||||||
|
Freq: 0,
|
||||||
|
PassNo: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -3,36 +3,14 @@ package mount
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/deniswernert/go-fstab"
|
internalUtils "github.com/kairos-io/immucore/internal/utils"
|
||||||
"github.com/kairos-io/kairos/pkg/utils"
|
|
||||||
"github.com/moby/sys/mountinfo"
|
"github.com/moby/sys/mountinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func rootFSType(s string) string {
|
|
||||||
out, _ := utils.SH(fmt.Sprintf("findmnt -rno FSTYPE %s", s))
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
func createIfNotExists(path string) error {
|
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
||||||
return os.MkdirAll(path, os.ModePerm)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendSlash(path string) string {
|
|
||||||
if !strings.HasSuffix(path, "/") {
|
|
||||||
return fmt.Sprintf("%s/", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L129
|
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L129
|
||||||
func baseOverlay(overlay Overlay) (mountOperation, error) {
|
func baseOverlay(overlay Overlay) (mountOperation, error) {
|
||||||
if err := os.MkdirAll(overlay.Base, 0700); err != nil {
|
if err := os.MkdirAll(overlay.Base, 0700); err != nil {
|
||||||
@@ -50,7 +28,7 @@ func baseOverlay(overlay Overlay) (mountOperation, error) {
|
|||||||
case "tmpfs":
|
case "tmpfs":
|
||||||
tmpMount := mount.Mount{Type: "tmpfs", Source: "tmpfs", Options: []string{fmt.Sprintf("size=%s", dat[1])}}
|
tmpMount := mount.Mount{Type: "tmpfs", Source: "tmpfs", Options: []string{fmt.Sprintf("size=%s", dat[1])}}
|
||||||
err := mount.All([]mount.Mount{tmpMount}, overlay.Base)
|
err := mount.All([]mount.Mount{tmpMount}, overlay.Base)
|
||||||
tmpFstab := mountToStab(tmpMount)
|
tmpFstab := internalUtils.MountToFstab(tmpMount)
|
||||||
tmpFstab.File = overlay.BackingBase
|
tmpFstab.File = overlay.BackingBase
|
||||||
return mountOperation{
|
return mountOperation{
|
||||||
MountOption: tmpMount,
|
MountOption: tmpMount,
|
||||||
@@ -61,7 +39,7 @@ func baseOverlay(overlay Overlay) (mountOperation, error) {
|
|||||||
blockMount := mount.Mount{Type: "auto", Source: dat[1]}
|
blockMount := mount.Mount{Type: "auto", Source: dat[1]}
|
||||||
err := mount.All([]mount.Mount{blockMount}, overlay.Base)
|
err := mount.All([]mount.Mount{blockMount}, overlay.Base)
|
||||||
|
|
||||||
tmpFstab := mountToStab(blockMount)
|
tmpFstab := internalUtils.MountToFstab(blockMount)
|
||||||
tmpFstab.File = overlay.BackingBase
|
tmpFstab.File = overlay.BackingBase
|
||||||
tmpFstab.MntOps["default"] = ""
|
tmpFstab.MntOps["default"] = ""
|
||||||
|
|
||||||
@@ -75,27 +53,6 @@ func baseOverlay(overlay Overlay) (mountOperation, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mountToStab(m mount.Mount) *fstab.Mount {
|
|
||||||
opts := map[string]string{}
|
|
||||||
for _, o := range m.Options {
|
|
||||||
if strings.Contains(o, "=") {
|
|
||||||
dat := strings.Split(o, "=")
|
|
||||||
key := dat[0]
|
|
||||||
value := dat[1]
|
|
||||||
opts[key] = value
|
|
||||||
} else {
|
|
||||||
opts[o] = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &fstab.Mount{
|
|
||||||
Spec: m.Source,
|
|
||||||
VfsType: m.Type,
|
|
||||||
MntOps: opts,
|
|
||||||
Freq: 0,
|
|
||||||
PassNo: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L183
|
// 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 {
|
func mountBind(mountpoint, root, stateTarget string) mountOperation {
|
||||||
mountpoint = strings.TrimLeft(mountpoint, "/") // normalize, remove / upfront as we are going to re-use it in subdirs
|
mountpoint = strings.TrimLeft(mountpoint, "/") // normalize, remove / upfront as we are going to re-use it in subdirs
|
||||||
@@ -113,7 +70,7 @@ func mountBind(mountpoint, root, stateTarget string) mountOperation {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpFstab := mountToStab(tmpMount)
|
tmpFstab := internalUtils.MountToFstab(tmpMount)
|
||||||
tmpFstab.File = fmt.Sprintf("/%s", mountpoint)
|
tmpFstab.File = fmt.Sprintf("/%s", mountpoint)
|
||||||
tmpFstab.Spec = strings.ReplaceAll(tmpFstab.Spec, root, "")
|
tmpFstab.Spec = strings.ReplaceAll(tmpFstab.Spec, root, "")
|
||||||
return mountOperation{
|
return mountOperation{
|
||||||
@@ -121,29 +78,26 @@ func mountBind(mountpoint, root, stateTarget string) mountOperation {
|
|||||||
FstabEntry: *tmpFstab,
|
FstabEntry: *tmpFstab,
|
||||||
Target: rootMount,
|
Target: rootMount,
|
||||||
PrepareCallback: func() error {
|
PrepareCallback: func() error {
|
||||||
if err := createIfNotExists(rootMount); err != nil {
|
if err := internalUtils.CreateIfNotExists(rootMount); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := createIfNotExists(stateDir); err != nil {
|
if err := internalUtils.CreateIfNotExists(stateDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return syncState(appendSlash(rootMount), appendSlash(stateDir))
|
return internalUtils.SyncState(internalUtils.AppendSlash(rootMount), internalUtils.AppendSlash(stateDir))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncState(src, dst string) error {
|
|
||||||
return exec.Command("rsync", "-aqAX", src, dst).Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/kairos-io/packages/blob/94aa3bef3d1330cb6c6905ae164f5004b6a58b8c/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L145
|
// 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) {
|
func mountWithBaseOverlay(mountpoint, root, base string) (mountOperation, error) {
|
||||||
mountpoint = strings.TrimLeft(mountpoint, "/") // normalize, remove / upfront as we are going to re-use it in subdirs
|
mountpoint = strings.TrimLeft(mountpoint, "/") // normalize, remove / upfront as we are going to re-use it in subdirs
|
||||||
rootMount := filepath.Join(root, mountpoint)
|
rootMount := filepath.Join(root, mountpoint)
|
||||||
bindMountPath := strings.ReplaceAll(mountpoint, "/", "-")
|
bindMountPath := strings.ReplaceAll(mountpoint, "/", "-")
|
||||||
|
|
||||||
createIfNotExists(rootMount)
|
// TODO: Should we error out if we cant create the target to mount to?
|
||||||
|
_ = internalUtils.CreateIfNotExists(rootMount)
|
||||||
if mounted, _ := mountinfo.Mounted(rootMount); !mounted {
|
if mounted, _ := mountinfo.Mounted(rootMount); !mounted {
|
||||||
upperdir := filepath.Join(base, bindMountPath, ".overlay", "upper")
|
upperdir := filepath.Join(base, bindMountPath, ".overlay", "upper")
|
||||||
workdir := filepath.Join(base, bindMountPath, ".overlay", "work")
|
workdir := filepath.Join(base, bindMountPath, ".overlay", "work")
|
||||||
@@ -159,7 +113,7 @@ func mountWithBaseOverlay(mountpoint, root, base string) (mountOperation, error)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpFstab := mountToStab(tmpMount)
|
tmpFstab := internalUtils.MountToFstab(tmpMount)
|
||||||
tmpFstab.File = rootMount
|
tmpFstab.File = rootMount
|
||||||
|
|
||||||
// TODO: update fstab with x-systemd info
|
// TODO: update fstab with x-systemd info
|
||||||
|
@@ -3,6 +3,7 @@ package mount
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/kairos-io/immucore/internal/constants"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -11,7 +12,6 @@ import (
|
|||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/deniswernert/go-fstab"
|
"github.com/deniswernert/go-fstab"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/joho/godotenv"
|
|
||||||
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"
|
||||||
@@ -69,14 +69,15 @@ func (s *State) WriteFstab(fstabFile string) func(context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
// As we mount on /sysroot during initramfs but the fstab file is for the real init process, we need to remove
|
// 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
|
// Any mentions to /sysroot from the fstab lines, otherwise they won't work
|
||||||
fstCleaned := strings.ReplaceAll(fst.String(), "/sysroot", "")
|
fstCleaned := strings.ReplaceAll(fst.String(), "/sysroot", "")
|
||||||
toWrite := fmt.Sprintf("%s\n", fstCleaned)
|
toWrite := fmt.Sprintf("%s\n", fstCleaned)
|
||||||
if _, err := f.WriteString(toWrite); err != nil {
|
if _, err := f.WriteString(toWrite); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_ = f.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -115,12 +116,10 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
default:
|
default:
|
||||||
if _, err := os.Stat(where); os.IsNotExist(err) {
|
err := internalUtils.CreateIfNotExists(where)
|
||||||
err = os.MkdirAll(where, os.ModeDir|os.ModePerm)
|
if err != nil {
|
||||||
if err != nil {
|
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Err(err).Msg("Creating dir")
|
||||||
log.Logger.Debug().Str("what", what).Str("where", where).Str("type", t).Strs("options", options).Err(err).Msg("Creating dir")
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
mountPoint := mount.Mount{
|
mountPoint := mount.Mount{
|
||||||
@@ -128,7 +127,7 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
|
|||||||
Source: what,
|
Source: what,
|
||||||
Options: options,
|
Options: options,
|
||||||
}
|
}
|
||||||
tmpFstab := mountToStab(mountPoint)
|
tmpFstab := internalUtils.MountToFstab(mountPoint)
|
||||||
tmpFstab.File = where
|
tmpFstab.File = where
|
||||||
op := mountOperation{
|
op := mountOperation{
|
||||||
MountOption: mountPoint,
|
MountOption: mountPoint,
|
||||||
@@ -136,7 +135,7 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
|
|||||||
Target: where,
|
Target: where,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := op.run()
|
err = op.run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -158,7 +157,7 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
|
|||||||
|
|
||||||
func (s *State) WriteDAG(g *herd.Graph) (out string) {
|
func (s *State) WriteDAG(g *herd.Graph) (out string) {
|
||||||
for i, layer := range g.Analyze() {
|
for i, layer := range g.Analyze() {
|
||||||
out += fmt.Sprintf("%d.\n", (i + 1))
|
out += fmt.Sprintf("%d.\n", i+1)
|
||||||
for _, op := range layer {
|
for _, op := range layer {
|
||||||
if op.Error != nil {
|
if op.Error != nil {
|
||||||
out += fmt.Sprintf(" <%s> (error: %s) (background: %t) (weak: %t)\n", op.Name, op.Error.Error(), op.Background, op.WeakDeps)
|
out += fmt.Sprintf(" <%s> (error: %s) (background: %t) (weak: %t)\n", op.Name, op.Error.Error(), op.Background, op.WeakDeps)
|
||||||
@@ -170,32 +169,9 @@ func (s *State) WriteDAG(g *herd.Graph) (out string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func readEnv(file string) (map[string]string, error) {
|
|
||||||
var envMap map[string]string
|
|
||||||
var err error
|
|
||||||
|
|
||||||
f, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return envMap, err
|
|
||||||
}
|
|
||||||
defer func(f *os.File) {
|
|
||||||
_ = f.Close()
|
|
||||||
}(f)
|
|
||||||
|
|
||||||
envMap, err = godotenv.Parse(f)
|
|
||||||
if err != nil {
|
|
||||||
return envMap, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return envMap, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) Register(g *herd.Graph) error {
|
func (s *State) Register(g *herd.Graph) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Default RW_PATHS to mount ALWAYS
|
|
||||||
s.OverlayDirs = []string{"/etc", "/root", "/home", "/opt", "/srv", "/usr/local", "/var"}
|
|
||||||
|
|
||||||
runtime, err := state.NewRuntime()
|
runtime, err := state.NewRuntime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Logger.Debug().Err(err).Msg("")
|
s.Logger.Debug().Err(err).Msg("")
|
||||||
@@ -299,32 +275,29 @@ func (s *State) Register(g *herd.Graph) error {
|
|||||||
s.CustomMounts = map[string]string{}
|
s.CustomMounts = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err := readEnv("/run/cos/cos-layout.env")
|
env, err := internalUtils.ReadEnv("/run/cos/cos-layout.env")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logger.Err(err).Msg("Reading env")
|
log.Logger.Err(err).Msg("Reading env")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// populate from env here
|
// populate from env here
|
||||||
s.OverlayDirs = append(s.OverlayDirs, strings.Split(env["RW_PATHS"], " ")...)
|
s.OverlayDirs = strings.Split(env["RW_PATHS"], " ")
|
||||||
|
// If empty, then set defaults
|
||||||
|
if len(s.OverlayDirs) == 0 {
|
||||||
|
s.OverlayDirs = constants.DefaultRWPaths()
|
||||||
|
}
|
||||||
// Remove any duplicates
|
// Remove any duplicates
|
||||||
s.OverlayDirs = internalUtils.UniqueSlice(s.OverlayDirs)
|
s.OverlayDirs = internalUtils.UniqueSlice(s.OverlayDirs)
|
||||||
|
|
||||||
// TODO: PERSISTENT_STATE_TARGET /usr/local/.state
|
|
||||||
s.BindMounts = strings.Split(env["PERSISTENT_STATE_PATHS"], " ")
|
s.BindMounts = strings.Split(env["PERSISTENT_STATE_PATHS"], " ")
|
||||||
// Remove any duplicates
|
// Remove any duplicates
|
||||||
s.BindMounts = internalUtils.UniqueSlice(s.BindMounts)
|
s.BindMounts = internalUtils.UniqueSlice(s.BindMounts)
|
||||||
|
|
||||||
s.StateDir = env["PERSISTENT_STATE_TARGET"]
|
s.StateDir = env["PERSISTENT_STATE_TARGET"]
|
||||||
if s.StateDir == "" {
|
if s.StateDir == "" {
|
||||||
s.StateDir = "/usr/local/.state"
|
s.StateDir = constants.PersistentStateTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
// s.CustomMounts is special:
|
|
||||||
// It gets parsed by the cmdline (TODO)
|
|
||||||
// and from the env var
|
|
||||||
// https://github.com/kairos-io/packages/blob/7c3581a8ba6371e5ce10c3a98bae54fde6a505af/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-generator.sh#L71
|
|
||||||
// https://github.com/kairos-io/packages/blob/7c3581a8ba6371e5ce10c3a98bae54fde6a505af/packages/system/dracut/immutable-rootfs/30cos-immutable-rootfs/cos-mount-layout.sh#L80
|
|
||||||
|
|
||||||
addLine := func(d string) {
|
addLine := func(d string) {
|
||||||
dat := strings.Split(d, ":")
|
dat := strings.Split(d, ":")
|
||||||
if len(dat) == 2 {
|
if len(dat) == 2 {
|
||||||
@@ -333,6 +306,8 @@ func (s *State) Register(g *herd.Graph) error {
|
|||||||
s.CustomMounts[disk] = path
|
s.CustomMounts[disk] = path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Parse custom mounts also from cmdline (rd.cos.mount=)
|
||||||
|
// Parse custom mounts also from env file (VOLUMES)
|
||||||
for _, v := range append(internalUtils.ReadCMDLineArg("rd.cos.mount="), strings.Split(env["VOLUMES"], " ")...) {
|
for _, v := range append(internalUtils.ReadCMDLineArg("rd.cos.mount="), strings.Split(env["VOLUMES"], " ")...) {
|
||||||
addLine(internalUtils.ParseMount(v))
|
addLine(internalUtils.ParseMount(v))
|
||||||
}
|
}
|
||||||
@@ -345,7 +320,7 @@ func (s *State) Register(g *herd.Graph) error {
|
|||||||
// end sysroot mount
|
// end sysroot mount
|
||||||
|
|
||||||
// overlay mount start
|
// overlay mount start
|
||||||
if rootFSType(s.Rootdir) != "overlay" {
|
if internalUtils.DiskFSType(s.Rootdir) != "overlay" {
|
||||||
err = g.Add(opMountBaseOverlay,
|
err = g.Add(opMountBaseOverlay,
|
||||||
herd.WithCallback(
|
herd.WithCallback(
|
||||||
func(ctx context.Context) error {
|
func(ctx context.Context) error {
|
||||||
@@ -366,7 +341,7 @@ func (s *State) Register(g *herd.Graph) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
overlayCondition := herd.ConditionalOption(func() bool { return rootFSType(s.Rootdir) != "overlay" }, herd.WithDeps(opMountBaseOverlay))
|
overlayCondition := herd.ConditionalOption(func() bool { return internalUtils.DiskFSType(s.Rootdir) != "overlay" }, herd.WithDeps(opMountBaseOverlay))
|
||||||
// TODO: Add fsck
|
// TODO: Add fsck
|
||||||
// mount overlay
|
// mount overlay
|
||||||
err = g.Add(
|
err = g.Add(
|
||||||
@@ -439,24 +414,7 @@ func (s *State) Register(g *herd.Graph) error {
|
|||||||
func(ctx context.Context) error {
|
func(ctx context.Context) error {
|
||||||
var err *multierror.Error
|
var err *multierror.Error
|
||||||
for _, p := range s.BindMounts {
|
for _, p := range s.BindMounts {
|
||||||
// TODO: Check why p can be empty, Example:
|
// Ignore empty values that can get there by having extra spaces in the cos-layout file
|
||||||
/*
|
|
||||||
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 == "" {
|
if p == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user