Commit 776b6291 authored by René Nussbaumer's avatar René Nussbaumer
Browse files

Rework the required_nodes field



This was used to verify the result of instance allocation. However, this
is not logic which belongs to the cmdlib rather than to the iallocator
request itself. So abstract it by its own function. And update the
ValidateResult accordingly.
Signed-off-by: default avatarRené Nussbaumer <rn@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent 52f93ffd
......@@ -7113,19 +7113,13 @@ class LUInstanceRecreateDisks(LogicalUnit):
 
ial.Run(self.op.iallocator)
 
assert ial.required_nodes == len(self.instance.all_nodes)
assert req.RequiredNodes() == len(self.instance.all_nodes)
 
if not ial.success:
raise errors.OpPrereqError("Can't compute nodes using iallocator '%s':"
" %s" % (self.op.iallocator, ial.info),
errors.ECODE_NORES)
 
if len(ial.result) != ial.required_nodes:
raise errors.OpPrereqError("iallocator '%s' returned invalid number"
" of nodes (%s), required %s" %
(self.op.iallocator, len(ial.result),
ial.required_nodes), errors.ECODE_FAULT)
self.op.nodes = ial.result
self.LogInfo("Selected nodes for instance %s via iallocator %s: %s",
self.op.instance_name, self.op.iallocator,
......@@ -8260,11 +8254,6 @@ class TLMigrateInstance(Tasklet):
" iallocator '%s': %s" %
(self.lu.op.iallocator, ial.info),
errors.ECODE_NORES)
if len(ial.result) != ial.required_nodes:
raise errors.OpPrereqError("iallocator '%s' returned invalid number"
" of nodes (%s), required %s" %
(self.lu.op.iallocator, len(ial.result),
ial.required_nodes), errors.ECODE_FAULT)
self.target_node = ial.result[0]
self.lu.LogInfo("Selected nodes for instance %s via iallocator %s: %s",
self.instance_name, self.lu.op.iallocator,
......@@ -9526,16 +9515,14 @@ class LUInstanceCreate(LogicalUnit):
" iallocator '%s': %s" %
(self.op.iallocator, ial.info),
errors.ECODE_NORES)
if len(ial.result) != ial.required_nodes:
raise errors.OpPrereqError("iallocator '%s' returned invalid number"
" of nodes (%s), required %s" %
(self.op.iallocator, len(ial.result),
ial.required_nodes), errors.ECODE_FAULT)
self.op.pnode = ial.result[0]
self.LogInfo("Selected nodes for instance %s via iallocator %s: %s",
self.op.instance_name, self.op.iallocator,
utils.CommaJoin(ial.result))
if ial.required_nodes == 2:
assert req.RequiredNodes() in (1, 2), "Wrong node count from iallocator"
if req.RequiredNodes() == 2:
self.op.snode = ial.result[1]
 
def BuildHooksEnv(self):
......@@ -10642,13 +10629,6 @@ class TLReplaceDisks(Tasklet):
" %s" % (iallocator_name, ial.info),
errors.ECODE_NORES)
 
if len(ial.result) != ial.required_nodes:
raise errors.OpPrereqError("iallocator '%s' returned invalid number"
" of nodes (%s), required %s" %
(iallocator_name,
len(ial.result), ial.required_nodes),
errors.ECODE_FAULT)
remote_node_name = ial.result[0]
 
