Commit fc1dc9d7 authored by Iustin Pop's avatar Iustin Pop
Browse files

Allow DRBD8 operation without backing storage

This patch adds the following functionality:
  - DRBD8 devices can assemble without local storage (done by allowing
    None in the list of children, and making DRBD8 to ignore all
    children if any is None)
  - DRBD8 devices can attach (i.e. identify a device) which is not
    connected to backing storage but to the correct network ports; this
    is a rare case in normal operation (it's what would happen if one
    manually detaches the local disk, and the backing LV still exists)

Reviewed-by: imsnah
parent 583e3f6f
......@@ -722,8 +722,20 @@ def _RecursiveAssembleBD(disk, owner, as_primary):
children = []
if disk.children:
mcn = disk.ChildrenNeeded()
if mcn == -1:
mcn = 0 # max number of Nones allowed
mcn = len(disk.children) - mcn # max number of Nones
for chld_disk in disk.children:
children.append(_RecursiveAssembleBD(chld_disk, owner, as_primary))
cdev = _RecursiveAssembleBD(chld_disk, owner, as_primary)
except errors.BlockDeviceError, err:
if children.count(None) > mcn:
cdev = None
logger.Debug("Error in child activation: %s" % str(err))
if as_primary or disk.AssembleOnSecondary():
r_dev = bdev.AttachOrAssemble(disk.dev_type, disk.physical_id, children)
......@@ -1566,6 +1566,8 @@ class DRBD8(BaseDRBD):
def __init__(self, unique_id, children):
if children and children.count(None) > 0:
children = []
super(DRBD8, self).__init__(unique_id, children)
self.major = self._DRBD_MAJOR
[kmaj, kmin, kfix, api, proto] = self._GetVersion()
......@@ -2030,6 +2032,10 @@ class DRBD8(BaseDRBD):
if res_r and self._MatchesNet(self._GetDevInfo(minor)):
# the weakest case: we find something that is only net attached
# even though we were passed some children at init time
if match_r and "local_dev" not in info:
minor = None
......@@ -2066,7 +2072,7 @@ class DRBD8(BaseDRBD):
minor = self._FindUnusedMinor()
need_localdev_teardown = False
if self._children[0]:
if self._children and self._children[0] and self._children[1]:
result = self._AssembleLocal(minor, self._children[0].dev_path,
if not result:
......@@ -338,6 +338,22 @@ class Disk(ConfigObject):
return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
return None
def ChildrenNeeded(self):
"""Compute the needed number of children for activation.
This method will return either -1 (all children) or a positive
number denoting the minimum number of children needed for
activation (only mirrored devices will usually return >=0).
Currently, only DRBD8 supports diskless activation (therefore we
return 0), for all other we keep the previous semantics and return
if self.dev_type == constants.LD_DRBD8:
return 0
return -1
def GetNodes(self, node):
"""This function returns the nodes this device lives on.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment