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:
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)
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"
from ganeti import cli
from ganeti import bootstrap
from ganeti import config
+from ganeti import netutils
options = None
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.
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")
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()
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)