Initial implementation of drbd8 template type
authorIustin Pop <iustin@google.com>
Wed, 24 Oct 2007 14:43:24 +0000 (14:43 +0000)
committerIustin Pop <iustin@google.com>
Wed, 24 Oct 2007 14:43:24 +0000 (14:43 +0000)
This is a partially working drbd8 template type. It does:
  - add/remove
  - startup/failover/shutdown

Not working is replace disks, which needs custom code for this template.

Reviewed-by: imsnah

lib/bdev.py
lib/cmdlib.py
lib/config.py
lib/constants.py
lib/objects.py
scripts/gnt-instance

index 0352ca8..0e8ddf4 100644 (file)
@@ -2086,6 +2086,7 @@ DEV_MAP = {
   constants.LD_LV: LogicalVolume,
   constants.LD_MD_R1: MDRaid1,
   constants.LD_DRBD7: DRBDev,
+  constants.LD_DRBD8: DRBD8,
   }
 
 
index 0ef8846..ab433ed 100644 (file)
@@ -2460,9 +2460,9 @@ class LUFailoverInstance(LogicalUnit):
       raise errors.OpPrereqError("Instance '%s' not known" %
                                  self.op.instance_name)
 
-    if instance.disk_template != constants.DT_REMOTE_RAID1:
+    if instance.disk_template not in constants.DTS_NET_MIRROR:
       raise errors.OpPrereqError("Instance's disk layout is not"
-                                 " remote_raid1.")
+                                 " network mirrored, cannot failover.")
 
     secondary_nodes = instance.secondary_nodes
     if not secondary_nodes:
@@ -2636,6 +2636,22 @@ def _GenerateMDDRBDBranch(cfg, primary, secondary, size, names):
   return drbd_dev
 
 
+def _GenerateDRBD8Branch(cfg, primary, secondary, size, names, iv_name):
+  """Generate a drbd8 device complete with its children.
+
+  """
+  port = cfg.AllocatePort()
+  vgname = cfg.GetVGName()
+  dev_data = objects.Disk(dev_type=constants.LD_LV, size=size,
+                          logical_id=(vgname, names[0]))
+  dev_meta = objects.Disk(dev_type=constants.LD_LV, size=128,
+                          logical_id=(vgname, names[1]))
+  drbd_dev = objects.Disk(dev_type=constants.LD_DRBD8, size=size,
+                          logical_id = (primary, secondary, port),
+                          children = [dev_data, dev_meta],
+                          iv_name=iv_name)
+  return drbd_dev
+
 def _GenerateDiskTemplate(cfg, template_name,
                           instance_name, primary_node,
                           secondary_nodes, disk_sz, swap_sz):
