X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/07813a9efd0baac14437ebcc9841c66e3131a265..cd098c41522469e462efeb1e157a8718ff7b7809:/scripts/gnt-instance?ds=sidebyside diff --git a/scripts/gnt-instance b/scripts/gnt-instance index ad7f237..6779bac 100755 --- a/scripts/gnt-instance +++ b/scripts/gnt-instance @@ -90,7 +90,7 @@ def _ExpandMultiNames(mode, names, client=None): if not names: raise errors.OpPrereqError("No node names passed") ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"], - True) + False) ipri = [row[1] for row in ndata] pri_names = list(itertools.chain(*ipri)) isec = [row[2] for row in ndata] @@ -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])) @@ -154,29 +154,6 @@ def _ConfirmOperation(inames, text): 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 - - def _EnsureInstancesExist(client, names): """Check for and ensure the given instance names exist. @@ -321,7 +298,7 @@ def AddInstance(opts, args): except ValueError, err: raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err)) nics = [{}] * nic_max - for nidx, ndict in opts.nics.items(): + for nidx, ndict in opts.nics: nidx = int(nidx) nics[nidx] = ndict elif opts.no_nics: @@ -463,6 +440,8 @@ def BatchCreate(opts, args): ToStderr("Can't parse the instance definition file: %s" % str(err)) return 1 + jex = JobExecutor() + # Iterate over the instances and do: # * Populate the specs with default value # * Validate the instance specs @@ -508,7 +487,9 @@ def BatchCreate(opts, args): file_storage_dir=specs['file_storage_dir'], file_driver=specs['file_driver']) - ToStdout("%s: %s", name, cli.SendJob([op])) + jex.QueueJob(name, op) + # we never want to wait, just show the submitted job IDs + jex.WaitOrShow(False) return 0 @@ -524,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) @@ -543,27 +531,39 @@ def ReinstallInstance(opts, args): number = number + 1 choices.append(('x', 'exit', 'Exit gnt-instance reinstall')) - selected = AskUser("Enter OS template name or number (or x to abort):", + selected = AskUser("Enter OS template number (or x to abort):", 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?") % inames[0] + 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 @@ -710,6 +710,11 @@ def StartupInstance(opts, args): 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 @@ -1084,6 +1089,15 @@ def ShowInstanceConfig(opts, args): @return: the desired exit code """ + if not args and not opts.show_all: + ToStderr("No instance selected." + " Please pass in --all if you want to query all instances.\n" + "Note that this can take a long time on a big cluster.") + return 1 + elif args and opts.show_all: + ToStderr("Cannot use --all if you specify instance names.") + return 1 + retcode = 0 op = opcodes.OpQueryInstanceData(instances=args, static=opts.static) result = SubmitOpCode(op) @@ -1360,7 +1374,11 @@ commands = { make_option("-s", "--static", dest="static", action="store_true", default=False, help="Only show configuration data, not runtime data"), - ], "[-s] [...]", + make_option("--all", dest="show_all", + default=False, action="store_true", + help="Show info on all instances on the cluster." + " This can take a long time to run, use wisely."), + ], "[-s] {--all | ...}", "Show information on the specified instance(s)"), 'list': (ListInstances, ARGS_ANY, [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT], @@ -1373,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" @@ -1416,9 +1437,9 @@ commands = { help=("Replace the disk(s) on the secondary" " node (only for the drbd template)")), make_option("--disks", dest="disks", default=None, - help=("Comma-separated list of disks" - " to replace (e.g. sda) (optional," - " defaults to all disks")), + help="Comma-separated list of disks" + " indices to replace (e.g. 0,2) (optional," + " defaults to all disks)"), make_option("-I", "--iallocator", metavar="", help="Select new secondary for the instance" " automatically using the" @@ -1459,8 +1480,14 @@ commands = { m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT, + keyval_option("-H", "--hypervisor", type="keyval", + default={}, dest="hvparams", + help="Temporary hypervisor parameters"), + keyval_option("-B", "--backend", type="keyval", + default={}, dest="beparams", + help="Temporary backend parameters"), ], - "", "Starts an instance"), + "", "Starts an instance"), 'reboot': (RebootInstance, ARGS_ANY, [DEBUG_OPT, m_force_multi,