Revision 735e1318 lib/cmdlib.py

b/lib/cmdlib.py
6901 6901
  HTYPE = constants.HTYPE_INSTANCE
6902 6902
  REQ_BGL = False
6903 6903

  
6904
  _MODIFYABLE = frozenset([
6905
    constants.IDISK_SIZE,
6906
    constants.IDISK_MODE,
6907
    ])
6908

  
6909
  # New or changed disk parameters may have different semantics
6910
  assert constants.IDISK_PARAMS == (_MODIFYABLE | frozenset([
6911
    constants.IDISK_ADOPT,
6912

  
6913
    # TODO: Implement support changing VG while recreating
6914
    constants.IDISK_VG,
6915
    constants.IDISK_METAVG,
6916
    ]))
6917

  
6904 6918
  def CheckArguments(self):
6905
    # normalise the disk list
6906
    self.op.disks = sorted(frozenset(self.op.disks))
6919
    if self.op.disks and ht.TPositiveInt(self.op.disks[0]):
6920
      # Normalize and convert deprecated list of disk indices
6921
      self.op.disks = [(idx, {}) for idx in sorted(frozenset(self.op.disks))]
6922

  
6923
    duplicates = utils.FindDuplicates(map(compat.fst, self.op.disks))
6924
    if duplicates:
6925
      raise errors.OpPrereqError("Some disks have been specified more than"
6926
                                 " once: %s" % utils.CommaJoin(duplicates),
6927
                                 errors.ECODE_INVAL)
6928

  
6929
    for (idx, params) in self.op.disks:
6930
      utils.ForceDictType(params, constants.IDISK_PARAMS_TYPES)
6931
      unsupported = frozenset(params.keys()) - self._MODIFYABLE
6932
      if unsupported:
6933
        raise errors.OpPrereqError("Parameters for disk %s try to change"
6934
                                   " unmodifyable parameter(s): %s" %
6935
                                   (idx, utils.CommaJoin(unsupported)),
6936
                                   errors.ECODE_INVAL)
6907 6937

  
6908 6938
  def ExpandNames(self):
6909 6939
    self._ExpandAndLockInstance()
......
6969 6999
    if instance.disk_template == constants.DT_DISKLESS:
6970 7000
      raise errors.OpPrereqError("Instance '%s' has no disks" %
6971 7001
                                 self.op.instance_name, errors.ECODE_INVAL)
7002

  
6972 7003
    # if we replace nodes *and* the old primary is offline, we don't
6973 7004
    # check
6974 7005
    assert instance.primary_node in self.owned_locks(locking.LEVEL_NODE)
......
6978 7009
      _CheckInstanceState(self, instance, INSTANCE_NOT_RUNNING,
6979 7010
                          msg="cannot recreate disks")
6980 7011

  
6981
    if not self.op.disks:
6982
      self.op.disks = range(len(instance.disks))
7012
    if self.op.disks:
7013
      self.disks = dict(self.op.disks)
6983 7014
    else:
6984
      for idx in self.op.disks:
6985
        if idx >= len(instance.disks):
6986
          raise errors.OpPrereqError("Invalid disk index '%s'" % idx,
6987
                                     errors.ECODE_INVAL)
6988
    if self.op.disks != range(len(instance.disks)) and self.op.nodes:
7015
      self.disks = dict((idx, {}) for idx in range(len(instance.disks)))
7016

  
7017
    maxidx = max(self.disks.keys())
7018
    if maxidx >= len(instance.disks):
7019
      raise errors.OpPrereqError("Invalid disk index '%s'" % maxidx,
7020
                                 errors.ECODE_INVAL)
7021

  
7022
    if (self.op.nodes and
7023
        sorted(self.disks.keys()) != range(len(instance.disks))):
6989 7024
      raise errors.OpPrereqError("Can't recreate disks partially and"
6990 7025
                                 " change the nodes at the same time",
6991 7026
                                 errors.ECODE_INVAL)
7027

  
6992 7028
    self.instance = instance
6993 7029

  
6994 7030
  def Exec(self, feedback_fn):
......
7001 7037
            self.owned_locks(locking.LEVEL_NODE_RES))
7002 7038

  
7003 7039
    to_skip = []
7004
    mods = [] # keeps track of needed logical_id changes
7040
    mods = [] # keeps track of needed changes
7005 7041

  
7006 7042
    for idx, disk in enumerate(instance.disks):
7007
      if idx not in self.op.disks: # disk idx has not been passed in
7043
      try:
7044
        changes = self.disks[idx]
7045
      except KeyError:
7046
        # Disk should not be recreated
7008 7047
        to_skip.append(idx)
7009 7048
        continue
7049

  
7010 7050
      # update secondaries for disks, if needed
7011
      if self.op.nodes:
7012
        if disk.dev_type == constants.LD_DRBD8:
7013
          # need to update the nodes and minors
7014
          assert len(self.op.nodes) == 2
7015
          assert len(disk.logical_id) == 6 # otherwise disk internals
7016
                                           # have changed
7017
          (_, _, old_port, _, _, old_secret) = disk.logical_id
7018
          new_minors = self.cfg.AllocateDRBDMinor(self.op.nodes, instance.name)
7019
          new_id = (self.op.nodes[0], self.op.nodes[1], old_port,
7020
                    new_minors[0], new_minors[1], old_secret)
7021
          assert len(disk.logical_id) == len(new_id)
7022
          mods.append((idx, new_id))
7051
      if self.op.nodes and disk.dev_type == constants.LD_DRBD8:
7052
        # need to update the nodes and minors
7053
        assert len(self.op.nodes) == 2
7054
        assert len(disk.logical_id) == 6 # otherwise disk internals
7055
                                         # have changed
7056
        (_, _, old_port, _, _, old_secret) = disk.logical_id
7057
        new_minors = self.cfg.AllocateDRBDMinor(self.op.nodes, instance.name)
7058
        new_id = (self.op.nodes[0], self.op.nodes[1], old_port,
7059
                  new_minors[0], new_minors[1], old_secret)
7060
        assert len(disk.logical_id) == len(new_id)
7061
      else:
7062
        new_id = None
7063

  
7064
      mods.append((idx, new_id, changes))
7023 7065

  
7024 7066
    # now that we have passed all asserts above, we can apply the mods
7025 7067
    # in a single run (to avoid partial changes)
7026
    for idx, new_id in mods:
7027
      instance.disks[idx].logical_id = new_id
7068
    for idx, new_id, changes in mods:
7069
      disk = instance.disks[idx]
7070
      if new_id is not None:
7071
        assert disk.dev_type == constants.LD_DRBD8
7072
        disk.logical_id = new_id
7073
      if changes:
7074
        disk.Update(size=changes.get(constants.IDISK_SIZE, None),
7075
                    mode=changes.get(constants.IDISK_MODE, None))
7028 7076

  
7029 7077
    # change primary node, if needed
7030 7078
    if self.op.nodes:

Also available in: Unified diff