Commit 153d9724 authored by Iustin Pop's avatar Iustin Pop
Browse files

Modify two mirror-device related rpc calls

The two calls mirror_addchild and mirror_removechild take only one child
for addition/removal. While this is enough for our md usage, for local
disk replacement in drbd8, we need to be able to specify both the data
and metadata device. This patch modifies these two rpc calls (and their
backend implementation and their usage in cmdlib) to take a list of
children to add/remove.

Reviewed-by: imsnah
parent a1f445d3
......@@ -135,7 +135,7 @@ class ServerObject(pb.Avatar):
return backend.ShutdownBlockDevice(bdev)
@staticmethod
def perspective_blockdev_addchild(params):
def perspective_blockdev_addchildren(params):
"""Add a child to a mirror device.
Note: this is only valid for mirror devices. It's the caller's duty
......@@ -144,13 +144,13 @@ class ServerObject(pb.Avatar):
"""
bdev_s, ndev_s = params
bdev = objects.Disk.FromDict(bdev_s)
ndev = objects.Disk.FromDict(ndev_s)
if bdev is None or ndev is None:
ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
if bdev is None or ndevs.count(None) > 0:
raise ValueError("can't unserialize data!")
return backend.MirrorAddChild(bdev, ndev)
return backend.MirrorAddChildren(bdev, ndevs)
@staticmethod
def perspective_blockdev_removechild(params):
def perspective_blockdev_removechildren(params):
"""Remove a child from a mirror device.
This is only valid for mirror devices, of course. It's the callers
......@@ -159,10 +159,10 @@ class ServerObject(pb.Avatar):
"""
bdev_s, ndev_s = params
bdev = objects.Disk.FromDict(bdev_s)
ndev = objects.Disk.FromDict(ndev_s)
if bdev is None or ndev is None:
ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
if bdev is None or ndevs.count(None) > 0:
raise ValueError("can't unserialize data!")
return backend.MirrorRemoveChild(bdev, ndev)
return backend.MirrorRemoveChildren(bdev, ndevs)
@staticmethod
def perspective_blockdev_getmirrorstatus(params):
......
......@@ -768,35 +768,33 @@ def ShutdownBlockDevice(disk):
return result
def MirrorAddChild(md_cdev, new_cdev):
"""Extend an MD raid1 array.
def MirrorAddChildren(parent_cdev, new_cdevs):
"""Extend a mirrored block device.
"""
md_bdev = _RecursiveFindBD(md_cdev, allow_partial=True)
if md_bdev is None:
logger.Error("Can't find md device")
parent_bdev = _RecursiveFindBD(parent_cdev, allow_partial=True)
if parent_bdev is None:
logger.Error("Can't find parent device")
return False
new_bdev = _RecursiveFindBD(new_cdev)
if new_bdev is None:
logger.Error("Can't find new device to add")
new_bdevs = [_RecursiveFindBD(disk) for disk in new_cdevs]
if new_bdevs.count(None) > 0:
logger.Error("Can't find new device(s) to add")
return False
new_bdev.Open()
md_bdev.AddChild(new_bdev)
parent_bdev.AddChildren(new_bdevs)
return True
def MirrorRemoveChild(md_cdev, new_cdev):
"""Reduce an MD raid1 array.
def MirrorRemoveChildren(parent_cdev, new_cdevs):
"""Shrink a mirrored block device.
"""
md_bdev = _RecursiveFindBD(md_cdev)
if md_bdev is None:
parent_bdev = _RecursiveFindBD(parent_cdev)
if parent_bdev is None:
return False
new_bdev = _RecursiveFindBD(new_cdev)
if new_bdev is None:
new_bdevs = [_RecursiveFindBD(disk) for disk in new_cdevs]
if new_bdevs.count(None) > 0:
return False
new_bdev.Open()
md_bdev.RemoveChild(new_bdev.dev_path)
parent_bdev.RemoveChildren(new_bdevs)
return True
......
......@@ -701,59 +701,71 @@ class MDRaid1(BlockDev):
return self.Shutdown()
def AddChild(self, device):
"""Add a new member to the md raid1.
def AddChildren(self, devices):
"""Add new member(s) to the md raid1.
"""
if self.minor is None and not self.Attach():
raise errors.BlockDeviceError("Can't attach to device")
if device.dev_path is None:
raise errors.BlockDeviceError("New child is not initialised")
result = utils.RunCmd(["mdadm", "-a", self.dev_path, device.dev_path])
args = ["mdadm", "-a", self.dev_path]
for dev in devices:
if dev.dev_path is None:
raise errors.BlockDeviceError("Child '%s' is not initialised" % dev)
dev.Open()
args.append(dev.dev_path)
result = utils.RunCmd(args)
if result.failed:
raise errors.BlockDeviceError("Failed to add new device to array: %s" %
result.output)
new_len = len(self._children) + 1
new_len = len(self._children) + len(devices)
result = utils.RunCmd(["mdadm", "--grow", self.dev_path, "-n", new_len])
if result.failed:
raise errors.BlockDeviceError("Can't grow md array: %s" %
result.output)
self._children.append(device)
self._children.extend(devices)
def RemoveChild(self, dev_path):
"""Remove member from the md raid1.
def RemoveChildren(self, devices):
"""Remove member(s) from the md raid1.
"""
if self.minor is None and not self.Attach():
raise errors.BlockDeviceError("Can't attach to device")
if len(self._children) == 1:
raise errors.BlockDeviceError("Can't reduce member when only one"
" child left")
for device in self._children:
if device.dev_path == dev_path:
break
else:
raise errors.BlockDeviceError("Can't find child with this path")
new_len = len(self._children) - 1
result = utils.RunCmd(["mdadm", "-f", self.dev_path, dev_path])
new_len = len(self._children) - len(devices)
if new_len < 1:
raise errors.BlockDeviceError("Can't reduce to less than one child")
args = ["mdadm", "-f", self.dev_path]
orig_devs = []
for dev in devices:
args.append(dev.dev_path)
for c in self._children:
if c.dev_path == dev.dev_path:
orig_devs.append(c)
break
else:
raise errors.BlockDeviceError("Can't find device '%s' for removal" %
dev)
result = utils.RunCmd(args)
if result.failed:
raise errors.BlockDeviceError("Failed to mark device as failed: %s" %
raise errors.BlockDeviceError("Failed to mark device(s) as failed: %s" %
result.output)
# it seems here we need a short delay for MD to update its
# superblocks
time.sleep(0.5)
result = utils.RunCmd(["mdadm", "-r", self.dev_path, dev_path])
args[1] = "-r"
result = utils.RunCmd(args)
if result.failed:
raise errors.BlockDeviceError("Failed to remove device from array:"
" %s" % result.output)
raise errors.BlockDeviceError("Failed to remove device(s) from array:"
" %s" % result.output)
result = utils.RunCmd(["mdadm", "--grow", "--force", self.dev_path,
"-n", new_len])
if result.failed:
raise errors.BlockDeviceError("Can't shrink md array: %s" %
result.output)
self._children.remove(device)
for dev in orig_devs:
self._children.remove(dev)
def GetStatus(self):
......
......@@ -3223,8 +3223,8 @@ class LUAddMDDRBDComponent(LogicalUnit):
# the device exists now
# call the primary node to add the mirror to md
logger.Info("adding new mirror component to md")
if not rpc.call_blockdev_addchild(instance.primary_node,
disk, new_drbd):
if not rpc.call_blockdev_addchildren(instance.primary_node,
disk, [new_drbd]):
logger.Error("Can't add mirror compoment to md!")
self.cfg.SetDiskID(new_drbd, remote_node)
if not rpc.call_blockdev_remove(remote_node, new_drbd):
......@@ -3316,8 +3316,8 @@ class LURemoveMDDRBDComponent(LogicalUnit):
child = self.child
logger.Info("remove mirror component")
self.cfg.SetDiskID(disk, instance.primary_node)
if not rpc.call_blockdev_removechild(instance.primary_node,
disk, child):
if not rpc.call_blockdev_removechildren(instance.primary_node,
disk, [child]):
raise errors.OpExecError("Can't remove child from mirror.")
for node in child.logical_id[:2]:
......@@ -3427,8 +3427,8 @@ class LUReplaceDisks(LogicalUnit):
# the device exists now
# call the primary node to add the mirror to md
logger.Info("adding new mirror component to md")
if not rpc.call_blockdev_addchild(instance.primary_node, dev,
new_drbd):
if not rpc.call_blockdev_addchildren(instance.primary_node, dev,
[new_drbd]):
logger.Error("Can't add mirror compoment to md!")
cfg.SetDiskID(new_drbd, remote_node)
if not rpc.call_blockdev_remove(remote_node, new_drbd):
......@@ -3462,8 +3462,8 @@ class LUReplaceDisks(LogicalUnit):
dev, child, new_drbd = iv_names[name]
logger.Info("remove mirror %s component" % name)
cfg.SetDiskID(dev, instance.primary_node)
if not rpc.call_blockdev_removechild(instance.primary_node,
dev, child):
if not rpc.call_blockdev_removechildren(instance.primary_node,
dev, [child]):
logger.Error("Can't remove child from mirror, aborting"
" *this device cleanup*.\nYou need to cleanup manually!!")
continue
......
......@@ -539,27 +539,27 @@ def call_blockdev_shutdown(node, disk):
return c.getresult().get(node, False)
def call_blockdev_addchild(node, bdev, ndev):
"""Request adding a new child to a (mirroring) device.
def call_blockdev_addchildren(node, bdev, ndevs):
"""Request adding a list of children to a (mirroring) device.
This is a single-node call.
"""
params = [bdev.ToDict(), ndev.ToDict()]
c = Client("blockdev_addchild", params)
params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
c = Client("blockdev_addchildren", params)
c.connect(node)
c.run()
return c.getresult().get(node, False)
def call_blockdev_removechild(node, bdev, ndev):
"""Request removing a new child from a (mirroring) device.
def call_blockdev_removechildren(node, bdev, ndevs):
"""Request removing a list of children from a (mirroring) device.
This is a single-node call.
"""
params = [bdev.ToDict(), ndev.ToDict()]
c = Client("blockdev_removechild", params)
params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
c = Client("blockdev_removechildren", params)
c.connect(node)
c.run()
return c.getresult().get(node, False)
......
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