Commit 011974df authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

cfgupgrade: Check master name, clarify question



- Check hostname and abort if it doesn't match contents of
  “ssconf_master_node”, can be overridden using “--ignore-hostname”
  parameter.
- Clarify confirmation question and don't mention instances anymore.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent e8deef56
......@@ -32,13 +32,17 @@ from ganeti import constants
from ganeti import utils
from ganeti import errors
from ganeti import serializer
from ganeti import netutils
import testutils
def _RunUpgrade(path, dry_run, no_verify):
def _RunUpgrade(path, dry_run, no_verify, ignore_hostname=True):
cmd = [sys.executable, "%s/tools/cfgupgrade" % testutils.GetSourceDir(),
"--debug", "--force", "--path=%s" % path]
if ignore_hostname:
cmd.append("--ignore-hostname")
if dry_run:
cmd.append("--dry-run")
if no_verify:
......@@ -60,6 +64,7 @@ class TestCfgupgrade(unittest.TestCase):
self.known_hosts_path = utils.PathJoin(self.tmpdir, "known_hosts")
self.confd_hmac_path = utils.PathJoin(self.tmpdir, "hmac.key")
self.cds_path = utils.PathJoin(self.tmpdir, "cluster-domain-secret")
self.ss_master_node_path = utils.PathJoin(self.tmpdir, "ssconf_master_node")
def tearDown(self):
shutil.rmtree(self.tmpdir)
......@@ -70,12 +75,41 @@ class TestCfgupgrade(unittest.TestCase):
def _CreateValidConfigDir(self):
utils.WriteFile(self.noded_cert_path, data="")
utils.WriteFile(self.known_hosts_path, data="")
utils.WriteFile(self.ss_master_node_path,
data="node.has.another.name.example.net")
def testNoConfigDir(self):
self.assertFalse(utils.ListVisibleFiles(self.tmpdir))
self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True)
self.assertRaises(Exception, _RunUpgrade, self.tmpdir, True, True)
def testWrongHostname(self):
self._CreateValidConfigDir()
utils.WriteFile(self.config_path, data=serializer.DumpJson({
"version": constants.CONFIG_VERSION,
"cluster": {},
}))
hostname = netutils.GetHostname().name
assert hostname != utils.ReadOneLineFile(self.ss_master_node_path)
self.assertRaises(Exception, _RunUpgrade, self.tmpdir, False, True,
ignore_hostname=False)
def testCorrectHostname(self):
self._CreateValidConfigDir()
utils.WriteFile(self.config_path, data=serializer.DumpJson({
"version": constants.CONFIG_VERSION,
"cluster": {},
}))
utils.WriteFile(self.ss_master_node_path,
data="%s\n" % netutils.GetHostname().name)
_RunUpgrade(self.tmpdir, False, True, ignore_hostname=False)
def testInconsistentConfig(self):
self._CreateValidConfigDir()
# There should be no "config_version"
......
......@@ -39,6 +39,7 @@ from ganeti import utils
from ganeti import cli
from ganeti import bootstrap
from ganeti import config
from ganeti import netutils
options = None
......@@ -63,13 +64,31 @@ def SetupLogging():
elif options.verbose:
stderr_handler.setLevel(logging.INFO)
else:
stderr_handler.setLevel(logging.CRITICAL)
stderr_handler.setLevel(logging.WARNING)
root_logger = logging.getLogger("")
root_logger.setLevel(logging.NOTSET)
root_logger.addHandler(stderr_handler)
def CheckHostname(path):
"""Ensures hostname matches ssconf value.
@param path: Path to ssconf file
"""
ssconf_master_node = utils.ReadOneLineFile(path)
hostname = netutils.GetHostname().name
if ssconf_master_node == hostname:
return True
logging.warning("Warning: ssconf says master node is '%s', but this"
" machine's name is '%s'; this tool must be run on"
" the master node", ssconf_master_node, hostname)
return False
def main():
"""Main program.
......@@ -87,6 +106,9 @@ def main():
parser.add_option(cli.FORCE_OPT)
parser.add_option(cli.DEBUG_OPT)
parser.add_option(cli.VERBOSE_OPT)
parser.add_option("--ignore-hostname", dest="ignore_hostname",
action="store_true", default=False,
help="Don't abort if hostname doesn't match")
parser.add_option('--path', help="Convert configuration in this"
" directory instead of '%s'" % constants.DATA_DIR,
default=constants.DATA_DIR, dest="data_dir")
......@@ -104,6 +126,7 @@ def main():
options.RAPI_CERT_FILE = options.data_dir + "/rapi.pem"
options.CONFD_HMAC_KEY = options.data_dir + "/hmac.key"
options.CDS_FILE = options.data_dir + "/cluster-domain-secret"
options.SSCONF_MASTER_NODE = options.data_dir + "/ssconf_master_node"
SetupLogging()
......@@ -111,9 +134,16 @@ def main():
if args:
raise Error("No arguments expected")
# Check master name
if not (CheckHostname(options.SSCONF_MASTER_NODE) or options.ignore_hostname):
logging.error("Aborting due to hostname mismatch")
sys.exit(constants.EXIT_FAILURE)
if not options.force:
usertext = ("%s MUST be run on the master node. Is this the master"
" node and are ALL instances down?" % program)
usertext = ("Please make sure you have read the upgrade notes for"
" Ganeti %s (available in the UPGRADE file and included"
" in other documentation formats). Continue with upgrading"
" configuration?" % constants.RELEASE_VERSION)
if not cli.AskUser(usertext):
sys.exit(constants.EXIT_FAILURE)
......
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