From fda6da692956d863d320f25cd50833da2f93104c Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 7 Mar 2023 23:17:31 +0400 Subject: [PATCH] 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 --- .../runtime/v1alpha1/v1alpha1_controller.go | 8 ++- .../pkg/runtime/v1alpha1/v1alpha1_dbus.go | 8 +++ .../v1alpha1/v1alpha1_sequencer_tasks.go | 52 +++++++++++-------- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_controller.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_controller.go index 2e61d1367..d24a35ebd 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_controller.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_controller.go @@ -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 diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_dbus.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_dbus.go index 9fa005164..e6bb329f1 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_dbus.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_dbus.go @@ -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 } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go index c5d297907..c6fff0dc9 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go @@ -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