From fe7b03519bbba088359c0dad5b8602acdbf73147 Mon Sep 17 00:00:00 2001
From: Michael Hanselmann <hansmi@google.com>
Date: Thu, 26 Jul 2007 16:09:11 +0000
Subject: [PATCH] =?UTF-8?q?-=20Move=20--force=20option=20to=20cli.py=20-?=
 =?UTF-8?q?=20Implement=20=E2=80=9Cgnt-instance=20reinstall=E2=80=9D=20-?=
 =?UTF-8?q?=20Fix=20two=20typos?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reviewed-by: iustinp
---
 lib/cli.py           |  5 ++-
 lib/cmdlib.py        | 88 +++++++++++++++++++++++++++++++++++++++-----
 lib/mcpu.py          |  1 +
 lib/opcodes.py       |  6 +++
 scripts/gnt-backup   |  4 +-
 scripts/gnt-instance | 37 ++++++++++++++-----
 6 files changed, 118 insertions(+), 23 deletions(-)

diff --git a/lib/cli.py b/lib/cli.py
index cfb8c3876..73ad02834 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -39,7 +39,7 @@ from optparse import (OptionParser, make_option, TitledHelpFormatter,
 __all__ = ["DEBUG_OPT", "NOHDR_OPT", "SEP_OPT", "GenericMain", "SubmitOpCode",
            "cli_option", "OutputTable",
            "ARGS_NONE", "ARGS_FIXED", "ARGS_ATLEAST", "ARGS_ANY", "ARGS_ONE",
-           "USEUNITS_OPT", "FIELDS_OPT"]
+           "USEUNITS_OPT", "FIELDS_OPT", "FORCE_OPT"]
 
 DEBUG_OPT = make_option("-d", "--debug", default=False,
                         action="store_true",
@@ -62,6 +62,9 @@ FIELDS_OPT = make_option("-o", "--output", dest="output", action="store",
                          type="string", help="Select output fields",
                          metavar="FIELDS")
 
+FORCE_OPT = make_option("-f", "--force", dest="force", action="store_true",
+                        default=False, help="Force the operation")
+
 _LOCK_OPT = make_option("--lock-retries", default=None,
                         type="int", help=SUPPRESS_HELP)
 
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index c202a3529..a5f5a9c5c 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -1648,6 +1648,17 @@ def _AssembleInstanceDisks(instance, cfg, ignore_secondaries=False):
   return disks_ok, device_info
 
 
+def _StartInstanceDisks(cfg, instance, force):
+  disks_ok, dummy = _AssembleInstanceDisks(instance, cfg,
+                                           ignore_secondaries=force)
+  if not disks_ok:
+    _ShutdownInstanceDisks(instance, cfg)
+    if force is not None and not force:
+      logger.Error("If the message above refers to a secondary node,"
+                   " you can retry the operation using '--force'.")
+    raise errors.OpExecError, ("Disk consistency error")
+
+
 class LUDeactivateInstanceDisks(NoHooksLU):
   """Shutdown an instance's disks.
 
@@ -1776,14 +1787,7 @@ class LUStartupInstance(LogicalUnit):
                                  (instance.name, node_current, memory,
                                   freememory))
 
-    disks_ok, dummy = _AssembleInstanceDisks(instance, self.cfg,
-                                             ignore_secondaries=force)
-    if not disks_ok:
-      _ShutdownInstanceDisks(instance, self.cfg)
-      if not force:
-        logger.Error("If the message above refers to a secondary node,"
-                     " you can retry the operation using '--force'.")
-      raise errors.OpExecError, ("Disk consistency error")
+    _StartInstanceDisks(self.cfg, instance, force)
 
     if not rpc.call_instance_start(node_current, instance, extra_args):
       _ShutdownInstanceDisks(instance, self.cfg)
@@ -1841,6 +1845,70 @@ class LUShutdownInstance(LogicalUnit):
     _ShutdownInstanceDisks(instance, self.cfg)
 
 
+class LUReinstallInstance(LogicalUnit):
+  """Reinstall an instance.
+
+  """
+  HPATH = "instance-reinstall"
+  HTYPE = constants.HTYPE_INSTANCE
+  _OP_REQP = ["instance_name"]
+
+  def BuildHooksEnv(self):
+    """Build hooks env.
+
+    This runs on master, primary and secondary nodes of the instance.
+
+    """
+    env = {
+      "INSTANCE_NAME": self.op.instance_name,
+      "INSTANCE_PRIMARY": self.instance.primary_node,
+      "INSTANCE_SECONDARIES": " ".join(self.instance.secondary_nodes),
+      }
+    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 and is not running.
+
+    """
+    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)
+    if instance.disk_template == constants.DT_DISKLESS:
+      raise errors.OpPrereqError, ("Instance '%s' has no disks" %
+                                   self.op.instance_name)
+    if instance.status != "down":
+      raise errors.OpPrereqError, ("Instance '%s' is marked to be up" %
+                                   self.op.instance_name)
+    remote_info = rpc.call_instance_info(instance.primary_node, instance.name)
+    if remote_info:
+      raise errors.OpPrereqError, ("Instance '%s' is running on the node %s" %
+                                   (self.op.instance_name,
+                                    instance.primary_node))
+    self.instance = instance
+
+  def Exec(self, feedback_fn):
+    """Reinstall the instance.
+
+    """
+    inst = self.instance
+
+    _StartInstanceDisks(self.cfg, inst, None)
+    try:
+      feedback_fn("Running the instance OS create scripts...")
+      if not rpc.call_instance_os_add(inst.primary_node, inst, "sda", "sdb"):
+        raise errors.OpExecError, ("Could not install OS for instance %s "
+                                   "on node %s" %
+                                   (inst.name, inst.primary_node))
+    finally:
+      _ShutdownInstanceDisks(inst, self.cfg)
+
+
 class LURemoveInstance(LogicalUnit):
   """Remove an instance.
 
@@ -2395,7 +2463,7 @@ class LUCreateInstance(LogicalUnit):
     # check primary node
     pnode = self.cfg.GetNodeInfo(self.cfg.ExpandNodeName(self.op.pnode))
     if pnode is None:
-      raise errors.OpPrereqError, ("Primary node '%s' is uknown" %
+      raise errors.OpPrereqError, ("Primary node '%s' is unknown" %
                                    self.op.pnode)
     self.op.pnode = pnode.name
     self.pnode = pnode
@@ -3264,7 +3332,7 @@ class LUExportInstance(LogicalUnit):
     self.dst_node = self.cfg.GetNodeInfo(dst_node_short)
 
     if self.dst_node is None:
-      raise errors.OpPrereqError, ("Destination node '%s' is uknown." %
+      raise errors.OpPrereqError, ("Destination node '%s' is unknown." %
                                    self.op.target_node)
     self.op.target_node = self.dst_node.name
 
diff --git a/lib/mcpu.py b/lib/mcpu.py
index daf79236f..dc83b3f85 100644
--- a/lib/mcpu.py
+++ b/lib/mcpu.py
@@ -63,6 +63,7 @@ class Processor(object):
     opcodes.OpRemoveNode: cmdlib.LURemoveNode,
     # instance lu
     opcodes.OpCreateInstance: cmdlib.LUCreateInstance,
+    opcodes.OpReinstallInstance: cmdlib.LUReinstallInstance,
     opcodes.OpRemoveInstance: cmdlib.LURemoveInstance,
     opcodes.OpActivateInstanceDisks: cmdlib.LUActivateInstanceDisks,
     opcodes.OpShutdownInstance: cmdlib.LUShutdownInstance,
diff --git a/lib/opcodes.py b/lib/opcodes.py
index a54bb4320..dd1d7a8d8 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -139,6 +139,12 @@ class OpCreateInstance(OpCode):
                "wait_for_sync"]
 
 
+class OpReinstallInstance(OpCode):
+  """Reinstall an instance."""
+  OP_ID = "OP_INSTANCE_REINSTALL"
+  __slots__ = ["instance_name"]
+
+
 class OpRemoveInstance(OpCode):
   """Remove an instance."""
   OP_ID = "OP_INSTANCE_REMOVE"
diff --git a/scripts/gnt-backup b/scripts/gnt-backup
index e185473d4..95734c5d7 100755
--- a/scripts/gnt-backup
+++ b/scripts/gnt-backup
@@ -100,8 +100,6 @@ def ImportInstance(opts, args):
 # options used in more than one cmd
 node_opt = make_option("-n", "--node", dest="node", help="Target node",
                        metavar="<node>")
-force_opt = make_option("-f", "--force", dest="force", action="store_true",
-                        default=False, help="Force the operation")
 
 # this is defined separately due to readability only
 import_opts = [
@@ -143,7 +141,7 @@ commands = {
             ],
            "", "Lists instance exports available in the ganeti cluster"),
   'export': (ExportInstance, ARGS_ONE,
-             [node_opt, DEBUG_OPT, force_opt,
+             [node_opt, DEBUG_OPT, FORCE_OPT,
               make_option("","--noshutdown", dest="shutdown",
                           action="store_false", default=True,
                           help="Don't shutdown the instance (unsafe)"), ],
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 27c44ac05..e9dbc522e 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -22,7 +22,6 @@
 import sys
 import os
 from optparse import make_option
-import textwrap
 from cStringIO import StringIO
 
 from ganeti.cli import *
@@ -96,6 +95,28 @@ def AddInstance(opts, args):
   return 0
 
 
+def ReinstallInstance(opts, args):
+  """Reinstall an instance.
+
+  Args:
+    opts - class with options as members
+    args - list containing a single element, the instance name
+
+  """
+  instance_name = args[0]
+
+  if not opts.force:
+    usertext = ("This will reinstall the instance %s and remove "
+                "all data. Continue?") % instance_name
+    if not opts._ask_user(usertext):
+      return 1
+
+  op = opcodes.OpReinstallInstance(instance_name=instance_name)
+  SubmitOpCode(op)
+
+  return 0
+
+
 def RemoveInstance(opts, args):
   """Remove an instance.
 
