Start, stop and reboot have the same code for dealing with
multi-instance handling. This patch moves all that into a single
decorator function, and leaves only the building of the specific opcode
for the operation in these functions.
---
 scripts/gnt-instance |  147 ++++++++++++++++++++++----------------------------
 1 files changed, 64 insertions(+), 83 deletions(-)

diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 779b948..69ebca6 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,39 @@ def _EnsureInstancesExist(client, names):
       raise errors.OpPrereqError("Instance '%s' does not exist" % orig_name)
 
 
+def _ManyOpsWrapper(operation):
+  """Wrapper for multi-instance operations.
+
+  The wrapper, given an operation name, will return (another) wrapper
+  that processes the options and arguments given, and uses the wrapped
+  function to build the opcode needed for the specific operation. Thus
+  all the generic loop/confirmation code is abstracted into this
+  function.
+
+  """
+  def wrap(fn):
+    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
+  return wrap
+
+
 def ListInstances(opts, args):
   """List instances and their properties.
 
@@ -729,109 +761,58 @@ def GrowDisk(opts, args):
   return 0
 
 
-def StartupInstance(opts, args):
+...@_manyopswrapper("startup")
+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
-
-
-def RebootInstance(opts, args):
+  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
+
+
+...@_manyopswrapper("reboot")
+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):
+...@_manyopswrapper("shutdown")
+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):
-- 
1.6.3.3

Reply via email to