Commit a421fdeb authored by Iustin Pop's avatar Iustin Pop

First run at cfgupgrade for 2.0 upgrades

This patch makes cfgupgrade work on empty cluster (i.e. no instances),
up to a point that the config file can be converted from 1.2 to 2.0.
This is not yet complete, though.

Reviewed-by: ultrotter
parent 75615bd3
# Copyright (C) 2007, 2008 Google Inc.
# Copyright (C) 2007, 2008, 2009 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
......@@ -21,8 +21,8 @@
"""Tool to upgrade the configuration file.
This code handles only the types supported by simplejson. As an example, "set"
is a "list".
This code handles only the types supported by simplejson. As an
example, 'set' is a 'list'.
......@@ -39,6 +39,7 @@ from ganeti import constants
from ganeti import serializer
from ganeti import utils
from ganeti import cli
from ganeti import bootstrap
# We need to keep filenames locally because they might be renamed between
......@@ -61,6 +62,13 @@ class Error(Exception):
def SsconfName(key):
"""Returns the file name of an (old) ssconf key.
return "%s/ssconf_%s" % (constants.DATA_DIR, key)
def ReadFile(file_name, default=NoDefault):
"""Reads a file.
......@@ -108,6 +116,63 @@ def SetupLogging():
def Cluster12To20(cluster):
"""Upgrades the cluster object from 1.2 to 2.0.
""""Upgrading the cluster object")
# Upgrade the configuration version
if 'config_version' in cluster:
del cluster['config_version']
# Add old ssconf keys back to config" - importing ssconf keys")
for key in ('master_node', 'master_ip', 'master_netdev', 'cluster_name'):
if key not in cluster:
cluster[key] = ReadFile(SsconfName(key)).strip()
if 'default_hypervisor' not in cluster:
old_hyp = ReadFile(SsconfName('hypervisor')).strip()
if old_hyp == "xen-3.0":
hyp = "xen-pvm"
elif old_hyp == "xen-hvm-3.1":
hyp = "xen-hvm"
elif old_hyp == "fake":
hyp = "fake"
raise Error("Unknown old hypervisor name '%s'" % old_hyp)"Setting the default and enabled hypervisor")
cluster['default_hypervisor'] = hyp
cluster['enabled_hypervisors'] = [hyp]
# hv/be params
if 'hvparams' not in cluster:" - adding hvparams")
cluster['hvparams'] = constants.HVC_DEFAULTS
if 'beparams' not in cluster:" - adding beparams")
cluster['beparams'] = {constants.BEGR_DEFAULT: constants.BEC_DEFAULTS}
# file storage
if 'file_storage_dir' not in cluster:
cluster['file_storage_dir'] = constants.DEFAULT_FILE_STORAGE_DIR
def Node12To20(node):
"""Upgrades a node from 1.2 to 2.0.
""""Upgrading node %s" % node['name'])
if 'serial_no' not in node:
node['serial_no'] = 1
if 'master_candidate' not in node:
node['master_candidate'] = True
for key in 'offline', 'drained':
if key not in node:
node[key] = False
def main():
"""Main program.
......@@ -124,7 +189,7 @@ def main():
" output file")
parser.add_option('--verbose', dest='verbose',
parser.add_option('-v', '--verbose', dest='verbose',
help="Verbose output")
(options, args) = parser.parse_args()
......@@ -136,8 +201,8 @@ def main():
raise Error("No arguments expected")
if not options.force:
usertext = ("%s MUST run on the master node. Is this the master"
" node?" % program)
usertext = ("%s MUST be run on the master node. Is this the master"
" node and are ALL instances down?" % program)
if not cli.AskUser(usertext):
......@@ -157,11 +222,17 @@ def main():
if config_version == "1.2":"Found a Ganeti 1.2 configuration")
old_config_version = config_data["cluster"].get("config_version", None)
cluster = config_data["cluster"]
old_config_version = cluster.get("config_version", None)"Found old configuration version %s", old_config_version)
if old_config_version not in (3, ):
raise Error("Unsupported configuration version: %s" %
if 'version' not in config_data:
config_data['version'] = constants.BuildVersion(2, 0, 0)
if 'serial_no' not in config_data:
config_data['serial_no'] = 1
# Make sure no instance uses remote_raid1 anymore
remote_raid1_instances = []
......@@ -174,15 +245,24 @@ def main():
raise Error("Unable to convert configuration as long as there are"
" instances using remote_raid1 disk template")
# The configuration version will be stored in a ssconf file
if 'config_version' in config_data['cluster']:
del config_data['cluster']['config_version']
# Build content of new known_hosts file
cluster_name = ReadFile(SSCONF_CLUSTER_NAME_PATH).rstrip()
cluster_key = config_data['cluster']['rsahostkeypub']
cluster_key = cluster['rsahostkeypub']
known_hosts = "%s ssh-rsa %s\n" % (cluster_name, cluster_key)
# Add node attributes"Upgrading nodes")
# stable-sort the names to have repeatable runs
for node_name in utils.NiceSort(config_data['nodes'].keys()):
# instance changes
# TODO: add instance upgrade
for instance in config_data['instances'].values():
else:"Found a Ganeti 2.0 configuration")
......@@ -192,18 +272,18 @@ def main():
known_hosts = None
config_version_str = "%s\n" % constants.BuildVersion(2, 0, 0)
try:"Writing configuration file")
WriteFile(CONFIG_DATA_PATH, serializer.DumpJson(config_data))"Writing configuration version %s",
WriteFile(SSCONF_CONFIG_VERSION_PATH, config_version_str)
if known_hosts is not None:"Writing SSH known_hosts file (%s)", known_hosts.strip())
WriteFile(KNOWN_HOSTS_PATH, known_hosts)
if not options.dry_run:
if not os.path.exists(constants.RAPI_CERT_FILE):
logging.critical("Writing configuration failed. It is proably in an"
" inconsistent state and needs manual intervention.")
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