X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/0b94cda82744b2db34009e0080600cb92212de32..43ffd83959093e1cd56c45bf7eac1c86d77b8ee7:/tools/cfgupgrade diff --git a/tools/cfgupgrade b/tools/cfgupgrade index eefabec..554877f 100755 --- a/tools/cfgupgrade +++ b/tools/cfgupgrade @@ -52,11 +52,11 @@ args = None #: Target major version we will upgrade to TARGET_MAJOR = 2 #: Target minor version we will upgrade to -TARGET_MINOR = 7 +TARGET_MINOR = 9 #: Target major version for downgrade DOWNGRADE_MAJOR = 2 #: Target minor version for downgrade -DOWNGRADE_MINOR = 7 +DOWNGRADE_MINOR = 8 class Error(Exception): @@ -102,17 +102,28 @@ def CheckHostname(path): return False -def UpgradeIPolicy(ipolicy): +def _FillIPolicySpecs(default_ipolicy, ipolicy): + if "minmax" in ipolicy: + for (key, spec) in ipolicy["minmax"][0].items(): + for (par, val) in default_ipolicy["minmax"][0][key].items(): + if par not in spec: + spec[par] = val + + +def UpgradeIPolicy(ipolicy, default_ipolicy, isgroup): minmax_keys = ["min", "max"] if any((k in ipolicy) for k in minmax_keys): minmax = {} - ipolicy["minmax"] = minmax for key in minmax_keys: if key in ipolicy: - minmax[key] = ipolicy[key] + if ipolicy[key]: + minmax[key] = ipolicy[key] del ipolicy[key] - else: - minmax[key] = {} + if minmax: + ipolicy["minmax"] = [minmax] + if isgroup and "std" in ipolicy: + del ipolicy["std"] + _FillIPolicySpecs(default_ipolicy, ipolicy) def UpgradeNetworks(config_data): @@ -125,19 +136,41 @@ def UpgradeCluster(config_data): cluster = config_data.get("cluster", None) if cluster is None: raise Error("Cannot find cluster") - ipolicy = cluster.get("ipolicy", None) + ipolicy = cluster.setdefault("ipolicy", None) if ipolicy: - UpgradeIPolicy(ipolicy) + UpgradeIPolicy(ipolicy, constants.IPOLICY_DEFAULTS, False) def UpgradeGroups(config_data): + cl_ipolicy = config_data["cluster"].get("ipolicy") for group in config_data["nodegroups"].values(): networks = group.get("networks", None) if not networks: group["networks"] = {} ipolicy = group.get("ipolicy", None) if ipolicy: - UpgradeIPolicy(ipolicy) + if cl_ipolicy is None: + raise Error("A group defines an instance policy but there is no" + " instance policy at cluster level") + UpgradeIPolicy(ipolicy, cl_ipolicy, True) + + +def GetExclusiveStorageValue(config_data): + """Return a conservative value of the exclusive_storage flag. + + Return C{True} if the cluster or at least a nodegroup have the flag set. + + """ + ret = False + cluster = config_data["cluster"] + ndparams = cluster.get("ndparams") + if ndparams is not None and ndparams.get("exclusive_storage"): + ret = True + for group in config_data["nodegroups"].values(): + ndparams = group.get("ndparams") + if ndparams is not None and ndparams.get("exclusive_storage"): + ret = True + return ret def UpgradeInstances(config_data): @@ -146,6 +179,7 @@ def UpgradeInstances(config_data): if "instances" not in config_data: raise Error("Can't find the 'instances' key in the configuration!") + missing_spindles = False for instance, iobj in config_data["instances"].items(): for nic in iobj["nics"]: name = nic.get("network", None) @@ -167,6 +201,17 @@ def UpgradeInstances(config_data): " from '%s' to '%s'", instance, idx, current, expected) dobj["iv_name"] = expected + if not "spindles" in dobj: + missing_spindles = True + + if GetExclusiveStorageValue(config_data) and missing_spindles: + # We cannot be sure that the instances that are missing spindles have + # exclusive storage enabled (the check would be more complicated), so we + # give a noncommittal message + logging.warning("Some instance disks could be needing to update the" + " spindles parameter; you can check by running" + " 'gnt-cluster verify', and fix any problem with" + " 'gnt-cluster repair-disk-sizes'") def UpgradeRapiUsers(): @@ -233,6 +278,64 @@ def UpgradeFileStoragePaths(config_data): backup=True) +def GetNewNodeIndex(nodes_by_old_key, old_key, new_key_field): + if old_key not in nodes_by_old_key: + logging.warning("Can't find node '%s' in configuration, assuming that it's" + " already up-to-date", old_key) + return old_key + return nodes_by_old_key[old_key][new_key_field] + + +def ChangeNodeIndices(config_data, old_key_field, new_key_field): + def ChangeDiskNodeIndices(disk): + if disk["dev_type"] in constants.LDS_DRBD: + for i in range(0, 2): + disk["logical_id"][i] = GetNewNodeIndex(nodes_by_old_key, + disk["logical_id"][i], + new_key_field) + if "children" in disk: + for child in disk["children"]: + ChangeDiskNodeIndices(child) + + nodes_by_old_key = {} + nodes_by_new_key = {} + for (_, node) in config_data["nodes"].items(): + nodes_by_old_key[node[old_key_field]] = node + nodes_by_new_key[node[new_key_field]] = node + + config_data["nodes"] = nodes_by_new_key + + cluster = config_data["cluster"] + cluster["master_node"] = GetNewNodeIndex(nodes_by_old_key, + cluster["master_node"], + new_key_field) + + for inst in config_data["instances"].values(): + inst["primary_node"] = GetNewNodeIndex(nodes_by_old_key, + inst["primary_node"], + new_key_field) + for disk in inst["disks"]: + ChangeDiskNodeIndices(disk) + + +def ChangeInstanceIndices(config_data, old_key_field, new_key_field): + insts_by_old_key = {} + insts_by_new_key = {} + for (_, inst) in config_data["instances"].items(): + insts_by_old_key[inst[old_key_field]] = inst + insts_by_new_key[inst[new_key_field]] = inst + + config_data["instances"] = insts_by_new_key + + +def UpgradeNodeIndices(config_data): + ChangeNodeIndices(config_data, "name", "uuid") + + +def UpgradeInstanceIndices(config_data): + ChangeInstanceIndices(config_data, "name", "uuid") + + def UpgradeAll(config_data): config_data["version"] = constants.BuildVersion(TARGET_MAJOR, TARGET_MINOR, 0) @@ -243,53 +346,45 @@ def UpgradeAll(config_data): UpgradeCluster(config_data) UpgradeGroups(config_data) UpgradeInstances(config_data) + UpgradeNodeIndices(config_data) + UpgradeInstanceIndices(config_data) -def DowngradeIPolicy(ipolicy): - # Downgrade IPolicy to 2.7 (stable) - minmax_keys = ["min", "max"] - specs_is_split = any((k in ipolicy) for k in minmax_keys) - if not specs_is_split: - if "minmax" in ipolicy: - minmax = ipolicy["minmax"] - del ipolicy["minmax"] - else: - minmax = {} - for key in minmax_keys: - spec = minmax.get(key, {}) - ipolicy[key] = spec +def DowngradeDisks(disks, owner): + for disk in disks: + # Remove spindles to downgrade to 2.8 + if "spindles" in disk: + logging.warning("Removing spindles (value=%s) from disk %s (%s) of" + " instance %s", + disk["spindles"], disk["iv_name"], disk["uuid"], owner) + del disk["spindles"] -def DowngradeGroups(config_data): - for group in config_data["nodegroups"].values(): - ipolicy = group.get("ipolicy", None) - if ipolicy: - DowngradeIPolicy(ipolicy) +def DowngradeInstances(config_data): + if "instances" not in config_data: + raise Error("Cannot find the 'instances' key in the configuration!") + for (iname, iobj) in config_data["instances"].items(): + if "disks" not in iobj: + raise Error("Cannot find 'disks' key for instance %s" % iname) + DowngradeDisks(iobj["disks"], iname) -def DowngradeStorageTypes(cluster): - # Remove storage types to downgrade to 2.7 - if "enabled_storage_types" in cluster: - logging.warning("Removing cluster storage types; value = %s", - utils.CommaJoin(cluster["enabled_storage_types"])) - del cluster["enabled_storage_types"] +def DowngradeNodeIndices(config_data): + ChangeNodeIndices(config_data, "uuid", "name") -def DowngradeCluster(config_data): - cluster = config_data.get("cluster", None) - if cluster is None: - raise Error("Cannot find cluster") - DowngradeStorageTypes(cluster) - ipolicy = cluster.get("ipolicy", None) - if ipolicy: - DowngradeIPolicy(ipolicy) +def DowngradeInstanceIndices(config_data): + ChangeInstanceIndices(config_data, "uuid", "name") def DowngradeAll(config_data): # Any code specific to a particular version should be labeled that way, so # it can be removed when updating to the next version. - DowngradeCluster(config_data) - DowngradeGroups(config_data) + config_data["version"] = constants.BuildVersion(DOWNGRADE_MAJOR, + DOWNGRADE_MINOR, 0) + DowngradeInstances(config_data) + DowngradeNodeIndices(config_data) + DowngradeInstanceIndices(config_data) def main(): @@ -401,15 +496,17 @@ def main(): # Downgrade to the previous stable version if options.downgrade: - if config_major != TARGET_MAJOR or config_minor != TARGET_MINOR: + if not ((config_major == TARGET_MAJOR and config_minor == TARGET_MINOR) or + (config_major == DOWNGRADE_MAJOR and + config_minor == DOWNGRADE_MINOR)): raise Error("Downgrade supported only from the latest version (%s.%s)," " found %s (%s.%s.%s) instead" % (TARGET_MAJOR, TARGET_MINOR, config_version, config_major, config_minor, config_revision)) DowngradeAll(config_data) - # Upgrade from 2.{0..7} to 2.7 - elif config_major == 2 and config_minor in range(0, 8): + # Upgrade from 2.{0..7} to 2.9 + elif config_major == 2 and config_minor in range(0, 10): if config_revision != 0: logging.warning("Config revision is %s, not 0", config_revision) UpgradeAll(config_data)