From 55efe6dabe48e5c37dc1ff6099e0bb8afde7a468 Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Fri, 22 May 2009 14:27:46 +0200
Subject: [PATCH] Convert instance reinstall to multi instance model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch converts β€˜gnt-instance reinstall’ from single-instance to
multi-instance model; since this is dangerours, it's required to pass
β€œ--force --force-multiple” to skip the confirmation.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Guido Trotter <ultrotter@google.com>
---
 man/gnt-instance.sgml | 36 ++++++++++++++++++++++---------
 scripts/gnt-instance  | 50 +++++++++++++++++++++++++++++++------------
 2 files changed, 62 insertions(+), 24 deletions(-)

diff --git a/man/gnt-instance.sgml b/man/gnt-instance.sgml
index 8ca11dec8..2d9d44fb0 100644
--- a/man/gnt-instance.sgml
+++ b/man/gnt-instance.sgml
@@ -1229,31 +1229,47 @@ instance5: 11225
         <cmdsynopsis>
           <command>reinstall</command>
           <arg choice="opt">-o <replaceable>os-type</replaceable></arg>
-          <arg choice="opt">-f <replaceable>force</replaceable></arg>
           <arg>--select-os</arg>
+          <arg choice="opt">-f <replaceable>force</replaceable></arg>
+          <arg>--force-multiple</arg>
+          <sbr>
+          <group choice="opt">
+            <arg>--instance</arg>
+            <arg>--node</arg>
+            <arg>--primary</arg>
+            <arg>--secondary</arg>
+            <arg>--all</arg>
+          </group>
           <arg>--submit</arg>
-          <arg choice="req"><replaceable>instance</replaceable></arg>
+          <arg choice="opt" rep="repeat"><replaceable>instance</replaceable></arg>
         </cmdsynopsis>
 
         <para>
-          Reinstalls the operating system on the given instance. The
-          instance must be stopped when running this command. If the
+          Reinstalls the operating system on the given instance(s). The
+          instance(s) must be stopped when running this command. If the
           <option>--os-type</option> is specified, the operating
           system is changed.
         </para>
 
-        <para>
-          Since reinstall is potentially dangerous command, the user
-          will be required to confirm this action, unless the
-          <option>-f</option> flag is passed.
-        </para>
-
         <para>
           The <option>--select-os</option> option switches to an
           interactive OS reinstall. The user is prompted to select the OS
           template from the list of available OS templates.
         </para>
 
+        <para>
+          Since this is a potentially dangerous command, the user will
+          be required to confirm this action, unless the
+          <option>-f</option> flag is passed. When multiple instances
+          are selected (either by passing multiple arguments or by
+          using the <option>--node</option>,
+          <option>--primary</option>, <option>--secondary</option> or
+          <option>--all</option> options), the user must pass both the
+          <option>--force</option> and
+          <option>--force-multiple</option> options to skip the
+          interactive confirmation.
+        </para>
+
         <para>
           The <option>--submit</option> option is used to send the job to
           the master daemon but not wait for its completion. The job
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 6d1112ad0..3bd8cfe9d 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -116,7 +116,7 @@ def _ExpandMultiNames(mode, names, client=None):
   return inames
 
 
-def _ConfirmOperation(inames, text):
+def _ConfirmOperation(inames, text, extra=""):
   """Ask the user to confirm an operation on a list of instances.
 
   This function is used to request confirmation for doing an operation
@@ -133,8 +133,8 @@ def _ConfirmOperation(inames, text):
 
   """
   count = len(inames)
-  msg = ("The %s will operate on %d instances.\n"
-         "Do you want to continue?" % (text, count))
+  msg = ("The %s will operate on %d instances.\n%s"
+         "Do you want to continue?" % (text, count, extra))
   affected = ("\nAffected instances:\n" +
               "\n".join(["  %s" % name for name in inames]))
 
@@ -505,8 +505,15 @@ def ReinstallInstance(opts, args):
   @return: the desired exit code
 
   """
-  instance_name = args[0]
+  # first, compute the desired name list
+  if opts.multi_mode is None:
+    opts.multi_mode = _SHUTDOWN_INSTANCES
+
+  inames = _ExpandMultiNames(opts.multi_mode, args)
+  if not inames:
+    raise errors.OpPrereqError("Selection filter does not match any instances")
 
+  # second, if requested, ask for an OS
   if opts.select_os is True:
     op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
     result = SubmitOpCode(op)
@@ -528,23 +535,35 @@ def ReinstallInstance(opts, args):
                        choices)
 
     if selected == 'exit':
-      ToStdout("User aborted reinstall, exiting")
+      ToStderr("User aborted reinstall, exiting")
       return 1
 
     os_name = selected
   else:
     os_name = opts.os
 
-  if not opts.force:
-    usertext = ("This will reinstall the instance %s and remove"
-                " all data. Continue?") % instance_name
-    if not AskUser(usertext):
+  # third, get confirmation: multi-reinstall requires --force-multi
+  # *and* --force, single-reinstall just --force
+  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
+  if multi_on:
+    warn_msg = "Note: this will remove *all* data for the below instances!\n"
+    if not ((opts.force_multi and opts.force) or
+            _ConfirmOperation(inames, "reinstall", extra=warn_msg)):
       return 1
+  else:
+    if not opts.force:
+      usertext = ("This will reinstall the instance %s and remove"
+                  " all data. Continue?") % instance_name
+      if not AskUser(usertext):
+        return 1
+
+  jex = JobExecutor(verbose=multi_on)
+  for instance_name in inames:
+    op = opcodes.OpReinstallInstance(instance_name=instance_name,
+                                     os_type=os_name)
+    jex.QueueJob(instance_name, op)
 
-  op = opcodes.OpReinstallInstance(instance_name=instance_name,
-                                   os_type=os_name)
-  SubmitOrSend(op, opts)
-
+  jex.WaitOrShow(not opts.submit_only)
   return 0
 
 
@@ -1372,8 +1391,11 @@ commands = {
            " The default field"
            " list is (in order): %s." % ", ".join(_LIST_DEF_FIELDS),
            ),
-  'reinstall': (ReinstallInstance, ARGS_ONE,
+  'reinstall': (ReinstallInstance, ARGS_ANY,
                 [DEBUG_OPT, FORCE_OPT, os_opt,
+                 m_force_multi,
+                 m_node_opt, m_pri_node_opt, m_sec_node_opt,
+                 m_clust_opt, m_inst_opt,
                  make_option("--select-os", dest="select_os",
                              action="store_true", default=False,
                              help="Interactive OS reinstall, lists available"
-- 
GitLab