import sys
import optparse
import logging
+import time
+from cStringIO import StringIO
from ganeti import constants
from ganeti import serializer
from ganeti import bootstrap
from ganeti import config
from ganeti import netutils
+from ganeti import pathutils
options = None
#: Target major version we will upgrade to
TARGET_MAJOR = 2
#: Target minor version we will upgrade to
-TARGET_MINOR = 6
+TARGET_MINOR = 7
class Error(Exception):
return False
+def UpgradeNetworks(config_data):
+ networks = config_data.get("networks", None)
+ if not networks:
+ config_data["networks"] = {}
+
+
+def UpgradeGroups(config_data):
+ for group in config_data["nodegroups"].values():
+ networks = group.get("networks", None)
+ if not networks:
+ group["networks"] = {}
+
+
def main():
"""Main program.
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")
+ " directory instead of '%s'" % pathutils.DATA_DIR,
+ default=pathutils.DATA_DIR, dest="data_dir")
+ parser.add_option("--confdir",
+ help=("Use this directory instead of '%s'" %
+ pathutils.CONF_DIR),
+ default=pathutils.CONF_DIR, dest="conf_dir")
parser.add_option("--no-verify",
help="Do not verify configuration after upgrade",
action="store_true", dest="no_verify", default=False)
options.CDS_FILE = options.data_dir + "/cluster-domain-secret"
options.SSCONF_MASTER_NODE = options.data_dir + "/ssconf_master_node"
options.WATCHER_STATEFILE = options.data_dir + "/watcher.data"
+ options.FILE_STORAGE_PATHS_FILE = options.conf_dir + "/file-storage-paths"
SetupLogging()
raise Error(("%s does not seem to be a Ganeti configuration"
" directory") % options.data_dir)
+ if not os.path.isdir(options.conf_dir):
+ raise Error("Not a directory: %s" % options.conf_dir)
+
config_data = serializer.LoadJson(utils.ReadFile(options.CONFIG_DATA_PATH))
try:
raise Error("Inconsistent configuration: found config_version in"
" configuration file")
- # Upgrade from 2.0/2.1/2.2/2.3 to 2.4
- if config_major == 2 and config_minor in (0, 1, 2, 3, 4, 5):
+ # Upgrade from 2.{0..6} to 2.7
+ if config_major == 2 and config_minor in (0, 1, 2, 3, 4, 5, 6):
if config_revision != 0:
logging.warning("Config revision is %s, not 0", config_revision)
if not options.dry_run:
utils.RemoveFile(options.WATCHER_STATEFILE)
+ # Write file storage paths
+ if not os.path.exists(options.FILE_STORAGE_PATHS_FILE):
+ cluster = config_data["cluster"]
+ file_storage_dir = cluster.get("file_storage_dir")
+ shared_file_storage_dir = cluster.get("shared_file_storage_dir")
+ del cluster
+
+ logging.info("Ganeti 2.7 and later only allow whitelisted directories"
+ " for file storage; writing existing configuration values"
+ " into '%s'",
+ options.FILE_STORAGE_PATHS_FILE)
+
+ if file_storage_dir:
+ logging.info("File storage directory: %s", file_storage_dir)
+ if shared_file_storage_dir:
+ logging.info("Shared file storage directory: %s",
+ shared_file_storage_dir)
+
+ buf = StringIO()
+ buf.write("# List automatically generated from configuration by\n")
+ buf.write("# cfgupgrade at %s\n" % time.asctime())
+ if file_storage_dir:
+ buf.write("%s\n" % file_storage_dir)
+ if shared_file_storage_dir:
+ buf.write("%s\n" % shared_file_storage_dir)
+ utils.WriteFile(file_name=options.FILE_STORAGE_PATHS_FILE,
+ data=buf.getvalue(),
+ mode=0600,
+ dry_run=options.dry_run,
+ backup=True)
+
+ UpgradeNetworks(config_data)
+ UpgradeGroups(config_data)
+
try:
logging.info("Writing configuration file to %s", options.CONFIG_DATA_PATH)
utils.WriteFile(file_name=options.CONFIG_DATA_PATH,
backup=True)
if not options.dry_run:
- bootstrap.GenerateClusterCrypto(False, False, False, False, False,
- nodecert_file=options.SERVER_PEM_PATH,
- rapicert_file=options.RAPI_CERT_FILE,
- spicecert_file=options.SPICE_CERT_FILE,
- spicecacert_file=options.SPICE_CACERT_FILE,
- hmackey_file=options.CONFD_HMAC_KEY,
- cds_file=options.CDS_FILE)
+ bootstrap.GenerateClusterCrypto(
+ False, False, False, False, False,
+ nodecert_file=options.SERVER_PEM_PATH,
+ rapicert_file=options.RAPI_CERT_FILE,
+ spicecert_file=options.SPICE_CERT_FILE,
+ spicecacert_file=options.SPICE_CACERT_FILE,
+ hmackey_file=options.CONFD_HMAC_KEY,
+ cds_file=options.CDS_FILE)
except Exception:
logging.critical("Writing configuration failed. It is probably in an"