m/n/c/update: implement kexec-based activation

As we've had some issues with EFI-based slot activation and enterprise
server firmware is extremely slow, this implements kexec-based
activation. This just kexecs into the freshly-installed slot instead of
rebooting. It still updates the BootOrder on successful boot to allow
cold-boots if the server crashes or loses power, but no longer uses the
NextBoot mechanism to boot into the new slot once (this is taken care of
by kexec).

Change-Id: I6092c47d988634ba39fb6bdd7fd7ccd41ceb02ef
Reviewed-on: https://review.monogon.dev/c/monogon/+/2021
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/proto/api/management.proto b/metropolis/proto/api/management.proto
index 80cb195..14184b6 100644
--- a/metropolis/proto/api/management.proto
+++ b/metropolis/proto/api/management.proto
@@ -271,14 +271,26 @@
   repeated metropolis.proto.common.LogEntry stream_entries = 2;
 }
 
+enum ActivationMode {
+  ACTIVATION_INVALID = 0;
+  // The new bundle is not activated immediately. It gets activated on the next
+  // reboot/reset.
+  ACTIVATION_NONE = 1;
+  // The node is rebooted immediately to activate the new image.
+  ACTIVATION_REBOOT = 2;
+  // The node uses kexec to activate the new image immediately without fully
+  // rebooting.
+  ACTIVATION_KEXEC = 3;
+}
+
 message UpdateNodeRequest {
   // An HTTPS URL to a Metropolis bundle containing the new OS to install.
   string bundle_url = 1;
 
-  // If set, do not reboot the node after installation. This means the updated
-  // version will not be active until the node has been rebooted via another
-  // method.
-  bool no_reboot = 2;
+  reserved 2;
+
+  // Specifies how the updated image should be activated.
+  ActivationMode activation_mode = 3;
 }
 
 message UpdateNodeResponse {}
\ No newline at end of file