Revision c8a96ae7 lib/cmdlib.py

b/lib/cmdlib.py
5440 5440
  HTYPE = constants.HTYPE_INSTANCE
5441 5441
  REQ_BGL = False
5442 5442

  
5443
  def CheckArguments(self):
5444
    # normalise the disk list
5445
    self.op.disks = sorted(frozenset(self.op.disks))
5446

  
5443 5447
  def ExpandNames(self):
5444 5448
    self._ExpandAndLockInstance()
5449
    self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_APPEND
5450
    if self.op.nodes:
5451
      self.op.nodes = [_ExpandNodeName(self.cfg, n) for n in self.op.nodes]
5452
      self.needed_locks[locking.LEVEL_NODE] = list(self.op.nodes)
5453
    else:
5454
      self.needed_locks[locking.LEVEL_NODE] = []
5455

  
5456
  def DeclareLocks(self, level):
5457
    if level == locking.LEVEL_NODE:
5458
      # if we replace the nodes, we only need to lock the old primary,
5459
      # otherwise we need to lock all nodes for disk re-creation
5460
      primary_only = bool(self.op.nodes)
5461
      self._LockInstancesNodes(primary_only=primary_only)
5445 5462

  
5446 5463
  def BuildHooksEnv(self):
5447 5464
    """Build hooks env.
......
5462 5479
    instance = self.cfg.GetInstanceInfo(self.op.instance_name)
5463 5480
    assert instance is not None, \
5464 5481
      "Cannot retrieve locked instance %s" % self.op.instance_name
5465
    _CheckNodeOnline(self, instance.primary_node)
5482
    if self.op.nodes:
5483
      if len(self.op.nodes) != len(instance.all_nodes):
5484
        raise errors.OpPrereqError("Instance %s currently has %d nodes, but"
5485
                                   " %d replacement nodes were specified" %
5486
                                   (instance.name, len(instance.all_nodes),
5487
                                    len(self.op.nodes)),
5488
                                   errors.ECODE_INVAL)
5489
      assert instance.disk_template != constants.DT_DRBD8 or \
5490
          len(self.op.nodes) == 2
5491
      assert instance.disk_template != constants.DT_PLAIN or \
5492
          len(self.op.nodes) == 1
5493
      primary_node = self.op.nodes[0]
5494
    else:
5495
      primary_node = instance.primary_node
5496
    _CheckNodeOnline(self, primary_node)
5466 5497

  
5467 5498
    if instance.disk_template == constants.DT_DISKLESS:
5468 5499
      raise errors.OpPrereqError("Instance '%s' has no disks" %
5469 5500
                                 self.op.instance_name, errors.ECODE_INVAL)
5470
    _CheckInstanceDown(self, instance, "cannot recreate disks")
5501
    # if we replace nodes *and* the old primary is offline, we don't
5502
    # check
5503
    assert instance.primary_node in self.needed_locks[locking.LEVEL_NODE]
5504
    old_pnode = self.cfg.GetNodeInfo(instance.primary_node)
5505
    if not (self.op.nodes and old_pnode.offline):
5506
      _CheckInstanceDown(self, instance, "cannot recreate disks")
5471 5507

  
5472 5508
    if not self.op.disks:
5473 5509
      self.op.disks = range(len(instance.disks))
......
5476 5512
        if idx >= len(instance.disks):
5477 5513
          raise errors.OpPrereqError("Invalid disk index passed '%s'" % idx,
5478 5514
                                     errors.ECODE_INVAL)
5479

  
5515
    if self.op.disks != range(len(instance.disks)) and self.op.nodes:
5516
      raise errors.OpPrereqError("Can't recreate disks partially and"
5517
                                 " change the nodes at the same time",
5518
                                 errors.ECODE_INVAL)
5480 5519
    self.instance = instance
5481 5520

  
5482 5521
  def Exec(self, feedback_fn):
5483 5522
    """Recreate the disks.
5484 5523

  
5485 5524
    """
5525
    # change primary node, if needed
5526
    if self.op.nodes:
5527
      self.instance.primary_node = self.op.nodes[0]
5528
      self.LogWarning("Changing the instance's nodes, you will have to"
5529
                      " remove any disks left on the older nodes manually")
5530

  
5486 5531
    to_skip = []
5487
    for idx, _ in enumerate(self.instance.disks):
5532
    for idx, disk in enumerate(self.instance.disks):
5488 5533
      if idx not in self.op.disks: # disk idx has not been passed in
5489 5534
        to_skip.append(idx)
5490 5535
        continue
5536
      # update secondaries for disks, if needed
5537
      if self.op.nodes:
5538
        if disk.dev_type == constants.LD_DRBD8:
5539
          # need to update the nodes
5540
          assert len(self.op.nodes) == 2
5541
          logical_id = list(disk.logical_id)
5542
          logical_id[0] = self.op.nodes[0]
5543
          logical_id[1] = self.op.nodes[1]
5544
          disk.logical_id = tuple(logical_id)
5545

  
5546
    if self.op.nodes:
5547
      self.cfg.Update(self.instance, feedback_fn)
5491 5548

  
5492 5549
    _CreateDisks(self, self.instance, to_skip=to_skip)
5493 5550

  

Also available in: Unified diff