Commit a421fdeb authored by Iustin Pop's avatar Iustin Pop
Browse files

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