@@ -244,7 +265,6 @@ def FailoverInstance(opts, args):
     usertext = ("Failover will happen to image %s."
                 " This requires a shutdown of the instance. Continue?" %
                 (instance_name,))
-    usertext = textwrap.fill(usertext)
     if not opts._ask_user(usertext):
       return 1
 
@@ -400,8 +420,6 @@ def SetInstanceParms(opts, args):
 # options used in more than one cmd
 node_opt = make_option("-n", "--node", dest="node", help="Target node",
                        metavar="<node>")
-force_opt = make_option("-f", "--force", dest="force", action="store_true",
-                        default=False, help="Force the operation")
 
 # this is defined separately due to readability only
 add_opts = [
@@ -448,7 +466,7 @@ commands = {
               "<instance>",
               "Opens a console on the specified instance"),
   'failover': (FailoverInstance, ARGS_ONE,
-               [DEBUG_OPT, force_opt,
+               [DEBUG_OPT, FORCE_OPT,
                 make_option("--ignore-consistency", dest="ignore_consistency",
                             action="store_true", default=False,
                             help="Ignore the consistency of the disks on"
@@ -462,7 +480,9 @@ commands = {
   'list': (ListInstances, ARGS_NONE,
            [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
            "", "Lists the instances and their status"),
-  'remove': (RemoveInstance, ARGS_ONE, [DEBUG_OPT, force_opt],
+  'reinstall': (ReinstallInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT],
+                "[-f] <instance>", "Reinstall the instance"),
+  'remove': (RemoveInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT],
              "[-f] <instance>", "Shuts down the instance and removes it"),
   'remove-mirror': (RemoveMDDRBDComponent, ARGS_ONE,
                    [DEBUG_OPT, node_opt,
@@ -484,9 +504,8 @@ commands = {
                                        " change the secondary)"))],
                     "[-n NODE] <instance>",
                     "Replaces all disks for the instance"),
-
   'modify': (SetInstanceParms, ARGS_ONE,
-             [DEBUG_OPT, force_opt,
+             [DEBUG_OPT, FORCE_OPT,
               cli_option("-m", "--memory", dest="mem",
                          help="Memory size",
                          default=None, type="unit", metavar="<mem>"),
@@ -504,7 +523,7 @@ commands = {
   'shutdown': (ShutdownInstance, ARGS_ONE, [DEBUG_OPT],
                "<instance>", "Stops an instance"),
   'startup': (StartupInstance, ARGS_ONE,
-              [DEBUG_OPT, force_opt,
+              [DEBUG_OPT, FORCE_OPT,
                make_option("-e", "--extra", dest="extra_args",
                            help="Extra arguments for the instance's kernel",
                            default=None, type="string", metavar="<PARAMS>"),
-- 
GitLab