lu.LogInfo("Selected new secondary for instance '%s': %s",
......
......@@ -168,6 +168,12 @@ class ParameterError(GenericError):
"""
class ResultValidationError(GenericError):
"""The iallocation results fails validation.
"""
class OpPrereqError(GenericError):
"""Prerequisites for the OpCode are not fulfilled.
......
......@@ -78,9 +78,7 @@ class IARequestBase(objectutils.ValidatedSlots):
__metaclass__ = _AutoReqParam
MODE = NotImplemented
REQ_PARAMS = [
("required_nodes", ht.TPositiveInt)
]
REQ_PARAMS = []
REQ_RESULT = NotImplemented
def __init__(self, **kwargs):
......@@ -92,7 +90,6 @@ class IARequestBase(objectutils.ValidatedSlots):
REQ_PARAMS attribute for this class.
"""
self.required_nodes = 0
objectutils.ValidatedSlots.__init__(self, **kwargs)
self.Validate()
......@@ -128,13 +125,13 @@ class IARequestBase(objectutils.ValidatedSlots):
@param ia: The IAllocator instance
@param result: The IAllocator run result
@returns: If it validates
@raises ResultValidationError: If validation fails
"""
if not (ia.success and self.REQ_RESULT(result)):
raise errors.OpExecError("Iallocator returned invalid result,"
" expected %s, got %s" %
(self.REQ_RESULT, result))
raise errors.ResultValidationError("iallocator returned invalid result,"
" expected %s, got %s" %
(self.REQ_RESULT, result))
class IAReqInstanceAlloc(IARequestBase):
......@@ -157,6 +154,15 @@ class IAReqInstanceAlloc(IARequestBase):
]
REQ_RESULT = ht.TList
def RequiredNodes(self):
"""Calculates the required nodes based on the disk_template.
"""
if self.disk_template in constants.DTS_INT_MIRROR:
return 2
else:
return 1
def GetRequest(self, cfg):
"""Requests a new instance.
......@@ -166,11 +172,6 @@ class IAReqInstanceAlloc(IARequestBase):
"""
disk_space = gmi.ComputeDiskSize(self.disk_template, self.disks)
if self.disk_template in constants.DTS_INT_MIRROR:
self.required_nodes = 2
else:
self.required_nodes = 1
return {
"name": self.name,
"disk_template": self.disk_template,
......@@ -182,10 +183,21 @@ class IAReqInstanceAlloc(IARequestBase):
"disks": self.disks,
"disk_space_total": disk_space,
"nics": self.nics,
"required_nodes": self.required_nodes,
"required_nodes": self.RequiredNodes(),
"hypervisor": self.hypervisor,
}
def ValidateResult(self, ia, result):
"""Validates an single instance allocation request.
"""
IARequestBase.ValidateResult(self, ia, result)
if len(result) != self.RequiredNodes():
raise errors.ResultValidationError("iallocator returned invalid number"
" of nodes (%s), required %s" %
(len(result), self.RequiredNodes()))
class IAReqMultiInstanceAlloc(IARequestBase):
"""An multi instance allocation request.
......@@ -244,14 +256,13 @@ class IAReqRelocate(IARequestBase):
raise errors.OpPrereqError("Instance has not exactly one secondary node",
errors.ECODE_STATE)
self.required_nodes = 1
disk_sizes = [{constants.IDISK_SIZE: disk.size} for disk in instance.disks]
disk_space = gmi.ComputeDiskSize(instance.disk_template, disk_sizes)
return {
"name": self.name,
"disk_space_total": disk_space,
"required_nodes": self.required_nodes,
"required_nodes": 1,
"relocate_from": self.relocate_from,
}
......@@ -259,6 +270,8 @@ class IAReqRelocate(IARequestBase):
"""Validates the result of an relocation request.
"""
IARequestBase.ValidateResult(self, ia, result)
node2group = dict((name, ndata["group"])
for (name, ndata) in ia.in_data["nodes"].items())
......@@ -270,10 +283,11 @@ class IAReqRelocate(IARequestBase):
result_groups = fn(result + [instance.primary_node])
if ia.success and not set(result_groups).issubset(request_groups):
raise errors.OpExecError("Groups of nodes returned by iallocator (%s)"
" differ from original groups (%s)" %
(utils.CommaJoin(result_groups),
utils.CommaJoin(request_groups)))
raise errors.ResultValidationError("Groups of nodes returned by"
"iallocator (%s) differ from original"
" groups (%s)" %
(utils.CommaJoin(result_groups),
utils.CommaJoin(request_groups)))
@staticmethod
def _NodesToGroups(node2group, groups, nodes):
......@@ -591,7 +605,6 @@ class IAllocator(object):
result = call_fn(self.cfg.GetMasterNode(), name, self.in_text)
result.Raise("Failure while running the iallocator script")
self.required_nodes = self.req.required_nodes
self.out_text = result.payload
if validate:
self._ValidateResult()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment