Commit f380d53c authored by Thomas Thrainer's avatar Thomas Thrainer
Browse files

Extract group related logial units from cmdlib

All LUGroup* classes are moved to Common functions are
extracted to
Signed-off-by: default avatarThomas Thrainer <>
Reviewed-by: default avatarBernardo Dal Seno <>
parent 7352d33b
......@@ -312,6 +312,7 @@ cmdlib_PYTHON = \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
lib/cmdlib/ \
This diff is collapsed.
......@@ -20,14 +20,17 @@
"""Common functions used by multiple logical units."""
import copy
import os
from ganeti import compat
from ganeti import constants
from ganeti import errors
from ganeti import hypervisor
from ganeti import locking
from ganeti import objects
from ganeti import opcodes
from ganeti import pathutils
from ganeti import rpc
from ganeti import ssconf
......@@ -722,3 +725,151 @@ def _FilterVmNodes(lu, nodenames):
vm_nodes = frozenset(lu.cfg.GetNonVmCapableNodeList())
return [name for name in nodenames if name not in vm_nodes]
def _GetDefaultIAllocator(cfg, ialloc):
"""Decides on which iallocator to use.
@type cfg: L{config.ConfigWriter}
@param cfg: Cluster configuration object
@type ialloc: string or None
@param ialloc: Iallocator specified in opcode
@rtype: string
@return: Iallocator name
if not ialloc:
# Use default iallocator
ialloc = cfg.GetDefaultIAllocator()
if not ialloc:
raise errors.OpPrereqError("No iallocator was specified, neither in the"
" opcode nor as a cluster-wide default",
return ialloc
def _CheckInstancesNodeGroups(cfg, instances, owned_groups, owned_nodes,
"""Checks if node groups for locked instances are still correct.
@type cfg: L{config.ConfigWriter}
@param cfg: Cluster configuration
@type instances: dict; string as key, L{objects.Instance} as value
@param instances: Dictionary, instance name as key, instance object as value
@type owned_groups: iterable of string
@param owned_groups: List of owned groups
@type owned_nodes: iterable of string
@param owned_nodes: List of owned nodes
@type cur_group_uuid: string or None
@param cur_group_uuid: Optional group UUID to check against instance's groups
for (name, inst) in instances.items():
assert owned_nodes.issuperset(inst.all_nodes), \
"Instance %s's nodes changed while we kept the lock" % name
inst_groups = _CheckInstanceNodeGroups(cfg, name, owned_groups)
assert cur_group_uuid is None or cur_group_uuid in inst_groups, \
"Instance %s has no node in group %s" % (name, cur_group_uuid)
def _CheckInstanceNodeGroups(cfg, instance_name, owned_groups,
"""Checks if the owned node groups are still correct for an instance.
@type cfg: L{config.ConfigWriter}
@param cfg: The cluster configuration
@type instance_name: string
@param instance_name: Instance name
@type owned_groups: set or frozenset
@param owned_groups: List of currently owned node groups
@type primary_only: boolean
@param primary_only: Whether to check node groups for only the primary node
inst_groups = cfg.GetInstanceNodeGroups(instance_name, primary_only)
if not owned_groups.issuperset(inst_groups):
raise errors.OpPrereqError("Instance %s's node groups changed since"
" locks were acquired, current groups are"
" are '%s', owning groups '%s'; retry the"
" operation" %
return inst_groups
def _LoadNodeEvacResult(lu, alloc_result, early_release, use_nodes):
"""Unpacks the result of change-group and node-evacuate iallocator requests.
Iallocator modes L{constants.IALLOCATOR_MODE_NODE_EVAC} and
@type lu: L{LogicalUnit}
@param lu: Logical unit instance
@type alloc_result: tuple/list
@param alloc_result: Result from iallocator
@type early_release: bool
@param early_release: Whether to release locks early if possible
@type use_nodes: bool
@param use_nodes: Whether to display node names instead of groups
(moved, failed, jobs) = alloc_result
if failed:
failreason = utils.CommaJoin("%s (%s)" % (name, reason)
for (name, reason) in failed)
lu.LogWarning("Unable to evacuate instances %s", failreason)
raise errors.OpExecError("Unable to evacuate instances %s" % failreason)
if moved:
lu.LogInfo("Instances to be moved: %s",
utils.CommaJoin("%s (to %s)" %
(name, _NodeEvacDest(use_nodes, group, nodes))
for (name, group, nodes) in moved))
return [map(compat.partial(_SetOpEarlyRelease, early_release),
map(opcodes.OpCode.LoadOpCode, ops))
for ops in jobs]
def _NodeEvacDest(use_nodes, group, nodes):
"""Returns group or nodes depending on caller's choice.
if use_nodes:
return utils.CommaJoin(nodes)
return group
def _SetOpEarlyRelease(early_release, op):
"""Sets C{early_release} flag on opcodes if available.
op.early_release = early_release
except AttributeError:
assert not isinstance(op, opcodes.OpInstanceReplaceDisks)
return op
def _MapInstanceDisksToNodes(instances):
"""Creates a map from (node, volume) to instance name.
@type instances: list of L{objects.Instance}
@rtype: dict; tuple of (node name, volume name) as key, instance name as value
return dict(((node, vol),
for inst in instances
for (node, vols) in inst.MapLVsByNode().items()
for vol in vols)
This diff is collapsed.
......@@ -35,6 +35,7 @@ from ganeti import constants
from ganeti import mcpu
from ganeti import cmdlib
from ganeti.cmdlib import cluster
from ganeti.cmdlib import group
from ganeti.cmdlib import common
from ganeti import opcodes
from ganeti import errors
......@@ -210,19 +211,19 @@ class TestLUGroupAssignNodes(unittest.TestCase):
# Test first with the existing state.
(new, prev) = \
self.assertEqual([], new)
self.assertEqual(set(["inst3b", "inst3c"]), set(prev))
# And now some changes.
(new, prev) = \
self.assertEqual(set(["inst1a", "inst1b"]), set(new))
self.assertEqual(set(["inst3c"]), set(prev))
......@@ -429,7 +430,7 @@ class TestLoadNodeEvacResult(unittest.TestCase):
assert iallocator._NEVAC_RESULT(alloc_result)
lu = _FakeLU()
result = cmdlib._LoadNodeEvacResult(lu, alloc_result,
result = common._LoadNodeEvacResult(lu, alloc_result,
early_release, use_nodes)
if moved:
......@@ -458,7 +459,7 @@ class TestLoadNodeEvacResult(unittest.TestCase):
assert iallocator._NEVAC_RESULT(alloc_result)
lu = _FakeLU()
self.assertRaises(errors.OpExecError, cmdlib._LoadNodeEvacResult,
self.assertRaises(errors.OpExecError, common._LoadNodeEvacResult,
lu, alloc_result, False, False)
(_, (args, )) = lu.warning_log.pop(0)
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