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(self.opts.conf_dir % "Not a directory: %s")

    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..n-1} to 2.n
    elif config_major == 2 and config_minor in range(0, TARGET_MINOR):
      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()
dataset/ETHPy150Open ganeti/ganeti/lib/tools/cfgupgrade.py/CfgUpgrade.Run/swapped operands of `%`