Start, stop and reboot have the same code for dealing with
multi-instance handling. This patch moves all that into a single generic
function, and leaves only the building of the specific opcode for the
operation in the individual functions.
---
 Second try, now with less sugar! Err, fewer wrappers.

 scripts/gnt-instance |  143 +++++++++++++++++++++-----------------------------
 1 files changed, 59 insertions(+), 84 deletions(-)

diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 779b948..3ed658e 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -31,7 +31,6 @@ import time
 from cStringIO import StringIO
 
 from ganeti.cli import *
-from ganeti import cli
 from ganeti import opcodes
 from ganeti import constants
 from ganeti import utils
@@ -175,6 +174,36 @@ def _EnsureInstancesExist(client, names):
       raise errors.OpPrereqError("Instance '%s' does not exist" % orig_name)
 
 
+def GenericManyOps(operation, fn):
+  """Generic multi-instance operations.
+
+  The will return a wrapper that processes the options and arguments
+  given, and uses the passed function to build the opcode needed for
+  the specific operation. Thus all the generic loop/confirmation code
+  is abstracted into this function.
+
+  """
+  def realfn(opts, args):
+    if opts.multi_mode is None:
+      opts.multi_mode = _SHUTDOWN_INSTANCES
+    cl = GetClient()
+    inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
+    if not inames:
+      raise errors.OpPrereqError("Selection filter does not match"
+                                 " any instances")
+    multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
+    if not (opts.force_multi or not multi_on
+            or _ConfirmOperation(inames, operation)):
+      return 1
+    jex = JobExecutor(verbose=multi_on, cl=cl)
+    for name in inames:
+      op = fn(name, opts)
+      jex.QueueJob(name, op)
+    jex.WaitOrShow(not opts.submit_only)
+    return 0
+  return realfn
+
+
 def ListInstances(opts, args):
   """List instances and their properties.
 
@@ -729,109 +758,55 @@ def GrowDisk(opts, args):
   return 0
 
 
-def StartupInstance(opts, args):
+def _StartupInstance(name, opts):
   """Startup instances.
 
-  Depending on the options given, this will start one or more
-  instances.
+  This returns the opcode to start an instance, and its decorator will
+  wrap this into a loop starting all desired instances.
 
+  @param name: the name of the instance to act on
   @param opts: the command line options selected by the user
-  @type args: list
-  @param args: the instance or node names based on which we
-      create the final selection (in conjunction with the
-      opts argument)
-  @rtype: int
-  @return: the desired exit code
+  @return: the opcode needed for the operation
 
   """
-  cl = GetClient()
-  if opts.multi_mode is None:
-    opts.multi_mode = _SHUTDOWN_INSTANCES
-  inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
-  if not inames:
-    raise errors.OpPrereqError("Selection filter does not match any instances")
-  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
-  if not (opts.force_multi or not multi_on
-          or _ConfirmOperation(inames, "startup")):
-    return 1
-  jex = cli.JobExecutor(verbose=multi_on, cl=cl)
-  for name in inames:
-    op = opcodes.OpStartupInstance(instance_name=name,
-                                   force=opts.force)
-    # do not add these parameters to the opcode unless they're defined
-    if opts.hvparams:
-      op.hvparams = opts.hvparams
-    if opts.beparams:
-      op.beparams = opts.beparams
-    jex.QueueJob(name, op)
-  jex.WaitOrShow(not opts.submit_only)
-  return 0
+  op = opcodes.OpStartupInstance(instance_name=name,
+                                 force=opts.force)
+  # do not add these parameters to the opcode unless they're defined
+  if opts.hvparams:
+    op.hvparams = opts.hvparams
+  if opts.beparams:
+    op.beparams = opts.beparams
+  return op
 
 
-def RebootInstance(opts, args):
+def _RebootInstance(name, opts):
   """Reboot instance(s).
 
-  Depending on the parameters given, this will reboot one or more
-  instances.
+  This returns the opcode to reboot an instance, and its decorator
+  will wrap this into a loop rebooting all desired instances.
 
+  @param name: the name of the instance to act on
   @param opts: the command line options selected by the user
-  @type args: list
-  @param args: the instance or node names based on which we
-      create the final selection (in conjunction with the
-      opts argument)
-  @rtype: int
-  @return: the desired exit code
+  @return: the opcode needed for the operation
 
   """
-  cl = GetClient()
-  if opts.multi_mode is None:
-    opts.multi_mode = _SHUTDOWN_INSTANCES
-  inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
-  if not inames:
-    raise errors.OpPrereqError("Selection filter does not match any instances")
-  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
-  if not (opts.force_multi or not multi_on
-          or _ConfirmOperation(inames, "reboot")):
-    return 1
-  jex = JobExecutor(verbose=multi_on, cl=cl)
-  for name in inames:
-    op = opcodes.OpRebootInstance(instance_name=name,
+  return opcodes.OpRebootInstance(instance_name=name,
                                   reboot_type=opts.reboot_type,
                                   ignore_secondaries=opts.ignore_secondaries)
-    jex.QueueJob(name, op)
-  jex.WaitOrShow(not opts.submit_only)
-  return 0
 
 
-def ShutdownInstance(opts, args):
+def _ShutdownInstance(name, opts):
   """Shutdown an instance.
 
+  This returns the opcode to shutdown an instance, and its decorator
+  will wrap this into a loop shutting down all desired instances.
+
+  @param name: the name of the instance to act on
   @param opts: the command line options selected by the user
-  @type args: list
-  @param args: the instance or node names based on which we
-      create the final selection (in conjunction with the
-      opts argument)
-  @rtype: int
-  @return: the desired exit code
+  @return: the opcode needed for the operation
 
   """
-  cl = GetClient()
-  if opts.multi_mode is None:
-    opts.multi_mode = _SHUTDOWN_INSTANCES
-  inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
-  if not inames:
-    raise errors.OpPrereqError("Selection filter does not match any instances")
-  multi_on = opts.multi_mode != _SHUTDOWN_INSTANCES or len(inames) > 1
-  if not (opts.force_multi or not multi_on
-          or _ConfirmOperation(inames, "shutdown")):
-    return 1
-
-  jex = cli.JobExecutor(verbose=multi_on, cl=cl)
-  for name in inames:
-    op = opcodes.OpShutdownInstance(instance_name=name)
-    jex.QueueJob(name, op)
-  jex.WaitOrShow(not opts.submit_only)
-  return 0
+  return opcodes.OpShutdownInstance(instance_name=name)
 
 
 def ReplaceDisks(opts, args):
@@ -1445,18 +1420,18 @@ commands = {
     [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT],
     "<instance>", "Alters the parameters of an instance"),
   'shutdown': (
-    ShutdownInstance, [ArgInstance()],
+    GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],
     [m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt,
      m_inst_opt, m_force_multi, SUBMIT_OPT],
     "<instance>", "Stops an instance"),
   'startup': (
-    StartupInstance, [ArgInstance()],
+    GenericManyOps("startup", _StartupInstance), [ArgInstance()],
     [FORCE_OPT, m_force_multi, m_node_opt, m_pri_node_opt,
      m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT, HVOPTS_OPT,
      BACKEND_OPT],
     "<instance>", "Starts an instance"),
   'reboot': (
-    RebootInstance, [ArgInstance()],
+    GenericManyOps("reboot", _RebootInstance), [ArgInstance()],
     [m_force_multi, REBOOT_TYPE_OPT, IGNORE_SECONDARIES_OPT, m_node_opt,
      m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT],
     "<instance>", "Reboots an instance"),
-- 
1.6.3.3

Reply via email to