From d5fe5fa91bf6e2f152ac348bc29805d5c064f0b6 Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Wed, 5 Dec 2012 16:02:11 +0100 Subject: [PATCH] Add tool to clean up node Sometimes a node is not removed properly from a cluster (especially during development). This new tool stops all daemons and removes (after making copies) the most critical files. Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- .gitignore | 1 + Makefile.am | 8 +++ NEWS | 4 ++ lib/tools/node_cleanup.py | 119 ++++++++++++++++++++++++++++++++++++++ man/gnt-node.rst | 4 ++ 5 files changed, 136 insertions(+) create mode 100644 lib/tools/node_cleanup.py diff --git a/.gitignore b/.gitignore index 3a655148c..e9b940489 100644 --- a/.gitignore +++ b/.gitignore @@ -95,6 +95,7 @@ /tools/kvm-ifup /tools/ensure-dirs /tools/vcluster-setup +/tools/node-cleanup /tools/node-daemon-setup /tools/prepare-node-join diff --git a/Makefile.am b/Makefile.am index 67f469fd4..6c2275bd9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -332,6 +332,7 @@ server_PYTHON = \ pytools_PYTHON = \ lib/tools/__init__.py \ lib/tools/ensure_dirs.py \ + lib/tools/node_cleanup.py \ lib/tools/node_daemon_setup.py \ lib/tools/prepare_node_join.py @@ -617,6 +618,7 @@ PYTHON_BOOTSTRAP_SBIN = \ PYTHON_BOOTSTRAP = \ $(PYTHON_BOOTSTRAP_SBIN) \ tools/ensure-dirs \ + tools/node-cleanup \ tools/node-daemon-setup \ tools/prepare-node-join @@ -720,7 +722,11 @@ dist_tools_SCRIPTS = \ tools/master-ip-setup \ tools/xen-console-wrapper +nodist_tools_python_scripts = \ + tools/node-cleanup + nodist_tools_SCRIPTS = \ + $(nodist_tools_python_scripts) \ tools/vcluster-setup pkglib_python_scripts = \ @@ -1034,6 +1040,7 @@ all_python_code = \ $(python_scripts) \ $(pkglib_python_scripts) \ $(nodist_pkglib_python_scripts) \ + $(nodist_tools_python_scripts) \ $(python_tests) \ $(pkgpython_PYTHON) \ $(client_PYTHON) \ @@ -1379,6 +1386,7 @@ scripts/%: MODULE = ganeti.client.$(subst -,_,$(notdir $@)) tools/ensure-dirs: MODULE = ganeti.tools.ensure_dirs tools/node-daemon-setup: MODULE = ganeti.tools.node_daemon_setup tools/prepare-node-join: MODULE = ganeti.tools.prepare_node_join +tools/node-cleanup: MODULE = ganeti.tools.node_cleanup $(HS_BUILT_TEST_HELPERS): TESTROLE = $(patsubst htest/%,%,$@) $(PYTHON_BOOTSTRAP): Makefile | stamp-directories diff --git a/NEWS b/NEWS index 0e4fa6607..5f0728475 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,10 @@ Version 2.7.0 beta1 for RAPI users. It allows granting permissions to query for information to a specific user without giving :pyeval:`rapi.RAPI_ACCESS_WRITE` permissions. +- A new tool named ``node-cleanup`` has been added. It cleans remains of + a cluster from a machine by stopping all daemons, removing + certificates and ssconf files. Unless the ``--no-backup`` option is + given, copies of the certificates are made. Version 2.6.1 diff --git a/lib/tools/node_cleanup.py b/lib/tools/node_cleanup.py new file mode 100644 index 000000000..f4aa24565 --- /dev/null +++ b/lib/tools/node_cleanup.py @@ -0,0 +1,119 @@ +# +# + +# Copyright (C) 2012 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +"""Script to configure the node daemon. + +""" + +import os +import os.path +import optparse +import sys +import logging + +from ganeti import cli +from ganeti import constants +from ganeti import pathutils +from ganeti import ssconf +from ganeti import utils + + +def ParseOptions(): + """Parses the options passed to the program. + + @return: Options and arguments + + """ + parser = optparse.OptionParser(usage="%prog [--no-backup]", + prog=os.path.basename(sys.argv[0])) + parser.add_option(cli.DEBUG_OPT) + parser.add_option(cli.VERBOSE_OPT) + parser.add_option(cli.YES_DOIT_OPT) + parser.add_option("--no-backup", dest="backup", default=True, + action="store_false", + help="Whether to create backup copies of deleted files") + + (opts, args) = parser.parse_args() + + return VerifyOptions(parser, opts, args) + + +def VerifyOptions(parser, opts, args): + """Verifies options and arguments for correctness. + + """ + if args: + parser.error("No arguments are expected") + + return opts + + +def Main(): + """Main routine. + + """ + opts = ParseOptions() + + utils.SetupToolLogging(opts.debug, opts.verbose) + + try: + # List of files to delete. Contains tuples consisting of the absolute path + # and a boolean denoting whether a backup copy should be created before + # deleting. + clean_files = [ + (pathutils.CONFD_HMAC_KEY, True), + (pathutils.CLUSTER_CONF_FILE, True), + (pathutils.CLUSTER_DOMAIN_SECRET_FILE, True), + ] + clean_files.extend(map(lambda s: (s, True), pathutils.ALL_CERT_FILES)) + clean_files.extend(map(lambda s: (s, False), + ssconf.SimpleStore().GetFileList())) + + if not opts.yes_do_it: + cli.ToStderr("Cleaning a node is irreversible. If you really want to" + " clean this node, supply the --yes-do-it option.") + return constants.EXIT_FAILURE + + logging.info("Stopping daemons") + result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop-all"], + interactive=True) + if result.failed: + raise Exception("Could not stop daemons, command '%s' failed: %s" % + (result.cmd, result.fail_reason)) + + for (filename, backup) in clean_files: + if os.path.exists(filename): + if opts.backup and backup: + logging.info("Backing up %s", filename) + utils.CreateBackup(filename) + + logging.info("Removing %s", filename) + utils.RemoveFile(filename) + + logging.info("Node successfully cleaned") + except Exception, err: # pylint: disable=W0703 + logging.debug("Caught unhandled exception", exc_info=True) + + (retcode, message) = cli.FormatError(err) + logging.error(message) + + return retcode + else: + return constants.EXIT_SUCCESS diff --git a/man/gnt-node.rst b/man/gnt-node.rst index d3c405227..fc423b54b 100644 --- a/man/gnt-node.rst +++ b/man/gnt-node.rst @@ -67,6 +67,10 @@ command fails at a later stage, it doesn't undo such changes. This should not be a problem, as a successful run of ``gnt-node add`` will bring everything back in sync. +If the node was previously part of another cluster and still has daemons +running, the ``node-cleanup`` tool can be run on the machine to be added +to clean remains of the previous cluster from the node. + Example:: # gnt-node add node5.example.com -- GitLab