Revision 942be002

b/lib/cmdlib.py
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()
b/lib/constants.py
254 254
REPLACE_DISK_PRI = "replace_on_primary"    # replace disks on primary
255 255
REPLACE_DISK_SEC = "replace_on_secondary"  # replace disks on secondary
256 256
REPLACE_DISK_CHG = "replace_new_secondary" # change secondary node
257
REPLACE_DISK_AUTO = "replace_auto"
257 258

  
258 259
# lock recalculate mode
259 260
LOCKS_REPLACE = 'replace'

Also available in: Unified diff