@@ -2696,6 +2712,17 @@ def _GenerateDiskTemplate(cfg, template_name,
     md_sdb_dev = objects.Disk(dev_type=constants.LD_MD_R1, iv_name="sdb",
                               children = [drbd_sdb_dev], size=swap_sz)
     disks = [md_sda_dev, md_sdb_dev]
+  elif template_name == constants.DT_DRBD8:
+    if len(secondary_nodes) != 1:
+      raise errors.ProgrammerError("Wrong template configuration")
+    remote_node = secondary_nodes[0]
+    names = _GenerateUniqueNames(cfg, [".sda_data", ".sda_meta",
+                                       ".sdb_data", ".sdb_meta"])
+    drbd_sda_dev = _GenerateDRBD8Branch(cfg, primary_node, remote_node,
+                                         disk_sz, names[0:2], "sda")
+    drbd_sdb_dev = _GenerateDRBD8Branch(cfg, primary_node, remote_node,
+                                         swap_sz, names[2:4], "sdb")
+    disks = [drbd_sda_dev, drbd_sdb_dev]
   else:
     raise errors.ProgrammerError("Invalid disk template '%s'" % template_name)
   return disks
@@ -2872,9 +2899,9 @@ class LUCreateInstance(LogicalUnit):
     if self.op.disk_template not in constants.DISK_TEMPLATES:
       raise errors.OpPrereqError("Invalid disk template name")
 
-    if self.op.disk_template == constants.DT_REMOTE_RAID1:
+    if self.op.disk_template in constants.DTS_NET_MIRROR:
       if getattr(self.op, "snode", None) is None:
-        raise errors.OpPrereqError("The 'remote_raid1' disk template needs"
+        raise errors.OpPrereqError("The networked disk templates need"
                                    " a mirror node")
 
       snode_name = self.cfg.ExpandNodeName(self.op.snode)
@@ -2897,6 +2924,7 @@ class LUCreateInstance(LogicalUnit):
       constants.DT_LOCAL_RAID1: (self.op.disk_size + self.op.swap_size) * 2,
       # 256 MB are added for drbd metadata, 128MB for each drbd device
       constants.DT_REMOTE_RAID1: self.op.disk_size + self.op.swap_size + 256,
+      constants.DT_DRBD8: self.op.disk_size + self.op.swap_size + 256,
     }
 
     if self.op.disk_template not in req_size_dict:
@@ -3006,7 +3034,7 @@ class LUCreateInstance(LogicalUnit):
 
     if self.op.wait_for_sync:
       disk_abort = not _WaitForSync(self.cfg, iobj)
-    elif iobj.disk_template == constants.DT_REMOTE_RAID1:
+    elif iobj.disk_template in constants.DTS_NET_MIRROR:
       # make sure the disks are not degraded (still sync-ing is ok)
       time.sleep(15)
       feedback_fn("* checking mirrors status")
@@ -3486,7 +3514,7 @@ class LUQueryInstanceData(NoHooksLU):
     """
     self.cfg.SetDiskID(dev, instance.primary_node)
     dev_pstatus = rpc.call_blockdev_find(instance.primary_node, dev)
-    if dev.dev_type == constants.LD_DRBD7:
+    if dev.dev_type in constants.LDS_DRBD:
       # we change the snode then (otherwise we use the one passed in)
       if dev.logical_id[0] == instance.primary_node:
         snode = dev.logical_id[1]
index e309316..0c769d2 100644 (file)
@@ -198,7 +198,7 @@ class ConfigWriter:
 
     if disk.logical_id is None and disk.physical_id is not None:
       return
-    if disk.dev_type == constants.LD_DRBD7:
+    if disk.dev_type in constants.LDS_DRBD:
       pnode, snode, port = disk.logical_id
       if node_name not in (pnode, snode):
         raise errors.ConfigurationError("DRBD device not knowing node %s" %
index 2c9067c..a6d99da 100644 (file)
@@ -78,18 +78,27 @@ DT_DISKLESS = "diskless"
 DT_PLAIN = "plain"
 DT_LOCAL_RAID1 = "local_raid1"
 DT_REMOTE_RAID1 = "remote_raid1"
+DT_DRBD8 = "drbd"
+
+# the set of network-mirrored disk templates
+DTS_NET_MIRROR = frozenset([DT_REMOTE_RAID1, DT_DRBD8])
 
 # logical disk types
 LD_LV = "lvm"
 LD_MD_R1 = "md_raid1"
 LD_DRBD7 = "drbd"
+LD_DRBD8 = "drbd8"
+
+# the set of drbd-like disk types
+LDS_DRBD = frozenset([LD_DRBD7, LD_DRBD8])
 
 # instance creation modem
 INSTANCE_CREATE = "create"
 INSTANCE_IMPORT = "import"
 
 DISK_TEMPLATES = frozenset([DT_DISKLESS, DT_PLAIN,
-                            DT_LOCAL_RAID1, DT_REMOTE_RAID1])
+                            DT_LOCAL_RAID1, DT_REMOTE_RAID1,
+                            DT_DRBD8])
 
 # import/export config options
 INISECT_EXP = "export"
index f5da82a..b009191 100644 (file)
@@ -314,11 +314,13 @@ class Disk(ConfigObject):
 
   def CreateOnSecondary(self):
     """Test if this device needs to be created on a secondary node."""
-    return self.dev_type in (constants.LD_DRBD7, constants.LD_LV)
+    return self.dev_type in (constants.LD_DRBD7, constants.LD_DRBD8,
+                             constants.LD_LV)
 
   def AssembleOnSecondary(self):
     """Test if this device needs to be assembled on a secondary node."""
-    return self.dev_type in (constants.LD_DRBD7, constants.LD_LV)
+    return self.dev_type in (constants.LD_DRBD7, constants.LD_DRBD8,
+                             constants.LD_LV)
 
   def OpenOnSecondary(self):
     """Test if this device needs to be opened on a secondary node."""
@@ -335,7 +337,7 @@ class Disk(ConfigObject):
     """
     if self.dev_type == constants.LD_LV or self.dev_type == constants.LD_MD_R1:
       result = [node]
-    elif self.dev_type == constants.LD_DRBD7:
+    elif self.dev_type in constants.LDS_DRBD:
       result = [self.logical_id[0], self.logical_id[1]]
       if node not in result:
         raise errors.ConfigurationError("DRBD device passed unknown node")
@@ -436,7 +438,7 @@ class Instance(TaggableObject):
     """
     def _Helper(primary, sec_nodes, device):
       """Recursively computes secondary nodes given a top device."""
-      if device.dev_type == constants.LD_DRBD7:
+      if device.dev_type in constants.LDS_DRBD:
         nodea, nodeb, dummy = device.logical_id
         if nodea == primary:
           candidate = nodeb
@@ -488,7 +490,7 @@ class Instance(TaggableObject):
       if dev.dev_type == constants.LD_LV:
         lvmap[node].append(dev.logical_id[1])
 
-      elif dev.dev_type == constants.LD_DRBD7:
+      elif dev.dev_type in constants.LDS_DRBD:
         if dev.logical_id[0] not in lvmap:
           lvmap[dev.logical_id[0]] = []
 
index 9d78dff..e1bb5af 100755 (executable)
@@ -503,7 +503,7 @@ def _FormatBlockDevInfo(buf, dev, indent_level):
     else:
       (path, major, minor, syncp, estt, degr) = status
       buf.write("%s (%d:%d)" % (path, major, minor))
-      if dtype in (constants.LD_MD_R1, constants.LD_DRBD7):
+      if dtype in (constants.LD_MD_R1, constants.LD_DRBD7, constants.LD_DRBD8):
         if syncp is not None:
           sync_text = "*RECOVERING* %5.2f%%," % syncp
           if estt:
@@ -661,8 +661,8 @@ add_opts = [
   make_option("-p", "--cpu", dest="vcpus", help="Number of virtual CPUs",
               default=1, type="int", metavar="<PROC>"),
   make_option("-t", "--disk-template", dest="disk_template",
-              help="Custom disk setup (diskless, plain, local_raid1 or"
-              " remote_raid1)", default=None, metavar="TEMPL"),
+              help="Custom disk setup (diskless, plain, local_raid1,"
+              " remote_raid1 or drbd)", default=None, metavar="TEMPL"),
   make_option("-i", "--ip", dest="ip",
               help="IP address ('none' [default], 'auto', or specify address)",
               default='none', type="string", metavar="<ADDRESS>"),