diff --git a/lib/bdev.py b/lib/bdev.py index 0352ca84630c7d57fa06b75526351cd3a3fcdb91..0e8ddf4d48e8e9353d0f173a558accc69a542cc6 100644 --- a/lib/bdev.py +++ b/lib/bdev.py @@ -2086,6 +2086,7 @@ DEV_MAP = { constants.LD_LV: LogicalVolume, constants.LD_MD_R1: MDRaid1, constants.LD_DRBD7: DRBDev, + constants.LD_DRBD8: DRBD8, } diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 0ef88462847547416110d574f5ec6b164254ae63..ab433ed09a0f23a9770a7ab61f1f9bdf4dd388f2 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -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] diff --git a/lib/config.py b/lib/config.py index e3093166889a2ec7092e8568a277a95c20a19863..0c769d2bce7e9fefaac48778b900d665a90ed9b5 100644 --- a/lib/config.py +++ b/lib/config.py @@ -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" % diff --git a/lib/constants.py b/lib/constants.py index 2c9067cc95b17083c9a2d55dd399d8104410765e..a6d99da8297896ab606daedea09172fe3814644d 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -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" diff --git a/lib/objects.py b/lib/objects.py index f5da82a732432f9b363283ddc430e6653a223fea..b009191a212a7e9d94f66596898150fbd9154254 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -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]] = [] diff --git a/scripts/gnt-instance b/scripts/gnt-instance index 9d78dff99f6ba4b8355c85d3b7abe3a6fcfcce9d..e1bb5af9b4bf1329fd8018a5ec0fe61e353024b5 100755 --- a/scripts/gnt-instance +++ b/scripts/gnt-instance @@ -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>"),