fix: successful ACPI shutdown in maintenance mode

Fixes #6817

The original problem wasn't reproducible with `main`, but there was a
set of bugs in the shutdown sequence which was preventing it from
completing successfully, as in the maintenance mode nothing is running
and initialized yet.

Most of the bugs were `nil` pointer dereferences.

Fixed a small issue with final 'RebootError' printed as a failure in the
ACPI shutdown path.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
Andrey Smirnov 2023-03-07 23:17:31 +04:00
parent b97e1abaa6
commit fda6da6929
No known key found for this signature in database
GPG Key ID: 7B26396447AB6DFD
3 changed files with 45 additions and 23 deletions

View File

@ -158,7 +158,9 @@ func (c *Controller) ListenForEvents(ctx context.Context) error {
log.Printf("shutdown via SIGTERM received")
if err := c.Run(ctx, runtime.SequenceShutdown, &machine.ShutdownRequest{Force: true}, runtime.WithTakeover()); err != nil {
log.Printf("shutdown failed: %v", err)
if !runtime.IsRebootError(err) {
log.Printf("shutdown failed: %v", err)
}
}
errCh <- nil
@ -178,7 +180,9 @@ func (c *Controller) ListenForEvents(ctx context.Context) error {
log.Printf("shutdown via ACPI received")
if err := c.Run(ctx, runtime.SequenceShutdown, &machine.ShutdownRequest{Force: true}, runtime.WithTakeover()); err != nil {
log.Printf("failed to run shutdown sequence: %s", err)
if !runtime.IsRebootError(err) {
log.Printf("failed to run shutdown sequence: %s", err)
}
}
errCh <- nil

View File

@ -55,8 +55,16 @@ func (dbus *DBusState) Start() error {
// Stop the D-Bus broker and logind mock.
func (dbus *DBusState) Stop() error {
if dbus.cancel == nil {
return nil
}
dbus.cancel()
if dbus.logindMock == nil || dbus.broker == nil {
return nil
}
if err := dbus.logindMock.Close(); err != nil {
return err
}

View File

@ -1096,25 +1096,6 @@ func mountDisks(r runtime.Runtime) (err error) {
return mount.Mount(mountpoints)
}
func unmountDisks(r runtime.Runtime) (err error) {
mountpoints := mount.NewMountPoints()
for _, disk := range r.Config().Machine().Disks() {
for i, part := range disk.Partitions() {
var partname string
partname, err = util.PartPath(disk.Device(), i+1)
if err != nil {
return err
}
mountpoints.Set(partname, mount.NewMountPoint(partname, part.MountPoint(), "xfs", unix.MS_NOATIME, ""))
}
}
return mount.Unmount(mountpoints)
}
// WriteUserFiles represents the WriteUserFiles task.
//
//nolint:gocyclo,cyclop
@ -1322,7 +1303,26 @@ func UnmountOverlayFilesystems(runtime.Sequence, any) (runtime.TaskExecutionFunc
// UnmountUserDisks represents the UnmountUserDisks task.
func UnmountUserDisks(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
return unmountDisks(r)
if r.Config() == nil {
return nil
}
mountpoints := mount.NewMountPoints()
for _, disk := range r.Config().Machine().Disks() {
for i, part := range disk.Partitions() {
var partname string
partname, err = util.PartPath(disk.Device(), i+1)
if err != nil {
return err
}
mountpoints.Set(partname, mount.NewMountPoint(partname, part.MountPoint(), "xfs", unix.MS_NOATIME, ""))
}
}
return mount.Unmount(mountpoints)
}, "unmountUserDisks"
}
@ -1366,7 +1366,12 @@ func UnmountPodMounts(runtime.Sequence, any) (runtime.TaskExecutionFunc, string)
// UnmountSystemDiskBindMounts represents the UnmountSystemDiskBindMounts task.
func UnmountSystemDiskBindMounts(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
devname := r.State().Machine().Disk().BlockDevice.Device().Name()
systemDisk := r.State().Machine().Disk()
if systemDisk == nil {
return nil
}
devname := systemDisk.BlockDevice.Device().Name()
f, err := os.Open("/proc/mounts")
if err != nil {
@ -1586,6 +1591,11 @@ func stopAndRemoveAllPods(stopAction cri.StopAction) runtime.TaskExecutionFunc {
return err
}
// check that the CRI is running and the socket is available, if not, skip the rest
if _, err = os.Stat(constants.CRIContainerdAddress); os.IsNotExist(err) {
return nil
}
client, err := cri.NewClient("unix://"+constants.CRIContainerdAddress, 10*time.Second)
if err != nil {
return err