def testConfigVersion(self): self.failUnless(constants.CONFIG_MAJOR >= 0 and constants.CONFIG_MAJOR <= 99) self.failUnless(constants.CONFIG_MINOR >= 0 and constants.CONFIG_MINOR <= 99) self.failUnless(constants.CONFIG_REVISION >= 0 and constants.CONFIG_REVISION <= 9999) self.failUnless(constants.CONFIG_VERSION >= 0 and constants.CONFIG_VERSION <= 99999999) self.failUnless(version.BuildVersion(0, 0, 0) == 0) self.failUnless(version.BuildVersion(10, 10, 1010) == 10101010) self.failUnless(version.BuildVersion(12, 34, 5678) == 12345678) self.failUnless(version.BuildVersion(99, 99, 9999) == 99999999) self.failUnless(version.SplitVersion(00000000) == (0, 0, 0)) self.failUnless(version.SplitVersion(10101010) == (10, 10, 1010)) self.failUnless(version.SplitVersion(12345678) == (12, 34, 5678)) self.failUnless(version.SplitVersion(99999999) == (99, 99, 9999)) self.failUnless(version.SplitVersion(constants.CONFIG_VERSION) == (constants.CONFIG_MAJOR, constants.CONFIG_MINOR, constants.CONFIG_REVISION))
def CheckMasterd(options, args): """Initial checks whether to run or exit with a failure. """ if args: # masterd doesn't take any arguments print >> sys.stderr, ("Usage: %s [-f] [-d]" % sys.argv[0]) sys.exit(constants.EXIT_FAILURE) ssconf.CheckMaster(options.debug) try: options.uid = pwd.getpwnam(constants.MASTERD_USER).pw_uid options.gid = grp.getgrnam(constants.DAEMONS_GROUP).gr_gid except KeyError: print >> sys.stderr, ( "User or group not existing on system: %s:%s" % (constants.MASTERD_USER, constants.DAEMONS_GROUP)) sys.exit(constants.EXIT_FAILURE) # Determine static runtime architecture information runtime.InitArchInfo() # Check the configuration is sane before anything else try: livelock = utils.livelock.LiveLock("masterd_check") config.GetConfig(None, livelock) except errors.ConfigVersionMismatch, err: v1 = "%s.%s.%s" % version.SplitVersion(err.args[0]) v2 = "%s.%s.%s" % version.SplitVersion(err.args[1]) print >> sys.stderr, \ ("Configuration version mismatch. The current Ganeti software" " expects version %s, but the on-disk configuration file has" " version %s. This is likely the result of upgrading the" " software without running the upgrade procedure. Please contact" " your cluster administrator or complete the upgrade using the" " cfgupgrade utility, after reading the upgrade notes." % (v1, v2)) sys.exit(constants.EXIT_FAILURE)
def Run(self): """Main program. """ self._ComposePaths() self.SetupLogging() # Option checking if self.args: raise Error("No arguments expected") if self.opts.downgrade and not self.opts.no_verify: self.opts.no_verify = True # Check master name if not (self.CheckHostname(self.opts.SSCONF_MASTER_NODE) or self.opts.ignore_hostname): logging.error("Aborting due to hostname mismatch") sys.exit(constants.EXIT_FAILURE) self._AskUser() # Check whether it's a Ganeti configuration directory if not (os.path.isfile(self.opts.CONFIG_DATA_PATH) and os.path.isfile(self.opts.SERVER_PEM_PATH) and os.path.isfile(self.opts.KNOWN_HOSTS_PATH)): raise Error(("%s does not seem to be a Ganeti configuration" " directory") % self.opts.data_dir) if not os.path.isdir(self.opts.conf_dir): raise Error("Not a directory: %s" % self.opts.conf_dir) self.config_data = serializer.LoadJson( utils.ReadFile(self.opts.CONFIG_DATA_PATH)) try: config_version = self.config_data["version"] except KeyError: raise Error("Unable to determine configuration version") (config_major, config_minor, config_revision) = \ version.SplitVersion(config_version) logging.info("Found configuration version %s (%d.%d.%d)", config_version, config_major, config_minor, config_revision) if "config_version" in self.config_data["cluster"]: raise Error("Inconsistent configuration: found config_version in" " configuration file") # Downgrade to the previous stable version if self.opts.downgrade: self._Downgrade(config_major, config_minor, config_version, config_revision) # Upgrade from 2.0-2.16 to 3.0 # TODO: handle upgrades from 2.17beta elif config_major == 2 and config_minor in range(0, LAST_V2_MINOR + 1): if config_revision != 0: logging.warning("Config revision is %s, not 0", config_revision) if not self.UpgradeAll(): raise Error("Upgrade failed:\n%s" % '\n'.join(self.errors)) elif config_major == TARGET_MAJOR and config_minor == TARGET_MINOR: logging.info("No changes necessary") else: raise Error( "Configuration version %d.%d.%d not supported by this tool" % (config_major, config_minor, config_revision)) try: logging.info("Writing configuration file to %s", self.opts.CONFIG_DATA_PATH) utils.WriteFile(file_name=self.opts.CONFIG_DATA_PATH, data=serializer.DumpJson(self.config_data), mode=0600, dry_run=self.opts.dry_run, backup=True) if not self.opts.dry_run: # This creates the cluster certificate if it does not exist yet. # In this case, we do not automatically create a client certificate # as well, because if the cluster certificate did not exist before, # no client certificate will exist on any node yet. In this case # all client certificate should be renewed by 'gnt-cluster # renew-crypto --new-node-certificates'. This will be enforced # by a nagging warning in 'gnt-cluster verify'. bootstrap.GenerateClusterCrypto( False, False, False, False, False, False, None, nodecert_file=self.opts.SERVER_PEM_PATH, rapicert_file=self.opts.RAPI_CERT_FILE, spicecert_file=self.opts.SPICE_CERT_FILE, spicecacert_file=self.opts.SPICE_CACERT_FILE, hmackey_file=self.opts.CONFD_HMAC_KEY, cds_file=self.opts.CDS_FILE) except Exception: logging.critical( "Writing configuration failed. It is probably in an" " inconsistent state and needs manual intervention.") raise self._TestLoadingConfigFile()