Implement upgrade/downgrade of the config file to support disks as
top-level citizens. During downgrade, disks that are not attached to any
instance will be removed from config file.

Signed-off-by: Ilias Tsitsimpis <[email protected]>
---
 test/py/cfgupgrade_unittest.py |  1 +
 tools/cfgupgrade               | 80 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/test/py/cfgupgrade_unittest.py b/test/py/cfgupgrade_unittest.py
index e30d22c..7360316 100755
--- a/test/py/cfgupgrade_unittest.py
+++ b/test/py/cfgupgrade_unittest.py
@@ -52,6 +52,7 @@ def GetMinimalConfig():
       "zeroing_image": "",
     },
     "instances": {},
+    "disks": {},
     "networks": {},
     "nodegroups": {},
     "nodes": {
diff --git a/tools/cfgupgrade b/tools/cfgupgrade
index 158a841..ab94cfe 100755
--- a/tools/cfgupgrade
+++ b/tools/cfgupgrade
@@ -237,22 +237,27 @@ def UpgradeInstances(config_data):
     if "disks" not in iobj:
       raise Error("Instance '%s' doesn't have a disks entry?!" % instance)
     disks = iobj["disks"]
-    for idx, dobj in enumerate(disks):
-      RemovePhysicalId(dobj)
+    if not all(isinstance(d, str) for d in disks):
+      #  Disks are not top level citizens
+      for idx, dobj in enumerate(disks):
+        RemovePhysicalId(dobj)
 
-      expected = "disk/%s" % idx
-      current = dobj.get("iv_name", "")
-      if current != expected:
-        logging.warning("Updating iv_name for instance %s/disk %s"
-                        " from '%s' to '%s'",
-                        instance, idx, current, expected)
-        dobj["iv_name"] = expected
+        expected = "disk/%s" % idx
+        current = dobj.get("iv_name", "")
+        if current != expected:
+          logging.warning("Updating iv_name for instance %s/disk %s"
+                          " from '%s' to '%s'",
+                          instance, idx, current, expected)
+          dobj["iv_name"] = expected
 
-      if "dev_type" in dobj:
-        UpgradeDiskDevType(dobj)
+        if "dev_type" in dobj:
+          UpgradeDiskDevType(dobj)
 
-      if not "spindles" in dobj:
-        missing_spindles = True
+        if not "spindles" in dobj:
+          missing_spindles = True
+
+        if not "uuid" in dobj:
+          dobj["uuid"] = utils.io.NewUUID()
 
   if GetExclusiveStorageValue(config_data) and missing_spindles:
     # We cannot be sure that the instances that are missing spindles have
@@ -390,6 +395,27 @@ def UpgradeInstanceIndices(config_data):
   ChangeInstanceIndices(config_data, "name", "uuid")
 
 
+def UpgradeTopLevelDisks(config_data):
+  """Upgrades the disks as config top level citizens."""
+  if "instances" not in config_data:
+    raise Error("Can't find the 'instances' key in the configuration!")
+
+  if "disks" in config_data:
+    # Disks are already top level citizens
+    return
+
+  config_data["disks"] = dict()
+  for iobj in config_data["instances"].values():
+    disk_uuids = []
+    for disk in iobj["disks"]:
+      duuid = disk["uuid"]
+      disk["serial_no"] = 1
+      disk["ctime"] = disk["mtime"] = iobj["ctime"]
+      config_data["disks"][duuid] = disk
+      disk_uuids.append(duuid)
+    iobj["disks"] = disk_uuids
+
+
 def UpgradeAll(config_data):
   config_data["version"] = version.BuildVersion(TARGET_MAJOR, TARGET_MINOR, 0)
   UpgradeRapiUsers()
@@ -401,6 +427,7 @@ def UpgradeAll(config_data):
   UpgradeInstances(config_data)
   UpgradeNodeIndices(config_data)
   UpgradeInstanceIndices(config_data)
+  UpgradeTopLevelDisks(config_data)
 
 
 # DOWNGRADE ------------------------------------------------------------
@@ -431,6 +458,32 @@ def DowngradeInstances(config_data):
       del iobj["osparams_private"]
 
 
+def DowngradeTopLevelDisks(config_data):
+  """Downgrade the disks from config top level citizens."""
+  if "instances" not in config_data:
+    raise Error("Can't find the 'instances' key in the configuration!")
+
+  if "disks" not in config_data:
+    # Disks are not top level citizens
+    return
+
+  for iobj in config_data["instances"].values():
+    disks = list()
+    for disk_uuid in iobj["disks"]:
+      disk_obj = config_data["disks"][disk_uuid]
+      del disk_obj["serial_no"]
+      del disk_obj["ctime"]
+      del disk_obj["mtime"]
+      disks.append(disk_obj)
+      del config_data["disks"][disk_uuid]
+    iobj["disks"] = disks
+
+  for disk_uuid in config_data["disks"].keys():
+    print("Disk %s is not attached to any Instance and will be removed."
+          % disk_uuid)
+  del config_data["disks"]
+
+
 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.
@@ -438,6 +491,7 @@ def DowngradeAll(config_data):
                                                 DOWNGRADE_MINOR, 0)
   DowngradeCluster(config_data)
   DowngradeInstances(config_data)
+  DowngradeTopLevelDisks(config_data)
 
 
 def main():
-- 
1.9.1

Reply via email to