From 923b152388cc879dc2b0d4caad57b200f8d4491d Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Fri, 3 Aug 2007 09:57:41 +0000
Subject: [PATCH] Change logival volume names to not be based on the instance's
 name, but instead use an UUID prefix and a suffix denoting the disk iv_name
 (sda/sdb) and possibly it's type (data/meta).

Reviewed-by: imsnah
---
 lib/cmdlib.py | 73 ++++++++++++++++++++++++++++++++-------------------
 lib/config.py | 67 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 112 insertions(+), 28 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 17bf5311f..5820bb93e 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -2300,23 +2300,36 @@ def _CreateBlockDevOnSecondary(cfg, node, device, force):
   return True
 
 
-def _GenerateMDDRBDBranch(cfg, vgname, primary, secondary, size, base):
+def _GenerateUniqueNames(cfg, exts):
+  """Generate a suitable LV name.
+
+  This will generate a logical volume name for the given instance.
+
+  """
+  results = []
+  for val in exts:
+    new_id = cfg.GenerateUniqueID()
+    results.append("%s%s" % (new_id, val))
+  return results
+
+
+def _GenerateMDDRBDBranch(cfg, primary, secondary, size, names):
   """Generate a drbd device complete with its children.
 
   """
   port = cfg.AllocatePort()
-  base = "%s_%s" % (base, port)
+  vgname = cfg.GetVGName()
   dev_data = objects.Disk(dev_type="lvm", size=size,
-                          logical_id=(vgname, "%s.data" % base))
+                          logical_id=(vgname, names[0]))
   dev_meta = objects.Disk(dev_type="lvm", size=128,
-                          logical_id=(vgname, "%s.meta" % base))
+                          logical_id=(vgname, names[1]))
   drbd_dev = objects.Disk(dev_type="drbd", size=size,
                           logical_id = (primary, secondary, port),
                           children = [dev_data, dev_meta])
   return drbd_dev
 
 
-def _GenerateDiskTemplate(cfg, vgname, template_name,
+def _GenerateDiskTemplate(cfg, template_name,
                           instance_name, primary_node,
                           secondary_nodes, disk_sz, swap_sz):
   """Generate the entire disk layout for a given template type.
@@ -2324,34 +2337,39 @@ def _GenerateDiskTemplate(cfg, vgname, template_name,
   """
   #TODO: compute space requirements
 
+  vgname = cfg.GetVGName()
   if template_name == "diskless":
     disks = []
   elif template_name == "plain":
     if len(secondary_nodes) != 0:
       raise errors.ProgrammerError("Wrong template configuration")
+
+    names = _GenerateUniqueNames(cfg, [".sda", ".sdb"])
     sda_dev = objects.Disk(dev_type="lvm", size=disk_sz,
-                           logical_id=(vgname, "%s.os" % instance_name),
+                           logical_id=(vgname, names[0]),
                            iv_name = "sda")
     sdb_dev = objects.Disk(dev_type="lvm", size=swap_sz,
-                           logical_id=(vgname, "%s.swap" % instance_name),
+                           logical_id=(vgname, names[1]),
                            iv_name = "sdb")
     disks = [sda_dev, sdb_dev]
   elif template_name == "local_raid1":
     if len(secondary_nodes) != 0:
       raise errors.ProgrammerError("Wrong template configuration")
+
+
+    names = _GenerateUniqueNames(cfg, [".sda_m1", ".sda_m2",
+                                       ".sdb_m1", ".sdb_m2"])
     sda_dev_m1 = objects.Disk(dev_type="lvm", size=disk_sz,
-                              logical_id=(vgname, "%s.os_m1" % instance_name))
+                              logical_id=(vgname, names[0]))
     sda_dev_m2 = objects.Disk(dev_type="lvm", size=disk_sz,
-                              logical_id=(vgname, "%s.os_m2" % instance_name))
+                              logical_id=(vgname, names[1]))
     md_sda_dev = objects.Disk(dev_type="md_raid1", iv_name = "sda",
                               size=disk_sz,
                               children = [sda_dev_m1, sda_dev_m2])
     sdb_dev_m1 = objects.Disk(dev_type="lvm", size=swap_sz,
-                              logical_id=(vgname, "%s.swap_m1" %
-                                          instance_name))
+                              logical_id=(vgname, names[2]))
     sdb_dev_m2 = objects.Disk(dev_type="lvm", size=swap_sz,
-                              logical_id=(vgname, "%s.swap_m2" %
-                                          instance_name))
+                              logical_id=(vgname, names[3]))
     md_sdb_dev = objects.Disk(dev_type="md_raid1", iv_name = "sdb",
                               size=swap_sz,
                               children = [sdb_dev_m1, sdb_dev_m2])
