5715 |
5715 |
|
5716 |
5716 |
return remote_node_name
|
5717 |
5717 |
|
|
5718 |
def _FindFaultyDisks(self, node_name):
|
|
5719 |
faulty = []
|
|
5720 |
|
|
5721 |
for dev in self.instance.disks:
|
|
5722 |
self.cfg.SetDiskID(dev, node_name)
|
|
5723 |
|
|
5724 |
result = self.rpc.call_blockdev_getmirrorstatus(node_name,
|
|
5725 |
self.instance.disks)
|
|
5726 |
result.Raise("Failed to get disk status from node %s" % node_name,
|
|
5727 |
prereq=True)
|
|
5728 |
|
|
5729 |
for idx, bdev_status in enumerate(result.payload):
|
|
5730 |
if bdev_status and bdev_status.ldisk_status == constants.LDS_FAULTY:
|
|
5731 |
faulty.append(idx)
|
|
5732 |
|
|
5733 |
return faulty
|
|
5734 |
|
5718 |
5735 |
def CheckPrereq(self):
|
5719 |
5736 |
"""Check prerequisites.
|
5720 |
5737 |
|
... | ... | |
5757 |
5774 |
raise errors.OpPrereqError("The specified node is already the"
|
5758 |
5775 |
" secondary node of the instance.")
|
5759 |
5776 |
|
5760 |
|
if self.mode == constants.REPLACE_DISK_PRI:
|
5761 |
|
self.target_node = self.instance.primary_node
|
5762 |
|
self.other_node = secondary_node
|
5763 |
|
check_nodes = [self.target_node, self.other_node]
|
|
5777 |
if self.mode == constants.REPLACE_DISK_AUTO:
|
|
5778 |
if self.disks:
|
|
5779 |
raise errors.OpPrereqError("Cannot specify disks to be replaced")
|
|
5780 |
|
|
5781 |
faulty_primary = self._FindFaultyDisks(self.instance.primary_node)
|
|
5782 |
faulty_secondary = self._FindFaultyDisks(secondary_node)
|
|
5783 |
|
|
5784 |
if faulty_primary and faulty_secondary:
|
|
5785 |
raise errors.OpPrereqError("Instance %s has faulty disks on more than"
|
|
5786 |
" one node and can not be repaired"
|
|
5787 |
" automatically" % self.instance_name)
|
|
5788 |
|
|
5789 |
if faulty_primary:
|
|
5790 |
self.disks = faulty_primary
|
|
5791 |
self.target_node = self.instance.primary_node
|
|
5792 |
self.other_node = secondary_node
|
|
5793 |
check_nodes = [self.target_node, self.other_node]
|
|
5794 |
elif faulty_secondary:
|
|
5795 |
self.disks = faulty_secondary
|
|
5796 |
self.target_node = secondary_node
|
|
5797 |
self.other_node = self.instance.primary_node
|
|
5798 |
check_nodes = [self.target_node, self.other_node]
|
|
5799 |
else:
|
|
5800 |
self.disks = []
|
|
5801 |
check_nodes = []
|
5764 |
5802 |
|
5765 |
|
elif self.mode == constants.REPLACE_DISK_SEC:
|
5766 |
|
self.target_node = secondary_node
|
5767 |
|
self.other_node = self.instance.primary_node
|
5768 |
|
check_nodes = [self.target_node, self.other_node]
|
|
5803 |
else:
|
|
5804 |
# Non-automatic modes
|
|
5805 |
if self.mode == constants.REPLACE_DISK_PRI:
|
|
5806 |
self.target_node = self.instance.primary_node
|
|
5807 |
self.other_node = secondary_node
|
|
5808 |
check_nodes = [self.target_node, self.other_node]
|
5769 |
5809 |
|
5770 |
|
elif self.mode == constants.REPLACE_DISK_CHG:
|
5771 |
|
self.new_node = remote_node
|
5772 |
|
self.other_node = self.instance.primary_node
|
5773 |
|
self.target_node = secondary_node
|
5774 |
|
check_nodes = [self.new_node, self.other_node]
|
|
5810 |
elif self.mode == constants.REPLACE_DISK_SEC:
|
|
5811 |
self.target_node = secondary_node
|
|
5812 |
self.other_node = self.instance.primary_node
|
|
5813 |
check_nodes = [self.target_node, self.other_node]
|
5775 |
5814 |
|
5776 |
|
_CheckNodeNotDrained(self.lu, remote_node)
|
|
5815 |
elif self.mode == constants.REPLACE_DISK_CHG:
|
|
5816 |
self.new_node = remote_node
|
|
5817 |
self.other_node = self.instance.primary_node
|
|
5818 |
self.target_node = secondary_node
|
|
5819 |
check_nodes = [self.new_node, self.other_node]
|
5777 |
5820 |
|
5778 |
|
else:
|
5779 |
|
raise errors.ProgrammerError("Unhandled disk replace mode (%s)" %
|
5780 |
|
self.mode)
|
|
5821 |
_CheckNodeNotDrained(self.lu, remote_node)
|
|
5822 |
|
|
5823 |
else:
|
|
5824 |
raise errors.ProgrammerError("Unhandled disk replace mode (%s)" %
|
|
5825 |
self.mode)
|
|
5826 |
|
|
5827 |
# If not specified all disks should be replaced
|
|
5828 |
if not self.disks:
|
|
5829 |
self.disks = range(len(self.instance.disks))
|
5781 |
5830 |
|
5782 |
5831 |
for node in check_nodes:
|
5783 |
5832 |
_CheckNodeOnline(self.lu, node)
|
5784 |
5833 |
|
5785 |
|
# If not specified all disks should be replaced
|
5786 |
|
if not self.disks:
|
5787 |
|
self.disks = range(len(self.instance.disks))
|
5788 |
|
|
5789 |
5834 |
# Check whether disks are valid
|
5790 |
5835 |
for disk_idx in self.disks:
|
5791 |
5836 |
self.instance.FindDisk(disk_idx)
|
... | ... | |
5805 |
5850 |
This dispatches the disk replacement to the appropriate handler.
|
5806 |
5851 |
|
5807 |
5852 |
"""
|
5808 |
|
feedback_fn("Replacing disks for %s" % self.instance.name)
|
|
5853 |
if not self.disks:
|
|
5854 |
feedback_fn("No disks need replacement")
|
|
5855 |
return
|
|
5856 |
|
|
5857 |
feedback_fn("Replacing disk(s) %s for %s" %
|
|
5858 |
(", ".join([str(i) for i in self.disks]), self.instance.name))
|
5809 |
5859 |
|
5810 |
5860 |
activate_disks = (not self.instance.admin_up)
|
5811 |
5861 |
|
... | ... | |
5814 |
5864 |
_StartInstanceDisks(self.lu, self.instance, True)
|
5815 |
5865 |
|
5816 |
5866 |
try:
|
5817 |
|
if self.mode == constants.REPLACE_DISK_CHG:
|
|
5867 |
# Should we replace the secondary node?
|
|
5868 |
if self.new_node is not None:
|
5818 |
5869 |
return self._ExecDrbd8Secondary()
|
5819 |
5870 |
else:
|
5820 |
5871 |
return self._ExecDrbd8DiskOnly()
|