From 8d8d650c475c0b1882433410e71eb9a0ee52b6bd Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Fri, 29 Jan 2010 18:44:42 +0100 Subject: [PATCH] Add command line options for instance removal on export Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/cli.py | 14 ++++++++++++++ lib/objects.py | 1 + man/gnt-backup.sgml | 8 ++++++++ qa/ganeti-qa.py | 13 +++++++++++++ qa/qa_instance.py | 10 ++++++++++ scripts/gnt-backup | 11 +++++++++-- 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/cli.py b/lib/cli.py index 14be846b6..3c5e97a40 100644 --- a/lib/cli.py +++ b/lib/cli.py @@ -70,6 +70,7 @@ __all__ = [ "IALLOCATOR_OPT", "IGNORE_CONSIST_OPT", "IGNORE_FAILURES_OPT", + "IGNORE_REMOVE_FAILURES_OPT", "IGNORE_SECONDARIES_OPT", "IGNORE_SIZE_OPT", "MAC_PREFIX_OPT", @@ -101,6 +102,7 @@ __all__ = [ "OS_SIZE_OPT", "READD_OPT", "REBOOT_TYPE_OPT", + "REMOVE_INSTANCE_OPT", "SECONDARY_IP_OPT", "SELECT_OS_OPT", "SEP_OPT", @@ -684,6 +686,18 @@ IGNORE_FAILURES_OPT = cli_option("--ignore-failures", dest="ignore_failures", " configuration even if there are failures" " during the removal process") +IGNORE_REMOVE_FAILURES_OPT = cli_option("--ignore-remove-failures", + dest="ignore_remove_failures", + action="store_true", default=False, + help="Remove the instance from the" + " cluster configuration even if there" + " are failures during the removal" + " process") + +REMOVE_INSTANCE_OPT = cli_option("--remove-instance", dest="remove_instance", + action="store_true", default=False, + help="Remove the instance from the cluster") + NEW_SECONDARY_OPT = cli_option("-n", "--new-secondary", dest="dst_node", help="Specifies the new secondary node", metavar="NODE", default=None, diff --git a/lib/objects.py b/lib/objects.py index 76ca042c4..81cde182d 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -48,6 +48,7 @@ __all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance", _TIMESTAMPS = ["ctime", "mtime"] _UUID = ["uuid"] + def FillDict(defaults_dict, custom_dict, skip_keys=None): """Basic function to apply settings on top a default dict. diff --git a/man/gnt-backup.sgml b/man/gnt-backup.sgml index d9c1fe74b..ff6c3cee9 100644 --- a/man/gnt-backup.sgml +++ b/man/gnt-backup.sgml @@ -65,6 +65,8 @@ <arg choice="req">-n <replaceable>node</replaceable></arg> <arg>--shutdown-timeout=<replaceable>N</replaceable></arg> <arg>--noshutdown</arg> + <arg>--remove-instance</arg> + <arg>--ignore-remove-failures</arg> <arg choice="req"><replaceable>instance</replaceable></arg> </cmdsynopsis> @@ -91,6 +93,12 @@ in the exported dump. </para> + <para> + The <option>--remove</option> option can be used to remove the + instance after it was exported. This is useful to make one last + backup before removing the instance. + </para> + <para> The exit code of the command is 0 if all disks were backed up successfully, 1 if no data was backed up or if the diff --git a/qa/ganeti-qa.py b/qa/ganeti-qa.py index 5c399e72c..990418538 100755 --- a/qa/ganeti-qa.py +++ b/qa/ganeti-qa.py @@ -169,6 +169,7 @@ def RunCommonInstanceTests(instance): if qa_rapi.Enabled(): RunTest(qa_rapi.TestInstance, instance) + def RunExportImportTests(instance, pnode): """Tries to export and import the instance. @@ -312,6 +313,18 @@ def main(): finally: qa_config.ReleaseNode(snode) + if (qa_config.TestEnabled('instance-add-plain-disk') and + qa_config.TestEnabled("instance-export")): + instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, pnode) + expnode = qa_config.AcquireNode(exclude=pnode) + try: + RunTest(qa_instance.TestInstanceExportWithRemove, instance, expnode) + RunTest(qa_instance.TestBackupList, expnode) + finally: + qa_config.ReleaseNode(expnode) + del expnode + del instance + finally: qa_config.ReleaseNode(pnode) diff --git a/qa/qa_instance.py b/qa/qa_instance.py index af3afeb6a..b0d9a6574 100644 --- a/qa/qa_instance.py +++ b/qa/qa_instance.py @@ -249,6 +249,16 @@ def TestInstanceExport(instance, node): return qa_utils.ResolveInstanceName(instance) +def TestInstanceExportWithRemove(instance, node): + """gnt-backup export --remove-instance""" + master = qa_config.GetMasterNode() + + cmd = ['gnt-backup', 'export', '-n', node['primary'], "--remove-instance", + instance['name']] + AssertEqual(StartSSH(master['primary'], + utils.ShellQuoteArgs(cmd)).wait(), 0) + + def TestInstanceImport(node, newinst, expnode, name): """gnt-backup import""" master = qa_config.GetMasterNode() diff --git a/scripts/gnt-backup b/scripts/gnt-backup index fd04a9295..fb1b767cf 100755 --- a/scripts/gnt-backup +++ b/scripts/gnt-backup @@ -71,10 +71,14 @@ def ExportInstance(opts, args): @return: the desired exit code """ + ignore_remove_failures = opts.ignore_remove_failures + op = opcodes.OpExportInstance(instance_name=args[0], target_node=opts.node, shutdown=opts.shutdown, - shutdown_timeout=opts.shutdown_timeout) + shutdown_timeout=opts.shutdown_timeout, + remove_instance=opts.remove_instance, + ignore_remove_failures=ignore_remove_failures) fin_resu, dlist = SubmitOpCode(op) if not isinstance(dlist, list): @@ -97,6 +101,7 @@ def ExportInstance(opts, args): rcode = 1 return rcode + def ImportInstance(opts, args): """Add an instance to the cluster. @@ -144,6 +149,7 @@ import_opts = [ SUBMIT_OPT, ] + commands = { 'list': ( PrintExportList, ARGS_NONE, @@ -151,7 +157,8 @@ commands = { "", "Lists instance exports available in the ganeti cluster"), 'export': ( ExportInstance, ARGS_ONE_INSTANCE, - [FORCE_OPT, SINGLE_NODE_OPT, NOSHUTDOWN_OPT, SHUTDOWN_TIMEOUT_OPT], + [FORCE_OPT, SINGLE_NODE_OPT, NOSHUTDOWN_OPT, SHUTDOWN_TIMEOUT_OPT, + REMOVE_INSTANCE_OPT, IGNORE_REMOVE_FAILURES_OPT], "-n <target_node> [opts...] <name>", "Exports an instance to an image"), 'import': ( -- GitLab