return None
+def _ComputeIPolicySpecViolation(ipolicy, mem_size, cpu_count, disk_count,
+ nic_count, disk_sizes,
+ _check_spec_fn=_CheckMinMaxSpecs):
+ """Verifies ipolicy against provided specs.
+
+ @type ipolicy: dict
+ @param ipolicy: The ipolicy
+ @type mem_size: int
+ @param mem_size: The memory size
+ @type cpu_count: int
+ @param cpu_count: Used cpu cores
+ @type disk_count: int
+ @param disk_count: Number of disks used
+ @type nic_count: int
+ @param nic_count: Number of nics used
+ @type disk_sizes: list of ints
+ @param disk_sizes: Disk sizes of used disk (len must match C{disk_count})
+ @param _check_spec_fn: The checking function (unittest only)
+ @return: A list of violations, or an empty list of no violations are found
+
+ """
+ assert disk_count == len(disk_sizes)
+
+ test_settings = [
+ (constants.ISPEC_MEM_SIZE, mem_size),
+ (constants.ISPEC_CPU_COUNT, cpu_count),
+ (constants.ISPEC_DISK_COUNT, disk_count),
+ (constants.ISPEC_NIC_COUNT, nic_count),
+ ] + map((lambda d: (constants.ISPEC_DISK_SIZE, d)), disk_sizes)
+
+ return filter(None,
+ (_check_spec_fn(name, ipolicy, value)
+ for (name, value) in test_settings))
+
+
+def _ComputeIPolicyInstanceViolation(ipolicy, instance,
+ _compute_fn=_ComputeIPolicySpecViolation):
+ """Compute if instance meets the specs of ipolicy.
+
+ @type ipolicy: dict
+ @param ipolicy: The ipolicy to verify against
+ @type instance: L{objects.Instance}
+ @param instance: The instance to verify
+ @param _compute_fn: The function to verify ipolicy (unittest only)
+ @see: L{_ComputeIPolicySpecViolation}
+
+ """
+ mem_size = instance.beparams.get(constants.BE_MAXMEM, None)
+ cpu_count = instance.beparams.get(constants.BE_VCPUS, None)
+ disk_count = len(instance.disks)
+ disk_sizes = [disk.size for disk in instance.disks]
+ nic_count = len(instance.nics)
+
+ return _compute_fn(ipolicy, mem_size, cpu_count, disk_count, nic_count,
+ disk_sizes)
+
+
+def _ComputeIPolicyInstanceSpecViolation(ipolicy, instance_spec,
+ _compute_fn=_ComputeIPolicySpecViolation):
+ """Compute if instance specs meets the specs of ipolicy.
+
+ @type ipolicy: dict
+ @param ipolicy: The ipolicy to verify against
+ @param instance_spec: dict
+ @param instance_spec: The instance spec to verify
+ @param _compute_fn: The function to verify ipolicy (unittest only)
+ @see: L{_ComputeIPolicySpecViolation}
+
+ """
+ mem_size = instance_spec.get(constants.ISPEC_MEM_SIZE, None)
+ cpu_count = instance_spec.get(constants.ISPEC_CPU_COUNT, None)
+ disk_count = instance_spec.get(constants.ISPEC_DISK_COUNT, 0)
+ disk_sizes = instance_spec.get(constants.ISPEC_DISK_SIZE, [])
+ nic_count = instance_spec.get(constants.ISPEC_NIC_COUNT, 0)
+
+ return _compute_fn(ipolicy, mem_size, cpu_count, disk_count, nic_count,
+ disk_sizes)
+
+
+def _ComputeIPolicyNodeViolation(ipolicy, instance, current_group,
+ target_group,
+ _compute_fn=_ComputeIPolicyInstanceViolation):
+ """Compute if instance meets the specs of the new target group.
+
+ @param ipolicy: The ipolicy to verify
+ @param instance: The instance object to verify
+ @param current_group: The current group of the instance
+ @param target_group: The new group of the instance
+ @param _compute_fn: The function to verify ipolicy (unittest only)
+ @see: L{_ComputeIPolicySpecViolation}
+
+ """
+ if current_group == target_group:
+ return []
+ else:
+ return _compute_fn(ipolicy, instance)
+
+
+def _CheckTargetNodeIPolicy(lu, ipolicy, instance, node, ignore=False,
+ _compute_fn=_ComputeIPolicyNodeViolation):
+ """Checks that the target node is correct in terms of instance policy.
+
+ @param ipolicy: The ipolicy to verify
+ @param instance: The instance object to verify
+ @param node: The new node to relocate
+ @param ignore: Ignore violations of the ipolicy
+ @param _compute_fn: The function to verify ipolicy (unittest only)
+ @see: L{_ComputeIPolicySpecViolation}
+
+ """
+ res = _compute_fn(ipolicy, instance, instance.primary_node.group, node.group)
+
+ if res:
+ msg = ("Instance does not meet target node group's (%s) instance"
+ " policy: %s") % (node.group, utils.CommaJoin(res))
+ if ignore:
+ lu.LogWarning(msg)
+ else:
+ raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
+
+
def _ExpandItemName(fn, name, kind):
"""Expand an item name.
return mc_now < mc_should
-def _CalculateGroupIPolicy(cfg, group):
+def _CalculateGroupIPolicy(cluster, group):
"""Calculate instance policy for group.
"""
- cluster = cfg.GetClusterInfo()
return cluster.SimpleFillIPolicy(group.ipolicy)
new, None)
+def _ValidateCheckMinMaxSpec(name, *_):
+ assert name in constants.ISPECS_PARAMETERS
+ return None
+
+
+class _SpecWrapper:
+ def __init__(self, spec):
+ self.spec = spec
+
+ def CheckMinMaxSpec(self, *args):
+ return self.spec.pop(0)
+
+
+class TestComputeIPolicySpecViolation(unittest.TestCase):
+ def test(self):
+ check_fn = _ValidateCheckMinMaxSpec
+ ret = cmdlib._ComputeIPolicySpecViolation(NotImplemented, 1024, 1, 1, 1,
+ [1024], _check_spec_fn=check_fn)
+ self.assertEqual(ret, [])
+
+ def testInvalidArguments(self):
+ self.assertRaises(AssertionError, cmdlib._ComputeIPolicySpecViolation,
+ NotImplemented, 1024, 1, 1, 1, [])
+
+ def testInvalidSpec(self):
+ spec = _SpecWrapper([None, False, "foo", None, "bar"])
+ check_fn = spec.CheckMinMaxSpec
+ ret = cmdlib._ComputeIPolicySpecViolation(NotImplemented, 1024, 1, 1, 1,
+ [1024], _check_spec_fn=check_fn)
+ self.assertEqual(ret, ["foo", "bar"])
+ self.assertFalse(spec.spec)
+
+
+class _StubComputeIPolicySpecViolation:
+ def __init__(self, mem_size, cpu_count, disk_count, nic_count, disk_sizes):
+ self.mem_size = mem_size
+ self.cpu_count = cpu_count
+ self.disk_count = disk_count
+ self.nic_count = nic_count
+ self.disk_sizes = disk_sizes
+
+ def __call__(self, _, mem_size, cpu_count, disk_count, nic_count, disk_sizes):
+ assert self.mem_size == mem_size
+ assert self.cpu_count == cpu_count
+ assert self.disk_count == disk_count
+ assert self.nic_count == nic_count
+ assert self.disk_sizes == disk_sizes
+
+ return []
+
+
+class TestComputeIPolicyInstanceViolation(unittest.TestCase):
+ def test(self):
+ beparams = {
+ constants.BE_MAXMEM: 2048,
+ constants.BE_VCPUS: 2,
+ }
+ disks = [objects.Disk(size=512)]
+ instance = objects.Instance(beparams=beparams, disks=disks, nics=[])
+ stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512])
+ ret = cmdlib._ComputeIPolicyInstanceViolation(NotImplemented, instance,
+ _compute_fn=stub)
+ self.assertEqual(ret, [])
+
+
+class TestComputeIPolicyInstanceSpecViolation(unittest.TestCase):
+ def test(self):
+ ispec = {
+ constants.ISPEC_MEM_SIZE: 2048,
+ constants.ISPEC_CPU_COUNT: 2,
+ constants.ISPEC_DISK_COUNT: 1,
+ constants.ISPEC_DISK_SIZE: [512],
+ constants.ISPEC_NIC_COUNT: 0,
+ }
+ stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512])
+ ret = cmdlib._ComputeIPolicyInstanceSpecViolation(NotImplemented, ispec,
+ _compute_fn=stub)
+ self.assertEqual(ret, [])
+
+
+class _CallRecorder:
+ def __init__(self, return_value=None):
+ self.called = False
+ self.return_value = return_value
+
+ def __call__(self, *args):
+ self.called = True
+ return self.return_value
+
+
+class TestComputeIPolicyNodeViolation(unittest.TestCase):
+ def setUp(self):
+ self.recorder = _CallRecorder(return_value=[])
+
+ def testSameGroup(self):
+ ret = cmdlib._ComputeIPolicyNodeViolation(NotImplemented, NotImplemented,
+ "foo", "foo",
+ _compute_fn=self.recorder)
+ self.assertFalse(self.recorder.called)
+ self.assertEqual(ret, [])
+
+ def testDifferentGroup(self):
+ ret = cmdlib._ComputeIPolicyNodeViolation(NotImplemented, NotImplemented,
+ "foo", "bar",
+ _compute_fn=self.recorder)
+ self.assertTrue(self.recorder.called)
+ self.assertEqual(ret, [])
+
+
+class TestCheckTargetNodeIPolicy(unittest.TestCase):
+ def setUp(self):
+ self.instance = objects.Instance(primary_node=objects.Node(group="foo"))
+ self.target_node = objects.Node(group="bar")
+ self.lu = _FakeLU()
+
+ def testNoViolation(self):
+ compute_recoder = _CallRecorder(return_value=[])
+ cmdlib._CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
+ self.target_node,
+ _compute_fn=compute_recoder)
+ self.assertTrue(compute_recoder.called)
+ self.assertEqual(self.lu.warning_log, [])
+
+ def testNoIgnore(self):
+ compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
+ self.assertRaises(errors.OpPrereqError, cmdlib._CheckTargetNodeIPolicy,
+ self.lu, NotImplemented, self.instance, self.target_node,
+ _compute_fn=compute_recoder)
+ self.assertTrue(compute_recoder.called)
+ self.assertEqual(self.lu.warning_log, [])
+
+ def testIgnoreViolation(self):
+ compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
+ cmdlib._CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
+ self.target_node, ignore=True,
+ _compute_fn=compute_recoder)
+ self.assertTrue(compute_recoder.called)
+ msg = ("Instance does not meet target node group's (bar) instance policy:"
+ " mem_size not in range")
+ self.assertEqual(self.lu.warning_log, [(msg, ())])
+
+
if __name__ == "__main__":
testutils.GanetiTestProgram()