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