Commit 31b836b8 authored by Thomas Thrainer's avatar Thomas Thrainer
Browse files

Extract node related logical units from cmdlib

All LUNode* classes are extracted to Common functions are moved
to if used by non-node logical units as well.
Signed-off-by: default avatarThomas Thrainer <>
Reviewed-by: default avatarBernardo Dal Seno <>
parent f380d53c
......@@ -313,6 +313,7 @@ cmdlib_PYTHON = \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
This diff is collapsed.
......@@ -37,6 +37,17 @@ from ganeti import ssconf
from ganeti import utils
# States of instance
#: Instance status in which an instance can be marked as offline/online
def _ExpandItemName(fn, name, kind):
"""Expand an item name.
......@@ -873,3 +884,131 @@ def _MapInstanceDisksToNodes(instances):
for inst in instances
for (node, vols) in inst.MapLVsByNode().items()
for vol in vols)
def _CheckParamsNotGlobal(params, glob_pars, kind, bad_levels, good_levels):
"""Make sure that none of the given paramters is global.
If a global parameter is found, an L{errors.OpPrereqError} exception is
raised. This is used to avoid setting global parameters for individual nodes.
@type params: dictionary
@param params: Parameters to check
@type glob_pars: dictionary
@param glob_pars: Forbidden parameters
@type kind: string
@param kind: Kind of parameters (e.g. "node")
@type bad_levels: string
@param bad_levels: Level(s) at which the parameters are forbidden (e.g.
@type good_levels: strings
@param good_levels: Level(s) at which the parameters are allowed (e.g.
"cluster or group")
used_globals = glob_pars.intersection(params)
if used_globals:
msg = ("The following %s parameters are global and cannot"
" be customized at %s level, please modify them at"
" %s level: %s" %
(kind, bad_levels, good_levels, utils.CommaJoin(used_globals)))
raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
def _IsExclusiveStorageEnabledNode(cfg, node):
"""Whether exclusive_storage is in effect for the given node.
@type cfg: L{config.ConfigWriter}
@param cfg: The cluster configuration
@type node: L{objects.Node}
@param node: The node
@rtype: bool
@return: The effective value of exclusive_storage
return cfg.GetNdParams(node)[constants.ND_EXCLUSIVE_STORAGE]
def _CheckInstanceState(lu, instance, req_states, msg=None):
"""Ensure that an instance is in one of the required states.
@param lu: the LU on behalf of which we make the check
@param instance: the instance to check
@param msg: if passed, should be a message to replace the default one
@raise errors.OpPrereqError: if the instance is not in the required state
if msg is None:
msg = ("can't use instance from outside %s states" %
if instance.admin_state not in req_states:
raise errors.OpPrereqError("Instance '%s' is marked to be %s, %s" %
(, instance.admin_state, msg),
if constants.ADMINST_UP not in req_states:
pnode = instance.primary_node
if not lu.cfg.GetNodeInfo(pnode).offline:
ins_l = lu.rpc.call_instance_list([pnode], [instance.hypervisor])[pnode]
ins_l.Raise("Can't contact node %s for instance information" % pnode,
prereq=True, ecode=errors.ECODE_ENVIRON)
if in ins_l.payload:
raise errors.OpPrereqError("Instance %s is running, %s" %
(, msg), errors.ECODE_STATE)
lu.LogWarning("Primary node offline, ignoring check that instance"
" is down")
def _CheckIAllocatorOrNode(lu, iallocator_slot, node_slot):
"""Check the sanity of iallocator and node arguments and use the
cluster-wide iallocator if appropriate.
Check that at most one of (iallocator, node) is specified. If none is
specified, or the iallocator is L{constants.DEFAULT_IALLOCATOR_SHORTCUT},
then the LU's opcode's iallocator slot is filled with the cluster-wide
default iallocator.
@type iallocator_slot: string
@param iallocator_slot: the name of the opcode iallocator slot
@type node_slot: string
@param node_slot: the name of the opcode target node slot
node = getattr(lu.op, node_slot, None)
ialloc = getattr(lu.op, iallocator_slot, None)
if node == []:
node = None
if node is not None and ialloc is not None:
raise errors.OpPrereqError("Do not specify both, iallocator and node",
elif ((node is None and ialloc is None) or
default_iallocator = lu.cfg.GetDefaultIAllocator()
if default_iallocator:
setattr(lu.op, iallocator_slot, default_iallocator)
raise errors.OpPrereqError("No iallocator or node given and no"
" cluster-wide default iallocator found;"
" please specify either an iallocator or a"
" node, or set a cluster-wide default"
" iallocator", errors.ECODE_INVAL)
def _FindFaultyInstanceDisks(cfg, rpc_runner, instance, node_name, prereq):
faulty = []
for dev in instance.disks:
cfg.SetDiskID(dev, node_name)
result = rpc_runner.call_blockdev_getmirrorstatus(node_name, (instance.disks,
result.Raise("Failed to get disk status from node %s" % node_name,
prereq=prereq, ecode=errors.ECODE_ENVIRON)
for idx, bdev_status in enumerate(result.payload):
if bdev_status and bdev_status.ldisk_status == constants.LDS_FAULTY:
return faulty
This diff is collapsed.
......@@ -109,7 +109,7 @@ class TestIAllocatorChecks(testutils.GanetiTestCase):
op = OpTest()
lu = TestLU(op)
c_i = lambda: cmdlib._CheckIAllocatorOrNode(lu, "iallocator", "node")
c_i = lambda: common._CheckIAllocatorOrNode(lu, "iallocator", "node")
# Neither node nor iallocator given
for n in (None, []):
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