@@ -2360,14 +2378,14 @@ def _GenerateDiskTemplate(cfg, vgname, template_name,
     if len(secondary_nodes) != 1:
       raise errors.ProgrammerError("Wrong template configuration")
     remote_node = secondary_nodes[0]
-    drbd_sda_dev = _GenerateMDDRBDBranch(cfg, vgname,
-                                         primary_node, remote_node, disk_sz,
-                                         "%s-sda" % instance_name)
+    names = _GenerateUniqueNames(cfg, [".sda_data", ".sda_meta",
+                                       ".sdb_data", ".sdb_meta"])
+    drbd_sda_dev = _GenerateMDDRBDBranch(cfg, primary_node, remote_node,
+                                         disk_sz, names[0:2])
     md_sda_dev = objects.Disk(dev_type="md_raid1", iv_name="sda",
                               children = [drbd_sda_dev], size=disk_sz)
-    drbd_sdb_dev = _GenerateMDDRBDBranch(cfg, vgname,
-                                         primary_node, remote_node, swap_sz,
-                                         "%s-sdb" % instance_name)
+    drbd_sdb_dev = _GenerateMDDRBDBranch(cfg, primary_node, remote_node,
+                                         swap_sz, names[2:4])
     md_sdb_dev = objects.Disk(dev_type="md_raid1", iv_name="sdb",
                               children = [drbd_sdb_dev], size=swap_sz)
     disks = [md_sda_dev, md_sdb_dev]
@@ -2644,7 +2662,7 @@ class LUCreateInstance(LogicalUnit):
     if self.inst_ip is not None:
       nic.ip = self.inst_ip
 
-    disks = _GenerateDiskTemplate(self.cfg, self.cfg.GetVGName(),
+    disks = _GenerateDiskTemplate(self.cfg,
                                   self.op.disk_template,
                                   instance, pnode_name,
                                   self.secondaries, self.op.disk_size,
@@ -2829,10 +2847,10 @@ class LUAddMDDRBDComponent(LogicalUnit):
     instance = self.instance
 
     remote_node = self.remote_node
-    new_drbd = _GenerateMDDRBDBranch(self.cfg, self.cfg.GetVGName(),
-                                     instance.primary_node, remote_node,
-                                     disk.size, "%s-%s" %
-                                     (instance.name, self.op.disk_name))
+    lv_names = [".%s_%s" % (disk.iv_name, suf) for suf in ["data", "meta"]]
+    names = _GenerateUniqueNames(self.cfg, lv_names)
+    new_drbd = _GenerateMDDRBDBranch(self.cfg, instance.primary_node,
+                                     remote_node, disk.size, names)
 
     logger.Info("adding new mirror component on secondary")
     #HARDCODE
@@ -3027,9 +3045,10 @@ class LUReplaceDisks(LogicalUnit):
     vgname = cfg.GetVGName()
     for dev in instance.disks:
       size = dev.size
-      new_drbd = _GenerateMDDRBDBranch(cfg, vgname, instance.primary_node,
-                                       remote_node, size,
-                                       "%s-%s" % (instance.name, dev.iv_name))
+      lv_names = [".%s_%s" % (dev.iv_name, suf) for suf in ["data", "meta"]]
+      names = _GenerateUniqueNames(cfg, lv_names)
+      new_drbd = _GenerateMDDRBDBranch(cfg, instance.primary_node,
+                                       remote_node, size, names)
       iv_names[dev.iv_name] = (dev, dev.children[0], new_drbd)
       logger.Info("adding new mirror component on secondary for %s" %
                   dev.iv_name)
diff --git a/lib/config.py b/lib/config.py
index f83fab6e2..b3a25f488 100644
--- a/lib/config.py
+++ b/lib/config.py
@@ -46,6 +46,22 @@ from ganeti import constants
 from ganeti import rpc
 from ganeti import objects
 
+def _my_uuidgen():
+  """Poor-man's uuidgen using the uuidgen binary.
+
+  """
+  result = utils.RunCmd(["uuidgen", "-r"])
+  if result.failed:
+    return None
+  return result.stdout.rstrip('\n')
+
+
+try:
+  import uuid
+  _uuidgen = uuid.uuid4
+except ImportError:
+  _uuidgen = _my_uuidgen
+
 
 class ConfigWriter:
   """The interface to the cluster configuration.
@@ -61,6 +77,7 @@ class ConfigWriter:
       self._cfg_file = constants.CLUSTER_CONF_FILE
     else:
       self._cfg_file = cfg_file
+    self._temporary_ids = set()
 
   # this method needs to be static, so that we can call it on the class
   @staticmethod
@@ -93,6 +110,52 @@ class ConfigWriter:
       raise errors.ConfigurationError, ("Can't generate unique MAC")
     return mac
 
+  def _ComputeAllLVs(self):
+    """Compute the list of all LVs.
+
+    """
+    self._OpenConfig()
+    self._ReleaseLock()
+    lvnames = set()
+    for instance in self._config_data.instances.values():
+      node_data = instance.MapLVsByNode()
+      for lv_list in node_data.values():
+        lvnames.update(lv_list)
+    return lvnames
+
+  def GenerateUniqueID(self, exceptions=None):
+    """Generate an unique disk name.
+
+    This checks the current node, instances and disk names for
+    duplicates.
+
+    Args:
+      - exceptions: a list with some other names which should be checked
+                    for uniqueness (used for example when you want to get
+                    more than one id at one time without adding each one in
+                    turn to the config file
+
+    Returns: the unique id as a string
+
+    """
+    existing = set()
+    existing.update(self._temporary_ids)
+    existing.update(self._ComputeAllLVs())
+    existing.update(self._config_data.instances.keys())
+    existing.update(self._config_data.nodes.keys())
+    if exceptions is not None:
+      existing.update(exceptions)
+    retries = 64
+    while retries > 0:
+      unique_id = _uuidgen()
+      if unique_id not in existing and unique_id is not None:
+        break
+    else:
+      raise errors.ConfigurationError, ("Not able generate an unique ID"
+                                        " (last tried ID: %s" % unique_id)
+    self._temporary_ids.add(unique_id)
+    return unique_id
+
   def _AllMACs(self):
     """Return all MACs present in the config.
 
@@ -133,7 +196,6 @@ class ConfigWriter:
           seen_macs.append(nic.mac)
     return result
 
-
   def SetDiskID(self, disk, node_name):
     """Convert the unique ID to the ID needed on the target nodes.
 
@@ -235,6 +297,9 @@ class ConfigWriter:
     if not isinstance(instance, objects.Instance):
       raise errors.ProgrammerError("Invalid type passed to AddInstance")
 
+    all_lvs = instance.MapLVsByNode()
+    logger.Info("Instance '%s' DISK_LAYOUT: %s" % (instance.name, all_lvs))
+
     self._OpenConfig()
     self._config_data.instances[instance.name] = instance
     self._WriteConfig()
-- 
GitLab