Commit 297b0cd3 authored by Iustin Pop's avatar Iustin Pop
Browse files

iallocator: add ht-checking for the request

Currently, we only ht-check the result value from the iallocator, and
we send whatever we happen to check manually in the LUs that call the

This is not good, as we have to duplicate checks in many places, and
still we might miss checks. So we add add ht information to the
per-request variables. As the cluster data is built in one place, the
iallocator code itself (and is more consistent), I didn't add checks
to that too.
Signed-off-by: default avatarIustin Pop <>
Reviewed-by: default avatarMichael Hanselmann <>
parent dd47a0f0
......@@ -205,19 +205,19 @@ in the ``request`` dictionary:
the name of the instance; if the request is a realocation, then this
name will be found in the list of instances (see below), otherwise
is the FQDN of the new instance
is the FQDN of the new instance; type *string*
how many nodes should the algorithm return; while this information
can be deduced from the instace's disk template, it's better if
this computation is left to Ganeti as then allocator scripts are
less sensitive to changes to the disk templates
less sensitive to changes to the disk templates; type *integer*
the total disk space that will be used by this instance on the
(new) nodes; again, this information can be computed from the list
of instance disks and its template type, but Ganeti is better
suited to compute it
suited to compute it; type *integer*
.. pyassert::
......@@ -274,13 +274,13 @@ Relocation:
a list of nodes to move the instance away from (note that with
Ganeti 2.0, this list will always contain a single node, the
current secondary of the instance)
current secondary of the instance); type *list of strings*
As for ``multi-relocate``, it needs the three following request
a list of instance names to relocate
a list of instance names to relocate; type *list of strings*
a string indicating the relocation mode; there are three possible
......@@ -292,13 +292,13 @@ arguments:
this argument is only accepted when ``reloc_mode``, as explained
above, is *change_group*; if present, it must either be the empty
list, or contain a list of group UUIDs that should be considered for
relocating instances to
relocating instances to; type *list of strings*
Finally, in the case of multi-evacuate, there's one single request
argument (in addition to ``type``):
the names of the nodes to be evacuated
the names of the nodes to be evacuated; type *list of strings*
Response message
......@@ -12020,11 +12020,13 @@ class IAllocator(object):
self.success = = self.result = None
(fn, keyset, self._result_check) = self._MODE_DATA[self.mode]
(fn, keydata, self._result_check) = self._MODE_DATA[self.mode]
except KeyError:
raise errors.ProgrammerError("Unknown mode '%s' passed to the"
" IAllocator" % self.mode)
keyset = [n for (n, _) in keydata]
for key in kwargs:
if key not in keyset:
raise errors.ProgrammerError("Invalid input parameter '%s' to"
......@@ -12035,7 +12037,7 @@ class IAllocator(object):
if key not in kwargs:
raise errors.ProgrammerError("Missing input parameter '%s' to"
" IAllocator" % key)
self._BuildInputData(compat.partial(fn, self))
self._BuildInputData(compat.partial(fn, self), keydata)
def _ComputeClusterData(self):
"""Compute the generic allocator input data.
......@@ -12310,7 +12312,7 @@ class IAllocator(object):
"target_groups": self.target_groups,
def _BuildInputData(self, fn):
def _BuildInputData(self, fn, keydata):
"""Build input data structures.
......@@ -12318,23 +12320,47 @@ class IAllocator(object):
request = fn()
request["type"] = self.mode
for keyname, keytype in keydata:
if keyname not in request:
raise errors.ProgrammerError("Request parameter %s is missing" %
val = request[keyname]
if not keytype(val):
raise errors.ProgrammerError("Request parameter %s doesn't pass"
" validation, value %s, expected"
" type %s" % (keyname, val, keytype))
self.in_data["request"] = request
self.in_text = serializer.Dump(self.in_data)
_STRING_LIST = ht.TListOf(ht.TString)
["name", "memory", "disks", "disk_template", "os", "tags", "nics",
"vcpus", "hypervisor"], ht.TList),
("name", ht.TString),
("memory", ht.TInt),
("disks", ht.TListOf(ht.TDict)),
("disk_template", ht.TString),
("os", ht.TString),
("tags", _STRING_LIST),
("nics", ht.TListOf(ht.TDict)),
("vcpus", ht.TInt),
("hypervisor", ht.TString),
], ht.TList),
(_AddRelocateInstance, ["name", "relocate_from"], ht.TList),
[("name", ht.TString), ("relocate_from", _STRING_LIST)],
(_AddEvacuateNodes, ["evac_nodes"],
(_AddEvacuateNodes, [("evac_nodes", _STRING_LIST)],
ht.TListOf(ht.TAnd(ht.TIsLength(2), _STRING_LIST))),
(_AddMultiRelocate, ["instances", "reloc_mode", "target_groups"],
(_AddMultiRelocate, [
("instances", _STRING_LIST),
("reloc_mode", ht.TElemOf(constants.IALLOCATOR_MRELOC_MODES)),
("target_groups", _STRING_LIST),
ht.TListOf(ht.TListOf(ht.TStrictDict(True, False, {
# pylint: disable-msg=E1101
# Class '...' has no 'OP_ID' member
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