Commit d5fe5fa9 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

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: default avatarMichael Hanselmann <>
Reviewed-by: default avatarIustin Pop <>
parent 7b8ba235
......@@ -95,6 +95,7 @@
......@@ -332,6 +332,7 @@ server_PYTHON = \
pytools_PYTHON = \
lib/tools/ \
lib/tools/ \
lib/tools/ \
lib/tools/ \
......@@ -617,6 +618,7 @@ PYTHON_BOOTSTRAP_SBIN = \
tools/ensure-dirs \
tools/node-cleanup \
tools/node-daemon-setup \
......@@ -720,7 +722,11 @@ dist_tools_SCRIPTS = \
tools/master-ip-setup \
nodist_tools_python_scripts = \
nodist_tools_SCRIPTS = \
$(nodist_tools_python_scripts) \
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 =
tools/node-daemon-setup: MODULE =
tools/prepare-node-join: MODULE =
tools/node-cleanup: MODULE =
$(HS_BUILT_TEST_HELPERS): TESTROLE = $(patsubst htest/%,%,$@)
$(PYTHON_BOOTSTRAP): Makefile | stamp-directories
......@@ -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
# 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
# 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]",
parser.add_option("--no-backup", dest="backup", default=True,
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)
# 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),
clean_files.extend(map(lambda s: (s, True), pathutils.ALL_CERT_FILES))
clean_files.extend(map(lambda s: (s, False),
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"Stopping daemons")
result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop-all"],
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:"Backing up %s", filename)
utils.CreateBackup(filename)"Removing %s", filename)
utils.RemoveFile(filename)"Node successfully cleaned")
except Exception, err: # pylint: disable=W0703
logging.debug("Caught unhandled exception", exc_info=True)
(retcode, message) = cli.FormatError(err)
return retcode
return constants.EXIT_SUCCESS
......@@ -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.
# gnt-node add
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment