Revision 153d9724
b/daemons/ganeti-noded | ||
---|---|---|
135 | 135 |
return backend.ShutdownBlockDevice(bdev) |
136 | 136 |
|
137 | 137 |
@staticmethod |
138 |
def perspective_blockdev_addchild(params): |
|
138 |
def perspective_blockdev_addchildren(params):
|
|
139 | 139 |
"""Add a child to a mirror device. |
140 | 140 |
|
141 | 141 |
Note: this is only valid for mirror devices. It's the caller's duty |
... | ... | |
144 | 144 |
""" |
145 | 145 |
bdev_s, ndev_s = params |
146 | 146 |
bdev = objects.Disk.FromDict(bdev_s) |
147 |
ndev = objects.Disk.FromDict(ndev_s)
|
|
148 |
if bdev is None or ndev is None:
|
|
147 |
ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
|
|
148 |
if bdev is None or ndevs.count(None) > 0:
|
|
149 | 149 |
raise ValueError("can't unserialize data!") |
150 |
return backend.MirrorAddChild(bdev, ndev)
|
|
150 |
return backend.MirrorAddChildren(bdev, ndevs)
|
|
151 | 151 |
|
152 | 152 |
@staticmethod |
153 |
def perspective_blockdev_removechild(params): |
|
153 |
def perspective_blockdev_removechildren(params):
|
|
154 | 154 |
"""Remove a child from a mirror device. |
155 | 155 |
|
156 | 156 |
This is only valid for mirror devices, of course. It's the callers |
... | ... | |
159 | 159 |
""" |
160 | 160 |
bdev_s, ndev_s = params |
161 | 161 |
bdev = objects.Disk.FromDict(bdev_s) |
162 |
ndev = objects.Disk.FromDict(ndev_s)
|
|
163 |
if bdev is None or ndev is None:
|
|
162 |
ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
|
|
163 |
if bdev is None or ndevs.count(None) > 0:
|
|
164 | 164 |
raise ValueError("can't unserialize data!") |
165 |
return backend.MirrorRemoveChild(bdev, ndev)
|
|
165 |
return backend.MirrorRemoveChildren(bdev, ndevs)
|
|
166 | 166 |
|
167 | 167 |
@staticmethod |
168 | 168 |
def perspective_blockdev_getmirrorstatus(params): |
b/lib/backend.py | ||
---|---|---|
768 | 768 |
return result |
769 | 769 |
|
770 | 770 |
|
771 |
def MirrorAddChild(md_cdev, new_cdev):
|
|
772 |
"""Extend an MD raid1 array.
|
|
771 |
def MirrorAddChildren(parent_cdev, new_cdevs):
|
|
772 |
"""Extend a mirrored block device.
|
|
773 | 773 |
|
774 | 774 |
""" |
775 |
md_bdev = _RecursiveFindBD(md_cdev, allow_partial=True)
|
|
776 |
if md_bdev is None:
|
|
777 |
logger.Error("Can't find md device")
|
|
775 |
parent_bdev = _RecursiveFindBD(parent_cdev, allow_partial=True)
|
|
776 |
if parent_bdev is None:
|
|
777 |
logger.Error("Can't find parent device")
|
|
778 | 778 |
return False |
779 |
new_bdev = _RecursiveFindBD(new_cdev)
|
|
780 |
if new_bdev is None:
|
|
781 |
logger.Error("Can't find new device to add") |
|
779 |
new_bdevs = [_RecursiveFindBD(disk) for disk in new_cdevs]
|
|
780 |
if new_bdevs.count(None) > 0:
|
|
781 |
logger.Error("Can't find new device(s) to add")
|
|
782 | 782 |
return False |
783 |
new_bdev.Open() |
|
784 |
md_bdev.AddChild(new_bdev) |
|
783 |
parent_bdev.AddChildren(new_bdevs) |
|
785 | 784 |
return True |
786 | 785 |
|
787 | 786 |
|
788 |
def MirrorRemoveChild(md_cdev, new_cdev):
|
|
789 |
"""Reduce an MD raid1 array.
|
|
787 |
def MirrorRemoveChildren(parent_cdev, new_cdevs):
|
|
788 |
"""Shrink a mirrored block device.
|
|
790 | 789 |
|
791 | 790 |
""" |
792 |
md_bdev = _RecursiveFindBD(md_cdev)
|
|
793 |
if md_bdev is None:
|
|
791 |
parent_bdev = _RecursiveFindBD(parent_cdev)
|
|
792 |
if parent_bdev is None:
|
|
794 | 793 |
return False |
795 |
new_bdev = _RecursiveFindBD(new_cdev)
|
|
796 |
if new_bdev is None:
|
|
794 |
new_bdevs = [_RecursiveFindBD(disk) for disk in new_cdevs]
|
|
795 |
if new_bdevs.count(None) > 0:
|
|
797 | 796 |
return False |
798 |
new_bdev.Open() |
|
799 |
md_bdev.RemoveChild(new_bdev.dev_path) |
|
797 |
parent_bdev.RemoveChildren(new_bdevs) |
|
800 | 798 |
return True |
801 | 799 |
|
802 | 800 |
|
b/lib/bdev.py | ||
---|---|---|
701 | 701 |
return self.Shutdown() |
702 | 702 |
|
703 | 703 |
|
704 |
def AddChild(self, device):
|
|
705 |
"""Add a new member to the md raid1.
|
|
704 |
def AddChildren(self, devices):
|
|
705 |
"""Add new member(s) to the md raid1.
|
|
706 | 706 |
|
707 | 707 |
""" |
708 | 708 |
if self.minor is None and not self.Attach(): |
709 | 709 |
raise errors.BlockDeviceError("Can't attach to device") |
710 |
if device.dev_path is None: |
|
711 |
raise errors.BlockDeviceError("New child is not initialised") |
|
712 |
result = utils.RunCmd(["mdadm", "-a", self.dev_path, device.dev_path]) |
|
710 |
|
|
711 |
args = ["mdadm", "-a", self.dev_path] |
|
712 |
for dev in devices: |
|
713 |
if dev.dev_path is None: |
|
714 |
raise errors.BlockDeviceError("Child '%s' is not initialised" % dev) |
|
715 |
dev.Open() |
|
716 |
args.append(dev.dev_path) |
|
717 |
result = utils.RunCmd(args) |
|
713 | 718 |
if result.failed: |
714 | 719 |
raise errors.BlockDeviceError("Failed to add new device to array: %s" % |
715 | 720 |
result.output) |
716 |
new_len = len(self._children) + 1
|
|
721 |
new_len = len(self._children) + len(devices)
|
|
717 | 722 |
result = utils.RunCmd(["mdadm", "--grow", self.dev_path, "-n", new_len]) |
718 | 723 |
if result.failed: |
719 | 724 |
raise errors.BlockDeviceError("Can't grow md array: %s" % |
720 | 725 |
result.output) |
721 |
self._children.append(device)
|
|
726 |
self._children.extend(devices)
|
|
722 | 727 |
|
723 | 728 |
|
724 |
def RemoveChild(self, dev_path):
|
|
725 |
"""Remove member from the md raid1. |
|
729 |
def RemoveChildren(self, devices):
|
|
730 |
"""Remove member(s) from the md raid1.
|
|
726 | 731 |
|
727 | 732 |
""" |
728 | 733 |
if self.minor is None and not self.Attach(): |
729 | 734 |
raise errors.BlockDeviceError("Can't attach to device") |
730 |
if len(self._children) == 1: |
|
731 |
raise errors.BlockDeviceError("Can't reduce member when only one" |
|
732 |
" child left") |
|
733 |
for device in self._children: |
|
734 |
if device.dev_path == dev_path: |
|
735 |
break |
|
736 |
else: |
|
737 |
raise errors.BlockDeviceError("Can't find child with this path") |
|
738 |
new_len = len(self._children) - 1 |
|
739 |
result = utils.RunCmd(["mdadm", "-f", self.dev_path, dev_path]) |
|
735 |
new_len = len(self._children) - len(devices) |
|
736 |
if new_len < 1: |
|
737 |
raise errors.BlockDeviceError("Can't reduce to less than one child") |
|
738 |
args = ["mdadm", "-f", self.dev_path] |
|
739 |
orig_devs = [] |
|
740 |
for dev in devices: |
|
741 |
args.append(dev.dev_path) |
|
742 |
for c in self._children: |
|
743 |
if c.dev_path == dev.dev_path: |
|
744 |
orig_devs.append(c) |
|
745 |
break |
|
746 |
else: |
|
747 |
raise errors.BlockDeviceError("Can't find device '%s' for removal" % |
|
748 |
dev) |
|
749 |
result = utils.RunCmd(args) |
|
740 | 750 |
if result.failed: |
741 |
raise errors.BlockDeviceError("Failed to mark device as failed: %s" % |
|
751 |
raise errors.BlockDeviceError("Failed to mark device(s) as failed: %s" %
|
|
742 | 752 |
result.output) |
743 | 753 |
|
744 | 754 |
# it seems here we need a short delay for MD to update its |
745 | 755 |
# superblocks |
746 | 756 |
time.sleep(0.5) |
747 |
result = utils.RunCmd(["mdadm", "-r", self.dev_path, dev_path]) |
|
757 |
args[1] = "-r" |
|
758 |
result = utils.RunCmd(args) |
|
748 | 759 |
if result.failed: |
749 |
raise errors.BlockDeviceError("Failed to remove device from array:" |
|
750 |
" %s" % result.output)
|
|
760 |
raise errors.BlockDeviceError("Failed to remove device(s) from array:"
|
|
761 |
" %s" % result.output) |
|
751 | 762 |
result = utils.RunCmd(["mdadm", "--grow", "--force", self.dev_path, |
752 | 763 |
"-n", new_len]) |
753 | 764 |
if result.failed: |
754 | 765 |
raise errors.BlockDeviceError("Can't shrink md array: %s" % |
755 | 766 |
result.output) |
756 |
self._children.remove(device) |
|
767 |
for dev in orig_devs: |
|
768 |
self._children.remove(dev) |
|
757 | 769 |
|
758 | 770 |
|
759 | 771 |
def GetStatus(self): |
b/lib/cmdlib.py | ||
---|---|---|
3223 | 3223 |
# the device exists now |
3224 | 3224 |
# call the primary node to add the mirror to md |
3225 | 3225 |
logger.Info("adding new mirror component to md") |
3226 |
if not rpc.call_blockdev_addchild(instance.primary_node, |
|
3227 |
disk, new_drbd):
|
|
3226 |
if not rpc.call_blockdev_addchildren(instance.primary_node,
|
|
3227 |
disk, [new_drbd]):
|
|
3228 | 3228 |
logger.Error("Can't add mirror compoment to md!") |
3229 | 3229 |
self.cfg.SetDiskID(new_drbd, remote_node) |
3230 | 3230 |
if not rpc.call_blockdev_remove(remote_node, new_drbd): |
... | ... | |
3316 | 3316 |
child = self.child |
3317 | 3317 |
logger.Info("remove mirror component") |
3318 | 3318 |
self.cfg.SetDiskID(disk, instance.primary_node) |
3319 |
if not rpc.call_blockdev_removechild(instance.primary_node, |
|
3320 |
disk, child):
|
|
3319 |
if not rpc.call_blockdev_removechildren(instance.primary_node,
|
|
3320 |
disk, [child]):
|
|
3321 | 3321 |
raise errors.OpExecError("Can't remove child from mirror.") |
3322 | 3322 |
|
3323 | 3323 |
for node in child.logical_id[:2]: |
... | ... | |
3427 | 3427 |
# the device exists now |
3428 | 3428 |
# call the primary node to add the mirror to md |
3429 | 3429 |
logger.Info("adding new mirror component to md") |
3430 |
if not rpc.call_blockdev_addchild(instance.primary_node, dev, |
|
3431 |
new_drbd):
|
|
3430 |
if not rpc.call_blockdev_addchildren(instance.primary_node, dev,
|
|
3431 |
[new_drbd]):
|
|
3432 | 3432 |
logger.Error("Can't add mirror compoment to md!") |
3433 | 3433 |
cfg.SetDiskID(new_drbd, remote_node) |
3434 | 3434 |
if not rpc.call_blockdev_remove(remote_node, new_drbd): |
... | ... | |
3462 | 3462 |
dev, child, new_drbd = iv_names[name] |
3463 | 3463 |
logger.Info("remove mirror %s component" % name) |
3464 | 3464 |
cfg.SetDiskID(dev, instance.primary_node) |
3465 |
if not rpc.call_blockdev_removechild(instance.primary_node, |
|
3466 |
dev, child):
|
|
3465 |
if not rpc.call_blockdev_removechildren(instance.primary_node,
|
|
3466 |
dev, [child]):
|
|
3467 | 3467 |
logger.Error("Can't remove child from mirror, aborting" |
3468 | 3468 |
" *this device cleanup*.\nYou need to cleanup manually!!") |
3469 | 3469 |
continue |
b/lib/rpc.py | ||
---|---|---|
539 | 539 |
return c.getresult().get(node, False) |
540 | 540 |
|
541 | 541 |
|
542 |
def call_blockdev_addchild(node, bdev, ndev):
|
|
543 |
"""Request adding a new child to a (mirroring) device.
|
|
542 |
def call_blockdev_addchildren(node, bdev, ndevs):
|
|
543 |
"""Request adding a list of children to a (mirroring) device.
|
|
544 | 544 |
|
545 | 545 |
This is a single-node call. |
546 | 546 |
|
547 | 547 |
""" |
548 |
params = [bdev.ToDict(), ndev.ToDict()]
|
|
549 |
c = Client("blockdev_addchild", params) |
|
548 |
params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
|
|
549 |
c = Client("blockdev_addchildren", params)
|
|
550 | 550 |
c.connect(node) |
551 | 551 |
c.run() |
552 | 552 |
return c.getresult().get(node, False) |
553 | 553 |
|
554 | 554 |
|
555 |
def call_blockdev_removechild(node, bdev, ndev):
|
|
556 |
"""Request removing a new child from a (mirroring) device.
|
|
555 |
def call_blockdev_removechildren(node, bdev, ndevs):
|
|
556 |
"""Request removing a list of children from a (mirroring) device.
|
|
557 | 557 |
|
558 | 558 |
This is a single-node call. |
559 | 559 |
|
560 | 560 |
""" |
561 |
params = [bdev.ToDict(), ndev.ToDict()]
|
|
562 |
c = Client("blockdev_removechild", params) |
|
561 |
params = [bdev.ToDict(), [disk.ToDict() for disk in ndevs]]
|
|
562 |
c = Client("blockdev_removechildren", params)
|
|
563 | 563 |
c.connect(node) |
564 | 564 |
c.run() |
565 | 565 |
return c.getresult().get(node, False) |
Also available in: Unified diff