4 # Copyright (C) 2008, 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Script for unittesting the cmdlib module"""
33 from ganeti import constants
34 from ganeti import mcpu
35 from ganeti import cmdlib
36 from ganeti import opcodes
37 from ganeti import errors
38 from ganeti import utils
39 from ganeti import luxi
41 from ganeti import objects
42 from ganeti import compat
43 from ganeti import rpc
44 from ganeti.hypervisor import hv_xen
50 class TestCertVerification(testutils.GanetiTestCase):
52 testutils.GanetiTestCase.setUp(self)
54 self.tmpdir = tempfile.mkdtemp()
57 shutil.rmtree(self.tmpdir)
59 def testVerifyCertificate(self):
60 cmdlib._VerifyCertificate(self._TestDataFilename("cert1.pem"))
62 nonexist_filename = os.path.join(self.tmpdir, "does-not-exist")
64 (errcode, msg) = cmdlib._VerifyCertificate(nonexist_filename)
65 self.assertEqual(errcode, cmdlib.LUClusterVerifyConfig.ETYPE_ERROR)
67 # Try to load non-certificate file
68 invalid_cert = self._TestDataFilename("bdev-net.txt")
69 (errcode, msg) = cmdlib._VerifyCertificate(invalid_cert)
70 self.assertEqual(errcode, cmdlib.LUClusterVerifyConfig.ETYPE_ERROR)
73 class TestOpcodeParams(testutils.GanetiTestCase):
74 def testParamsStructures(self):
75 for op in sorted(mcpu.Processor.DISPATCH_TABLE):
76 lu = mcpu.Processor.DISPATCH_TABLE[op]
78 self.failIf(hasattr(lu, "_OP_REQP"),
79 msg=("LU '%s' has old-style _OP_REQP" % lu_name))
80 self.failIf(hasattr(lu, "_OP_DEFS"),
81 msg=("LU '%s' has old-style _OP_DEFS" % lu_name))
82 self.failIf(hasattr(lu, "_OP_PARAMS"),
83 msg=("LU '%s' has old-style _OP_PARAMS" % lu_name))
86 class TestIAllocatorChecks(testutils.GanetiTestCase):
87 def testFunction(self):
89 def __init__(self, opcode):
90 self.cfg = mocks.FakeConfig()
93 class OpTest(opcodes.OpCode):
95 ("iallocator", None, ht.NoType, None),
96 ("node", None, ht.NoType, None),
99 default_iallocator = mocks.FakeConfig().GetDefaultIAllocator()
100 other_iallocator = default_iallocator + "_not"
105 c_i = lambda: cmdlib._CheckIAllocatorOrNode(lu, "iallocator", "node")
107 # Neither node nor iallocator given
111 self.assertEqual(lu.op.iallocator, default_iallocator)
112 self.assertEqual(lu.op.node, None)
114 # Both, iallocator and node given
115 op.iallocator = "test"
117 self.assertRaises(errors.OpPrereqError, c_i)
119 # Only iallocator given
120 op.iallocator = other_iallocator
123 self.assertEqual(lu.op.iallocator, other_iallocator)
124 self.assertEqual(lu.op.node, None)
130 self.assertEqual(lu.op.iallocator, None)
131 self.assertEqual(lu.op.node, "node")
133 # No node, iallocator or default iallocator
136 lu.cfg.GetDefaultIAllocator = lambda: None
137 self.assertRaises(errors.OpPrereqError, c_i)
140 class TestLUTestJqueue(unittest.TestCase):
142 self.assert_(cmdlib.LUTestJqueue._CLIENT_CONNECT_TIMEOUT <
143 (luxi.WFJC_TIMEOUT * 0.75),
144 msg=("Client timeout too high, might not notice bugs"
145 " in WaitForJobChange"))
148 class TestLUQuery(unittest.TestCase):
150 self.assertEqual(sorted(cmdlib._QUERY_IMPL.keys()),
151 sorted(constants.QR_VIA_OP))
153 assert constants.QR_NODE in constants.QR_VIA_OP
154 assert constants.QR_INSTANCE in constants.QR_VIA_OP
156 for i in constants.QR_VIA_OP:
157 self.assert_(cmdlib._GetQueryImplementation(i))
159 self.assertRaises(errors.OpPrereqError, cmdlib._GetQueryImplementation, "")
160 self.assertRaises(errors.OpPrereqError, cmdlib._GetQueryImplementation,
164 class TestLUGroupAssignNodes(unittest.TestCase):
166 def testCheckAssignmentForSplitInstances(self):
167 node_data = dict((name, objects.Node(name=name, group=group))
168 for (name, group) in [("n1a", "g1"), ("n1b", "g1"),
169 ("n2a", "g2"), ("n2b", "g2"),
170 ("n3a", "g3"), ("n3b", "g3"),
174 def Instance(name, pnode, snode):
177 disk_template = constants.DT_DISKLESS
179 disks = [objects.Disk(dev_type=constants.LD_DRBD8,
180 logical_id=[pnode, snode, 1, 17, 17])]
181 disk_template = constants.DT_DRBD8
183 return objects.Instance(name=name, primary_node=pnode, disks=disks,
184 disk_template=disk_template)
186 instance_data = dict((name, Instance(name, pnode, snode))
187 for name, pnode, snode in [("inst1a", "n1a", "n1b"),
188 ("inst1b", "n1b", "n1a"),
189 ("inst2a", "n2a", "n2b"),
190 ("inst3a", "n3a", None),
191 ("inst3b", "n3b", "n1b"),
192 ("inst3c", "n3b", "n2b"),
195 # Test first with the existing state.
197 cmdlib.LUGroupAssignNodes.CheckAssignmentForSplitInstances([],
201 self.assertEqual([], new)
202 self.assertEqual(set(["inst3b", "inst3c"]), set(prev))
204 # And now some changes.
206 cmdlib.LUGroupAssignNodes.CheckAssignmentForSplitInstances([("n1b",
211 self.assertEqual(set(["inst1a", "inst1b"]), set(new))
212 self.assertEqual(set(["inst3c"]), set(prev))
215 class TestClusterVerifySsh(unittest.TestCase):
216 def testMultipleGroups(self):
217 fn = cmdlib.LUClusterVerifyGroup._SelectSshCheckNodes
219 objects.Node(name="node20", group="my", offline=False),
220 objects.Node(name="node21", group="my", offline=False),
221 objects.Node(name="node22", group="my", offline=False),
222 objects.Node(name="node23", group="my", offline=False),
223 objects.Node(name="node24", group="my", offline=False),
224 objects.Node(name="node25", group="my", offline=False),
225 objects.Node(name="node26", group="my", offline=True),
228 objects.Node(name="node1", group="g1", offline=True),
229 objects.Node(name="node2", group="g1", offline=False),
230 objects.Node(name="node3", group="g1", offline=False),
231 objects.Node(name="node4", group="g1", offline=True),
232 objects.Node(name="node5", group="g1", offline=False),
233 objects.Node(name="node10", group="xyz", offline=False),
234 objects.Node(name="node11", group="xyz", offline=False),
235 objects.Node(name="node40", group="alloff", offline=True),
236 objects.Node(name="node41", group="alloff", offline=True),
237 objects.Node(name="node50", group="aaa", offline=False),
239 assert not utils.FindDuplicates(map(operator.attrgetter("name"), nodes))
241 (online, perhost) = fn(mygroupnodes, "my", nodes)
242 self.assertEqual(online, ["node%s" % i for i in range(20, 26)])
243 self.assertEqual(set(perhost.keys()), set(online))
245 self.assertEqual(perhost, {
246 "node20": ["node10", "node2", "node50"],
247 "node21": ["node11", "node3", "node50"],
248 "node22": ["node10", "node5", "node50"],
249 "node23": ["node11", "node2", "node50"],
250 "node24": ["node10", "node3", "node50"],
251 "node25": ["node11", "node5", "node50"],
254 def testSingleGroup(self):
255 fn = cmdlib.LUClusterVerifyGroup._SelectSshCheckNodes
257 objects.Node(name="node1", group="default", offline=True),
258 objects.Node(name="node2", group="default", offline=False),
259 objects.Node(name="node3", group="default", offline=False),
260 objects.Node(name="node4", group="default", offline=True),
262 assert not utils.FindDuplicates(map(operator.attrgetter("name"), nodes))
264 (online, perhost) = fn(nodes, "default", nodes)
265 self.assertEqual(online, ["node2", "node3"])
266 self.assertEqual(set(perhost.keys()), set(online))
268 self.assertEqual(perhost, {
274 class TestClusterVerifyFiles(unittest.TestCase):
276 def _FakeErrorIf(errors, cond, ecode, item, msg, *args, **kwargs):
277 assert ((ecode == constants.CV_ENODEFILECHECK and
278 ht.TNonEmptyString(item)) or
279 (ecode == constants.CV_ECLUSTERFILECHECK and
286 errors.append((item, msg))
288 _VerifyFiles = cmdlib.LUClusterVerifyGroup._VerifyFiles
292 master_name = "master.example.com"
294 objects.Node(name=master_name, offline=False, vm_capable=True),
295 objects.Node(name="node2.example.com", offline=False, vm_capable=True),
296 objects.Node(name="node3.example.com", master_candidate=True,
298 objects.Node(name="node4.example.com", offline=False, vm_capable=True),
299 objects.Node(name="nodata.example.com", offline=False, vm_capable=True),
300 objects.Node(name="offline.example.com", offline=True),
302 cluster = objects.Cluster(modify_etc_hosts=True,
303 enabled_hypervisors=[constants.HT_XEN_HVM])
305 constants.CLUSTER_DOMAIN_SECRET_FILE,
306 constants.RAPI_CERT_FILE,
307 constants.RAPI_USERS_FILE,
310 constants.RAPI_USERS_FILE,
311 hv_xen.XL_CONFIG_FILE,
312 constants.VNC_PASSWORD_FILE,
315 constants.CLUSTER_CONF_FILE,
318 hv_xen.XEND_CONFIG_FILE,
319 hv_xen.XL_CONFIG_FILE,
320 constants.VNC_PASSWORD_FILE,
323 master_name: rpc.RpcResult(data=(True, {
324 constants.NV_FILELIST: {
325 constants.CLUSTER_CONF_FILE: "82314f897f38b35f9dab2f7c6b1593e0",
326 constants.RAPI_CERT_FILE: "babbce8f387bc082228e544a2146fee4",
327 constants.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
328 hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310",
329 hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9"
331 "node2.example.com": rpc.RpcResult(data=(True, {
332 constants.NV_FILELIST: {
333 constants.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
334 hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310",
337 "node3.example.com": rpc.RpcResult(data=(True, {
338 constants.NV_FILELIST: {
339 constants.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
340 constants.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
343 "node4.example.com": rpc.RpcResult(data=(True, {
344 constants.NV_FILELIST: {
345 constants.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
346 constants.CLUSTER_CONF_FILE: "conf-a6d4b13e407867f7a7b4f0f232a8f527",
347 constants.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
348 constants.RAPI_USERS_FILE: "rapiusers-ea3271e8d810ef3",
349 hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9"
352 "nodata.example.com": rpc.RpcResult(data=(True, {})),
353 "offline.example.com": rpc.RpcResult(offline=True),
355 assert set(nvinfo.keys()) == set(map(operator.attrgetter("name"), nodeinfo))
357 self._VerifyFiles(compat.partial(self._FakeErrorIf, errors), nodeinfo,
359 (files_all, files_opt, files_mc, files_vm))
360 self.assertEqual(sorted(errors), sorted([
361 (None, ("File %s found with 2 different checksums (variant 1 on"
362 " node2.example.com, node3.example.com, node4.example.com;"
363 " variant 2 on master.example.com)" % constants.RAPI_CERT_FILE)),
364 (None, ("File %s is missing from node(s) node2.example.com" %
365 constants.CLUSTER_DOMAIN_SECRET_FILE)),
366 (None, ("File %s should not exist on node(s) node4.example.com" %
367 constants.CLUSTER_CONF_FILE)),
368 (None, ("File %s is missing from node(s) node4.example.com" %
369 hv_xen.XEND_CONFIG_FILE)),
370 (None, ("File %s is missing from node(s) node3.example.com" %
371 constants.CLUSTER_CONF_FILE)),
372 (None, ("File %s found with 2 different checksums (variant 1 on"
373 " master.example.com; variant 2 on node4.example.com)" %
374 constants.CLUSTER_CONF_FILE)),
375 (None, ("File %s is optional, but it must exist on all or no nodes (not"
376 " found on master.example.com, node2.example.com,"
377 " node3.example.com)" % constants.RAPI_USERS_FILE)),
378 (None, ("File %s is optional, but it must exist on all or no nodes (not"
379 " found on node2.example.com)" % hv_xen.XL_CONFIG_FILE)),
380 ("nodata.example.com", "Node did not return file checksum data"),
385 def __init__(self, cfg=NotImplemented):
386 self.warning_log = []
390 def LogWarning(self, text, *args):
391 self.warning_log.append((text, args))
393 def LogInfo(self, text, *args):
394 self.info_log.append((text, args))
397 class TestLoadNodeEvacResult(unittest.TestCase):
398 def testSuccess(self):
400 ("inst20153.example.com", "grp2", ["nodeA4509", "nodeB2912"]),
402 for early_release in [False, True]:
403 for use_nodes in [False, True]:
405 [opcodes.OpInstanceReplaceDisks().__getstate__()],
406 [opcodes.OpInstanceMigrate().__getstate__()],
409 alloc_result = (moved, [], jobs)
410 assert cmdlib.IAllocator._NEVAC_RESULT(alloc_result)
413 result = cmdlib._LoadNodeEvacResult(lu, alloc_result,
414 early_release, use_nodes)
417 (_, (info_args, )) = lu.info_log.pop(0)
418 for (instname, instgroup, instnodes) in moved:
419 self.assertTrue(instname in info_args)
422 self.assertTrue(i in info_args)
424 self.assertTrue(instgroup in info_args)
426 self.assertFalse(lu.info_log)
427 self.assertFalse(lu.warning_log)
429 for op in itertools.chain(*result):
430 if hasattr(op.__class__, "early_release"):
431 self.assertEqual(op.early_release, early_release)
433 self.assertFalse(hasattr(op, "early_release"))
435 def testFailed(self):
436 alloc_result = ([], [
437 ("inst5191.example.com", "errormsg21178"),
439 assert cmdlib.IAllocator._NEVAC_RESULT(alloc_result)
442 self.assertRaises(errors.OpExecError, cmdlib._LoadNodeEvacResult,
443 lu, alloc_result, False, False)
444 self.assertFalse(lu.info_log)
445 (_, (args, )) = lu.warning_log.pop(0)
446 self.assertTrue("inst5191.example.com" in args)
447 self.assertTrue("errormsg21178" in args)
448 self.assertFalse(lu.warning_log)
451 class TestUpdateAndVerifySubDict(unittest.TestCase):
454 "a": constants.VTYPE_INT,
455 "b": constants.VTYPE_STRING,
456 "c": constants.VTYPE_BOOL,
457 "d": constants.VTYPE_STRING,
504 verified = cmdlib._UpdateAndVerifySubDict(old_test, test, self.type_check)
505 self.assertEqual(verified, mv)
521 self.assertRaises(errors.TypeEnforcementError,
522 cmdlib._UpdateAndVerifySubDict, {}, test, self.type_check)
525 class TestHvStateHelper(unittest.TestCase):
526 def testWithoutOpData(self):
527 self.assertEqual(cmdlib._MergeAndVerifyHvState(None, NotImplemented), None)
529 def testWithoutOldData(self):
531 constants.HT_XEN_PVM: {
532 constants.HVST_MEMORY_TOTAL: 4096,
535 self.assertEqual(cmdlib._MergeAndVerifyHvState(new, None), new)
537 def testWithWrongHv(self):
540 constants.HVST_MEMORY_TOTAL: 4096,
543 self.assertRaises(errors.OpPrereqError, cmdlib._MergeAndVerifyHvState, new,
546 class TestDiskStateHelper(unittest.TestCase):
547 def testWithoutOpData(self):
548 self.assertEqual(cmdlib._MergeAndVerifyDiskState(None, NotImplemented),
551 def testWithoutOldData(self):
555 constants.DS_DISK_RESERVED: 1024,
559 self.assertEqual(cmdlib._MergeAndVerifyDiskState(new, None), new)
561 def testWithWrongStorageType(self):
565 constants.DS_DISK_RESERVED: 1024,
569 self.assertRaises(errors.OpPrereqError, cmdlib._MergeAndVerifyDiskState,
573 class TestComputeMinMaxSpec(unittest.TestCase):
576 constants.ISPECS_MAX: {
577 constants.ISPEC_MEM_SIZE: 512,
578 constants.ISPEC_DISK_SIZE: 1024,
580 constants.ISPECS_MIN: {
581 constants.ISPEC_MEM_SIZE: 128,
582 constants.ISPEC_DISK_COUNT: 1,
586 def testNoneValue(self):
587 self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_MEM_SIZE,
588 self.ipolicy, None) is None)
590 def testAutoValue(self):
591 self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_MEM_SIZE,
593 constants.VALUE_AUTO) is None)
595 def testNotDefined(self):
596 self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_NIC_COUNT,
597 self.ipolicy, 3) is None)
599 def testNoMinDefined(self):
600 self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_DISK_SIZE,
601 self.ipolicy, 128) is None)
603 def testNoMaxDefined(self):
604 self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_DISK_COUNT,
605 self.ipolicy, 16) is None)
607 def testOutOfRange(self):
608 for (name, val) in ((constants.ISPEC_MEM_SIZE, 64),
609 (constants.ISPEC_MEM_SIZE, 768),
610 (constants.ISPEC_DISK_SIZE, 4096),
611 (constants.ISPEC_DISK_COUNT, 0)):
612 min_v = self.ipolicy[constants.ISPECS_MIN].get(name, val)
613 max_v = self.ipolicy[constants.ISPECS_MAX].get(name, val)
614 self.assertEqual(cmdlib._ComputeMinMaxSpec(name, self.ipolicy, val),
615 "%s value %s is not in range [%s, %s]" %
616 (name, val,min_v, max_v))
619 for (name, val) in ((constants.ISPEC_MEM_SIZE, 256),
620 (constants.ISPEC_MEM_SIZE, 128),
621 (constants.ISPEC_MEM_SIZE, 512),
622 (constants.ISPEC_DISK_SIZE, 1024),
623 (constants.ISPEC_DISK_SIZE, 0),
624 (constants.ISPEC_DISK_COUNT, 1),
625 (constants.ISPEC_DISK_COUNT, 5)):
626 self.assertTrue(cmdlib._ComputeMinMaxSpec(name, self.ipolicy, val)
630 def _ValidateComputeMinMaxSpec(name, *_):
631 assert name in constants.ISPECS_PARAMETERS
636 def __init__(self, spec):
639 def ComputeMinMaxSpec(self, *args):
640 return self.spec.pop(0)
643 class TestComputeIPolicySpecViolation(unittest.TestCase):
645 compute_fn = _ValidateComputeMinMaxSpec
646 ret = cmdlib._ComputeIPolicySpecViolation(NotImplemented, 1024, 1, 1, 1,
647 [1024], _compute_fn=compute_fn)
648 self.assertEqual(ret, [])
650 def testInvalidArguments(self):
651 self.assertRaises(AssertionError, cmdlib._ComputeIPolicySpecViolation,
652 NotImplemented, 1024, 1, 1, 1, [])
654 def testInvalidSpec(self):
655 spec = _SpecWrapper([None, False, "foo", None, "bar"])
656 compute_fn = spec.ComputeMinMaxSpec
657 ret = cmdlib._ComputeIPolicySpecViolation(NotImplemented, 1024, 1, 1, 1,
658 [1024], _compute_fn=compute_fn)
659 self.assertEqual(ret, ["foo", "bar"])
660 self.assertFalse(spec.spec)
663 class _StubComputeIPolicySpecViolation:
664 def __init__(self, mem_size, cpu_count, disk_count, nic_count, disk_sizes):
665 self.mem_size = mem_size
666 self.cpu_count = cpu_count
667 self.disk_count = disk_count
668 self.nic_count = nic_count
669 self.disk_sizes = disk_sizes
671 def __call__(self, _, mem_size, cpu_count, disk_count, nic_count, disk_sizes):
672 assert self.mem_size == mem_size
673 assert self.cpu_count == cpu_count
674 assert self.disk_count == disk_count
675 assert self.nic_count == nic_count
676 assert self.disk_sizes == disk_sizes
681 class TestComputeIPolicyInstanceViolation(unittest.TestCase):
684 constants.BE_MAXMEM: 2048,
685 constants.BE_VCPUS: 2,
687 disks = [objects.Disk(size=512)]
688 instance = objects.Instance(beparams=beparams, disks=disks, nics=[])
689 stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512])
690 ret = cmdlib._ComputeIPolicyInstanceViolation(NotImplemented, instance,
692 self.assertEqual(ret, [])
695 class TestComputeIPolicyInstanceSpecViolation(unittest.TestCase):
698 constants.ISPEC_MEM_SIZE: 2048,
699 constants.ISPEC_CPU_COUNT: 2,
700 constants.ISPEC_DISK_COUNT: 1,
701 constants.ISPEC_DISK_SIZE: [512],
702 constants.ISPEC_NIC_COUNT: 0,
704 stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512])
705 ret = cmdlib._ComputeIPolicyInstanceSpecViolation(NotImplemented, ispec,
707 self.assertEqual(ret, [])
711 def __init__(self, return_value=None):
713 self.return_value = return_value
715 def __call__(self, *args):
717 return self.return_value
720 class TestComputeIPolicyNodeViolation(unittest.TestCase):
722 self.recorder = _CallRecorder(return_value=[])
724 def testSameGroup(self):
725 ret = cmdlib._ComputeIPolicyNodeViolation(NotImplemented, NotImplemented,
727 _compute_fn=self.recorder)
728 self.assertFalse(self.recorder.called)
729 self.assertEqual(ret, [])
731 def testDifferentGroup(self):
732 ret = cmdlib._ComputeIPolicyNodeViolation(NotImplemented, NotImplemented,
734 _compute_fn=self.recorder)
735 self.assertTrue(self.recorder.called)
736 self.assertEqual(ret, [])
739 class _FakeConfigForTargetNodeIPolicy:
740 def __init__(self, node_info=NotImplemented):
741 self._node_info = node_info
743 def GetNodeInfo(self, _):
744 return self._node_info
747 class TestCheckTargetNodeIPolicy(unittest.TestCase):
749 self.instance = objects.Instance(primary_node="blubb")
750 self.target_node = objects.Node(group="bar")
751 node_info = objects.Node(group="foo")
752 fake_cfg = _FakeConfigForTargetNodeIPolicy(node_info=node_info)
753 self.lu = _FakeLU(cfg=fake_cfg)
755 def testNoViolation(self):
756 compute_recoder = _CallRecorder(return_value=[])
757 cmdlib._CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
759 _compute_fn=compute_recoder)
760 self.assertTrue(compute_recoder.called)
761 self.assertEqual(self.lu.warning_log, [])
763 def testNoIgnore(self):
764 compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
765 self.assertRaises(errors.OpPrereqError, cmdlib._CheckTargetNodeIPolicy,
766 self.lu, NotImplemented, self.instance, self.target_node,
767 _compute_fn=compute_recoder)
768 self.assertTrue(compute_recoder.called)
769 self.assertEqual(self.lu.warning_log, [])
771 def testIgnoreViolation(self):
772 compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
773 cmdlib._CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
774 self.target_node, ignore=True,
775 _compute_fn=compute_recoder)
776 self.assertTrue(compute_recoder.called)
777 msg = ("Instance does not meet target node group's (bar) instance policy:"
778 " mem_size not in range")
779 self.assertEqual(self.lu.warning_log, [(msg, ())])
782 if __name__ == "__main__":
783 testutils.GanetiTestProgram()