m/n/c/mgmt: move and factor out reboot code

Make sure we do not have two copies of mostly temporary reboot code
sitting around and put it in a sensible place.

Change-Id: I293a699dbfc3cfe23378485c512d8769b2859ab8
Reviewed-on: https://review.monogon.dev/c/monogon/+/3396
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/core/mgmt/power.go b/metropolis/node/core/mgmt/power.go
index 77601d7..05a5649 100644
--- a/metropolis/node/core/mgmt/power.go
+++ b/metropolis/node/core/mgmt/power.go
@@ -5,6 +5,7 @@
 	"os"
 	"time"
 
+	"github.com/vishvananda/netlink"
 	"golang.org/x/sys/unix"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -57,12 +58,38 @@
 		// Best-effort, if it fails this will still be a firmware reboot.
 		os.WriteFile("/sys/kernel/reboot/mode", []byte("cold"), 0644)
 	}
+	s.initiateReboot(method)
+	return &apb.RebootResponse{}, nil
+}
+
+func (s *Service) initiateReboot(method int) {
 	s.LogTree.MustLeveledFor("root.mgmt").Warning("Reboot requested, rebooting in 2s")
+	// TODO(#253): Tell Supervisor to shut down gracefully and reboot
 	go func() {
 		time.Sleep(2 * time.Second)
 		unix.Unmount(s.UpdateService.ESPPath, 0)
 		unix.Sync()
+		s.disableNetworkInterfaces()
 		unix.Reboot(method)
 	}()
-	return &apb.RebootResponse{}, nil
+}
+
+// For kexec it's recommended to disable all physical network interfaces
+// before doing it. This function doesn't return any errors as it's best-
+// effort anyways as we cannot reliably log the error anymore.
+func (s *Service) disableNetworkInterfaces() {
+	links, err := netlink.LinkList()
+	if err != nil {
+		return
+	}
+	for _, link := range links {
+		d, ok := link.(*netlink.Device)
+		if !ok {
+			continue
+		}
+		if err := netlink.LinkSetDown(d); err != nil {
+			s.LogTree.MustLeveledFor("root.mgmt").Errorf("Error taking link %q down: %v", link.Attrs().Name, err)
+			continue
+		}
+	}
 }