+from ganeti import errors
+
+
+_SHUTDOWN_CLUSTER = "cluster"
+_SHUTDOWN_NODES_BOTH = "nodes"
+_SHUTDOWN_NODES_PRI = "nodes-pri"
+_SHUTDOWN_NODES_SEC = "nodes-sec"
+_SHUTDOWN_INSTANCES = "instances"
+
+def _ExpandMultiNames(mode, names):
+ """Expand the given names using the passed mode.
+
+ Args:
+ - mode, which can be one of _SHUTDOWN_CLUSTER, _SHUTDOWN_NODES_BOTH,
+ _SHUTDOWN_NODES_PRI, _SHUTDOWN_NODES_SEC or _SHUTDOWN_INSTANCES
+ - names, which is a list of names; for cluster, it must be empty,
+ and for node and instance it must be a list of valid item
+ names (short names are valid as usual, e.g. node1 instead of
+ node1.example.com)
+
+ For _SHUTDOWN_CLUSTER, all instances will be returned. For
+ _SHUTDOWN_NODES_PRI/SEC, all instances having those nodes as
+ primary/secondary will be shutdown. For _SHUTDOWN_NODES_BOTH, all
+ instances having those nodes as either primary or secondary will be
+ returned. For _SHUTDOWN_INSTANCES, the given instances will be
+ returned.
+
+ """
+ if mode == _SHUTDOWN_CLUSTER:
+ if names:
+ raise errors.OpPrereqError("Cluster filter mode takes no arguments")
+ op = opcodes.OpQueryInstances(output_fields=["name"], names=[])
+ idata = SubmitOpCode(op)
+ inames = [row[0] for row in idata]
+
+ elif mode in (_SHUTDOWN_NODES_BOTH,
+ _SHUTDOWN_NODES_PRI,
+ _SHUTDOWN_NODES_SEC):
+ if not names:
+ raise errors.OpPrereqError("No node names passed")
+ op = opcodes.OpQueryNodes(output_fields=["name", "pinst_list",
+ "sinst_list"], names=names)
+ ndata = SubmitOpCode(op)
+ ipri = [row[1] for row in ndata]
+ pri_names = list(itertools.chain(*ipri))
+ isec = [row[2] for row in ndata]
+ sec_names = list(itertools.chain(*isec))
+ if mode == _SHUTDOWN_NODES_BOTH:
+ inames = pri_names + sec_names
+ elif mode == _SHUTDOWN_NODES_PRI:
+ inames = pri_names
+ elif mode == _SHUTDOWN_NODES_SEC:
+ inames = sec_names
+ else:
+ raise errors.ProgrammerError("Unhandled shutdown type")
+
+ elif mode == _SHUTDOWN_INSTANCES:
+ if not names:
+ raise errors.OpPrereqError("No instance names passed")
+ op = opcodes.OpQueryInstances(output_fields=["name"], names=names)
+ idata = SubmitOpCode(op)
+ inames = [row[0] for row in idata]
+
+ else:
+ raise errors.OpPrereqError("Unknown mode '%s'" % mode)
+
+ return inames
+
+
+def _ConfirmOperation(inames, text):
+ """Ask the user to confirm an operation on a list of instances.
+
+ This function is used to request confirmation for doing an operation
+ on a given list of instances.
+
+ The inames argument is what the selection algorithm computed, and
+ the text argument is the operation we should tell the user to
+ confirm (e.g. 'shutdown' or 'startup').
+
+ Returns: boolean depending on user's confirmation.
+
+ """
+ count = len(inames)
+ msg = ("The %s will operate on %d instances.\n"
+ "Do you want to continue?" % (text, count))
+ affected = ("\nAffected instances:\n" +
+ "\n".join([" %s" % name for name in inames]))
+
+ choices = [('y', True, 'Yes, execute the %s' % text),
+ ('n', False, 'No, abort the %s' % text)]
+
+ if count > 20:
+ choices.insert(1, ('v', 'v', 'View the list of affected instances'))
+ ask = msg
+ else:
+ ask = msg + affected
+
+ choice = AskUser(ask, choices)
+ if choice == 'v':
+ choices.pop(1)
+ choice = AskUser(choices, msg + affected)
+ return choice
+
+
+def _TransformPath(user_input):
+ """Transform a user path into a canonical value.
+
+ This function transforms the a path passed as textual information
+ into the constants that the LU code expects.
+
+ """
+ if user_input:
+ if user_input.lower() == "default":
+ result_path = constants.VALUE_DEFAULT
+ elif user_input.lower() == "none":
+ result_path = constants.VALUE_NONE
+ else:
+ if not os.path.isabs(user_input):
+ raise errors.OpPrereqError("Path '%s' is not an absolute filename" %
+ user_input)
+ result_path = user_input
+ else:
+ result_path = constants.VALUE_DEFAULT
+
+ return result_path