From bf6929a22dc99c0da5404b1e55569e14db820956 Mon Sep 17 00:00:00 2001
From: Alexander Schreiber <als@google.com>
Date: Thu, 18 Oct 2007 10:25:50 +0000
Subject: [PATCH] Patch series for reboot feature, part 2

This patch series implements the reboot command for gnt-instance. It
supports three types of reboot: soft (hypervisor reboot), hard (instance
config rebuild and reboot) and full (full instance shutdown and startup
again).

This patch contains the opcode and lu part.

Reviewed-by: iustinp
---
 lib/cmdlib.py  | 94 +++++++++++++++++++++++++++++++++++++++++++++++---
 lib/mcpu.py    |  1 +
 lib/opcodes.py |  7 ++++
 3 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index f84ac6337..2fce8a2a5 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -528,6 +528,18 @@ def _InitGanetiServerSetup(ss):
                              (result.cmd, result.exit_code, result.output))
 
 
+def _CheckInstanceBridgesExist(instance):
+  """Check that the brigdes needed by an instance exist.
+
+  """
+  # check bridges existance
+  brlist = [nic.bridge for nic in instance.nics]
+  if not rpc.call_bridges_exist(instance.primary_node, brlist):
+    raise errors.OpPrereqError("one or more target bridges %s does not"
+                               " exist on destination node '%s'" %
+                               (brlist, instance.primary_node))
+
+
 class LUInitCluster(LogicalUnit):
   """Initialise the cluster.
 
@@ -1934,11 +1946,7 @@ class LUStartupInstance(LogicalUnit):
                                  self.op.instance_name)
 
     # check bridges existance
-    brlist = [nic.bridge for nic in instance.nics]
-    if not rpc.call_bridges_exist(instance.primary_node, brlist):
-      raise errors.OpPrereqError("one or more target bridges %s does not"
-                                 " exist on destination node '%s'" %
-                                 (brlist, instance.primary_node))
+    _CheckInstanceBridgesExist(instance)
 
     self.instance = instance
     self.op.instance_name = instance.name
@@ -1976,6 +1984,82 @@ class LUStartupInstance(LogicalUnit):
     self.cfg.MarkInstanceUp(instance.name)
 
 
+class LURebootInstance(LogicalUnit):
+  """Reboot an instance.
+
+  """
+  HPATH = "instance-reboot"
+  HTYPE = constants.HTYPE_INSTANCE
+  _OP_REQP = ["instance_name", "ignore_secondaries", "reboot_type"]
+
+  def BuildHooksEnv(self):
+    """Build hooks env.
+
+    This runs on master, primary and secondary nodes of the instance.
+
+    """
+    env = {
+      "IGNORE_SECONDARIES": self.op.ignore_secondaries,
+      }
+    env.update(_BuildInstanceHookEnvByObject(self.instance))
+    nl = ([self.sstore.GetMasterNode(), self.instance.primary_node] +
+          list(self.instance.secondary_nodes))
+    return env, nl, nl
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks that the instance is in the cluster.
+
+    """
+    instance = self.cfg.GetInstanceInfo(
+      self.cfg.ExpandInstanceName(self.op.instance_name))
+    if instance is None:
+      raise errors.OpPrereqError("Instance '%s' not known" %
+                                 self.op.instance_name)
+
+    # check bridges existance
+    _CheckInstanceBridgesExist(instance)
+
+    self.instance = instance
+    self.op.instance_name = instance.name
+
+  def Exec(self, feedback_fn):
+    """Reboot the instance.
+
+    """
+    instance = self.instance
+    ignore_secondaries = self.op.ignore_secondaries
+    reboot_type = self.op.reboot_type
+    extra_args = getattr(self.op, "extra_args", "")
+
+    node_current = instance.primary_node
+
+    if reboot_type not in [constants.INSTANCE_REBOOT_SOFT,
+                           constants.INSTANCE_REBOOT_HARD,
+                           constants.INSTANCE_REBOOT_FULL]:
+      raise errors.ParameterError("reboot type not in [%s, %s, %s]" %
+                                  (constants.INSTANCE_REBOOT_SOFT,
+                                   constants.INSTANCE_REBOOT_HARD,
+                                   constants.INSTANCE_REBOOT_FULL))
+
+    if reboot_type in [constants.INSTANCE_REBOOT_SOFT,
+                       constants.INSTANCE_REBOOT_HARD]:
+      if not rpc.call_instance_reboot(node_current, instance,
+                                      reboot_type, extra_args):
+        raise errors.OpExecError("Could not reboot instance")
+    else:
+      if not rpc.call_instance_shutdown(node_current, instance):
+        raise errors.OpExecError("could not shutdown instance for full reboot")
+      _ShutdownInstanceDisks(instance, self.cfg)
+      _StartInstanceDisks(self.cfg, instance, ignore_secondaries)
+      if not rpc.call_instance_start(node_current, instance, extra_args):
+        _ShutdownInstanceDisks(instance, self.cfg)
+        raise errors.OpExecError("Could not start instance for full reboot")
+
+    self.cfg.MarkInstanceUp(instance.name)
+
+
 class LUShutdownInstance(LogicalUnit):
   """Shutdown an instance.
 
diff --git a/lib/mcpu.py b/lib/mcpu.py
index 0eb4324a1..2f89842fb 100644
--- a/lib/mcpu.py
+++ b/lib/mcpu.py
@@ -63,6 +63,7 @@ class Processor(object):
     opcodes.OpActivateInstanceDisks: cmdlib.LUActivateInstanceDisks,
     opcodes.OpShutdownInstance: cmdlib.LUShutdownInstance,
     opcodes.OpStartupInstance: cmdlib.LUStartupInstance,
+    opcodes.OpRebootInstance: cmdlib.LURebootInstance,
     opcodes.OpDeactivateInstanceDisks: cmdlib.LUDeactivateInstanceDisks,
     opcodes.OpAddMDDRBDComponent: cmdlib.LUAddMDDRBDComponent,
     opcodes.OpRemoveMDDRBDComponent: cmdlib.LURemoveMDDRBDComponent,
diff --git a/lib/opcodes.py b/lib/opcodes.py
index 5e11fbae8..e06a37ec9 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -171,6 +171,13 @@ class OpShutdownInstance(OpCode):
   __slots__ = ["instance_name"]
 
 
+class OpRebootInstance(OpCode):
+  """Reboot an instance."""
+  OP_ID = "OP_INSTANCE_STARTUP"
+  __slots__ = ["instance_name", "reboot_type", "extra_args",
+               "ignore_secondaries" ]
+
+
 class OpAddMDDRBDComponent(OpCode):
   """Add a MD-DRBD component."""
   OP_ID = "OP_INSTANCE_ADD_MDDRBD"
-- 
GitLab