Deal nicely with already mounted errors

Signed-off-by: Itxaka <itxaka@spectrocloud.com>
This commit is contained in:
Itxaka
2023-02-09 12:35:45 +01:00
parent 645d0a428a
commit aee2bbde84
4 changed files with 38 additions and 22 deletions

View File

@@ -1,8 +1,12 @@
package constants package constants
import "errors"
const PersistentStateTarget = "/usr/local/.state" const PersistentStateTarget = "/usr/local/.state"
func DefaultRWPaths() []string { func DefaultRWPaths() []string {
// Default RW_PATHS to mount if there are none defined // Default RW_PATHS to mount if there are none defined
return []string{"/etc", "/root", "/home", "/opt", "/srv", "/usr/local", "/var"} return []string{"/etc", "/root", "/home", "/opt", "/srv", "/usr/local", "/var"}
} }
var ErrAlreadyMounted = errors.New("already mounted")

View File

@@ -27,21 +27,15 @@ func baseOverlay(overlay Overlay) (mountOperation, error) {
switch t { switch t {
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)
tmpFstab := internalUtils.MountToFstab(tmpMount) tmpFstab := internalUtils.MountToFstab(tmpMount)
// TODO: Fix this
// Currently stores it wrongly the the fstab as `tmpfs tmpfs:20% tmpfs size=20% 0 0`
// Correct format should be `tmpfs /run/overlay tmpfs defaults,size=20% 0 0`
tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base) tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base)
return mountOperation{ return mountOperation{
MountOption: tmpMount, MountOption: tmpMount,
FstabEntry: *tmpFstab, FstabEntry: *tmpFstab,
Target: overlay.Base, Target: overlay.Base,
}, err }, nil
case "block": case "block":
blockMount := mount.Mount{Type: "auto", Source: dat[1]} blockMount := mount.Mount{Type: "auto", Source: dat[1]}
err := mount.All([]mount.Mount{blockMount}, overlay.Base)
tmpFstab := internalUtils.MountToFstab(blockMount) tmpFstab := internalUtils.MountToFstab(blockMount)
// TODO: Check if this is properly written to fstab, currently have no examples // TODO: Check if this is properly written to fstab, currently have no examples
tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base) tmpFstab.File = internalUtils.CleanSysrootForFstab(overlay.Base)
@@ -51,7 +45,7 @@ func baseOverlay(overlay Overlay) (mountOperation, error) {
MountOption: blockMount, MountOption: blockMount,
FstabEntry: *tmpFstab, FstabEntry: *tmpFstab,
Target: overlay.Base, Target: overlay.Base,
}, err }, nil
default: default:
return mountOperation{}, fmt.Errorf("invalid overlay backing base type") return mountOperation{}, fmt.Errorf("invalid overlay backing base type")
} }

View File

@@ -2,6 +2,7 @@ package mount
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"github.com/kairos-io/immucore/internal/constants" "github.com/kairos-io/immucore/internal/constants"
"os" "os"
@@ -132,11 +133,16 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du
} }
err = op.run() err = op.run()
if err != nil {
if err == nil {
s.fstabs = append(s.fstabs, tmpFstab)
}
// only continue the loop if it's an error and not an already mounted error
if err != nil && !errors.Is(err, constants.ErrAlreadyMounted) {
continue continue
} }
s.fstabs = append(s.fstabs, tmpFstab)
return nil return nil
case <-c.Done(): case <-c.Done():
e := fmt.Errorf("context canceled") e := fmt.Errorf("context canceled")
@@ -328,7 +334,12 @@ func (s *State) Register(g *herd.Graph) error {
return err return err
} }
s.fstabs = append(s.fstabs, &op.FstabEntry) s.fstabs = append(s.fstabs, &op.FstabEntry)
return op.run() err = op.run()
// Don't return error if it's an already mounted error
if err != nil && errors.Is(err, constants.ErrAlreadyMounted) {
return nil
}
return err
}, },
), ),
) )
@@ -347,17 +358,21 @@ func (s *State) Register(g *herd.Graph) error {
mountRootCondition, mountRootCondition,
herd.WithCallback( herd.WithCallback(
func(ctx context.Context) error { func(ctx context.Context) error {
var err error var err *multierror.Error
for _, p := range s.OverlayDirs { for _, p := range s.OverlayDirs {
op, err := mountWithBaseOverlay(p, s.Rootdir, "/run/overlay") op, err := mountWithBaseOverlay(p, s.Rootdir, "/run/overlay")
if err != nil { if err != nil {
return err return err
} }
s.fstabs = append(s.fstabs, &op.FstabEntry) s.fstabs = append(s.fstabs, &op.FstabEntry)
err = multierror.Append(err, op.run()) err2 := op.run()
// Append to errors only if it's not an already mounted error
if err2 != nil && !errors.Is(err2, constants.ErrAlreadyMounted) {
err = multierror.Append(err, err2)
}
} }
return err return err.ErrorOrNil()
}, },
), ),
) )
@@ -416,13 +431,15 @@ func (s *State) Register(g *herd.Graph) error {
} }
op := mountBind(p, s.Rootdir, s.StateDir) op := mountBind(p, s.Rootdir, s.StateDir)
err2 := op.run() err2 := op.run()
if err2 != nil { 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 // 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)
} }
// Append to errors only if it's not an already mounted error
if err2 != nil && !errors.Is(err2, constants.ErrAlreadyMounted) {
log.Logger.Err(err2).Send()
err = multierror.Append(err, err2)
}
} }
log.Logger.Err(err.ErrorOrNil()).Send() log.Logger.Err(err.ErrorOrNil()).Send()
return err.ErrorOrNil() return err.ErrorOrNil()

View File

@@ -3,6 +3,7 @@ package mount
import ( 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/moby/sys/mountinfo" "github.com/moby/sys/mountinfo"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@@ -20,19 +21,19 @@ func (m mountOperation) run() error {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger() log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Logger()
if m.PrepareCallback != nil { if m.PrepareCallback != nil {
if err := m.PrepareCallback(); err != nil { 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") log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).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 {
log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("checking mount status") log.Logger.Err(err).Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Msg("checking mount status")
return err return err
} }
if mounted { if mounted {
log.Logger.Debug().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Msg("Already mounted") log.Logger.Debug().Str("what", m.MountOption.Source).Str("where", m.Target).Str("type", m.MountOption.Type).Strs("options", m.MountOption.Options).Msg("Already mounted")
return nil return constants.ErrAlreadyMounted
} }
return mount.All([]mount.Mount{m.MountOption}, m.Target) return mount.All([]mount.Mount{m.MountOption}, m.Target)
} }