Revision d4752785 lib/cmdlib.py

b/lib/cmdlib.py
10409 10409
    return list(iobj.all_nodes)
10410 10410

  
10411 10411

  
10412
class LUInstanceMultiAlloc(NoHooksLU):
10413
  """Allocates multiple instances at the same time.
10414

  
10415
  """
10416
  REQ_BGL = False
10417

  
10418
  def CheckArguments(self):
10419
    """Check arguments.
10420

  
10421
    """
10422
    nodes = []
10423
    for inst in self.op.instances:
10424
      if inst.iallocator is not None:
10425
        raise errors.OpPrereqError("iallocator are not allowed to be set on"
10426
                                   " instance objects", errors.ECODE_INVAL)
10427
      nodes.append(bool(inst.pnode))
10428
      if inst.disk_template in constants.DTS_INT_MIRROR:
10429
        nodes.append(bool(inst.snode))
10430

  
10431
    has_nodes = compat.any(nodes)
10432
    if compat.all(nodes) ^ has_nodes:
10433
      raise errors.OpPrereqError("There are instance objects providing"
10434
                                 " pnode/snode while others do not",
10435
                                 errors.ECODE_INVAL)
10436

  
10437
    if self.op.iallocator is None:
10438
      default_iallocator = self.cfg.GetDefaultIAllocator()
10439
      if default_iallocator and has_nodes:
10440
        self.op.iallocator = default_iallocator
10441
      else:
10442
        raise errors.OpPrereqError("No iallocator or nodes on the instances"
10443
                                   " given and no cluster-wide default"
10444
                                   " iallocator found; please specify either"
10445
                                   " an iallocator or nodes on the instances"
10446
                                   " or set a cluster-wide default iallocator",
10447
                                   errors.ECODE_INVAL)
10448

  
10449
    dups = utils.FindDuplicates([op.instance_name for op in self.op.instances])
10450
    if dups:
10451
      raise errors.OpPrereqError("There are duplicate instance names: %s" %
10452
                                 utils.CommaJoin(dups), errors.ECODE_INVAL)
10453

  
10454
  def ExpandNames(self):
10455
    """Calculate the locks.
10456

  
10457
    """
10458
    self.share_locks = _ShareAll()
10459
    self.needed_locks = {}
10460

  
10461
    if self.op.iallocator:
10462
      self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET
10463
      self.needed_locks[locking.LEVEL_NODE_RES] = locking.ALL_SET
10464
    else:
10465
      nodeslist = []
10466
      for inst in self.op.instances:
10467
        inst.pnode = _ExpandNodeName(self.cfg, inst.pnode)
10468
        nodeslist.append(inst.pnode)
10469
        if inst.snode is not None:
10470
          inst.snode = _ExpandNodeName(self.cfg, inst.snode)
10471
          nodeslist.append(inst.snode)
10472

  
10473
      self.needed_locks[locking.LEVEL_NODE] = nodeslist
10474
      # Lock resources of instance's primary and secondary nodes (copy to
10475
      # prevent accidential modification)
10476
      self.needed_locks[locking.LEVEL_NODE_RES] = list(nodeslist)
10477

  
10478
  def CheckPrereq(self):
10479
    """Check prerequisite.
10480

  
10481
    """
10482
    cluster = self.cfg.GetClusterInfo()
10483
    default_vg = self.cfg.GetVGName()
10484
    insts = [_CreateInstanceAllocRequest(op, _ComputeDisks(op, default_vg),
10485
                                         _ComputeNics(op, cluster, None,
10486
                                                      self.cfg, self.proc),
10487
                                         _ComputeFullBeParams(op, cluster))
10488
             for op in self.op.instances]
10489
    req = iallocator.IAReqMultiInstanceAlloc(instances=insts)
10490
    ial = iallocator.IAllocator(self.cfg, self.rpc, req)
10491

  
10492
    ial.Run(self.op.iallocator)
10493

  
10494
    if not ial.success:
10495
      raise errors.OpPrereqError("Can't compute nodes using"
10496
                                 " iallocator '%s': %s" %
10497
                                 (self.op.iallocator, ial.info),
10498
                                 errors.ECODE_NORES)
10499

  
10500
    self.ia_result = ial.result
10501

  
10502
    if self.op.dry_run:
10503
      self.dry_run_rsult = objects.FillDict(self._ConstructPartialResult(), {
10504
        constants.JOB_IDS_KEY: [],
10505
        })
10506

  
10507
  def _ConstructPartialResult(self):
10508
    """Contructs the partial result.
10509

  
10510
    """
10511
    (allocatable, failed) = self.ia_result
10512
    return {
10513
      opcodes.OpInstanceMultiAlloc.ALLOCATABLE_KEY:
10514
        map(compat.fst, allocatable),
10515
      opcodes.OpInstanceMultiAlloc.FAILED_KEY: failed,
10516
      }
10517

  
10518
  def Exec(self, feedback_fn):
10519
    """Executes the opcode.
10520

  
10521
    """
10522
    op2inst = dict((op.instance_name, op) for op in self.op.instances)
10523
    (allocatable, failed) = self.ia_result
10524

  
10525
    jobs = []
10526
    for (name, nodes) in allocatable:
10527
      op = op2inst.pop(name)
10528

  
10529
      if len(nodes) > 1:
10530
        (op.pnode, op.snode) = nodes
10531
      else:
10532
        (op.pnode,) = nodes
10533

  
10534
      jobs.append([op])
10535

  
10536
    missing = set(op2inst.keys()) - set(failed)
10537
    assert not missing, \
10538
      "Iallocator did return incomplete result: %s" % utils.CommaJoin(missing)
10539

  
10540
    return ResultWithJobs(jobs, **self._ConstructPartialResult())
10541

  
10542

  
10412 10543
def _CheckRADOSFreeSpace():
10413 10544
  """Compute disk size requirements inside the RADOS cluster.
10414 10545

  

Also available in: Unified diff