+ # If any parameter has documentation, all others need to have it as well
+ has_doc = [doc is not None for (_, _, _, doc) in cls.OP_PARAMS]
+ self.assertTrue(not compat.any(has_doc) or compat.all(has_doc),
+ msg="%s does not document all parameters" % cls)
+
+ def testValidateNoModification(self):
+ class OpTest(opcodes.OpCode):
+ OP_PARAMS = [
+ ("nodef", ht.NoDefault, ht.TMaybeString, None),
+ ("wdef", "default", ht.TMaybeString, None),
+ ("number", 0, ht.TInt, None),
+ ("notype", None, ht.NoType, None),
+ ]
+
+ # Missing required parameter "nodef"
+ op = OpTest()
+ before = op.__getstate__()
+ self.assertRaises(errors.OpPrereqError, op.Validate, False)
+ self.assertFalse(hasattr(op, "nodef"))
+ self.assertFalse(hasattr(op, "wdef"))
+ self.assertFalse(hasattr(op, "number"))
+ self.assertFalse(hasattr(op, "notype"))
+ self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
+
+ # Required parameter "nodef" is provided
+ op = OpTest(nodef="foo")
+ before = op.__getstate__()
+ op.Validate(False)
+ self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
+ self.assertEqual(op.nodef, "foo")
+ self.assertFalse(hasattr(op, "wdef"))
+ self.assertFalse(hasattr(op, "number"))
+ self.assertFalse(hasattr(op, "notype"))
+
+ # Missing required parameter "nodef"
+ op = OpTest(wdef="hello", number=999)
+ before = op.__getstate__()
+ self.assertRaises(errors.OpPrereqError, op.Validate, False)
+ self.assertFalse(hasattr(op, "nodef"))
+ self.assertFalse(hasattr(op, "notype"))
+ self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
+
+ # Wrong type for "nodef"
+ op = OpTest(nodef=987)
+ before = op.__getstate__()
+ self.assertRaises(errors.OpPrereqError, op.Validate, False)
+ self.assertEqual(op.nodef, 987)
+ self.assertFalse(hasattr(op, "notype"))
+ self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
+
+ # Testing different types for "notype"
+ op = OpTest(nodef="foo", notype=[1, 2, 3])
+ before = op.__getstate__()
+ op.Validate(False)
+ self.assertEqual(op.nodef, "foo")
+ self.assertEqual(op.notype, [1, 2, 3])
+ self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
+
+ op = OpTest(nodef="foo", notype="Hello World")
+ before = op.__getstate__()
+ op.Validate(False)
+ self.assertEqual(op.nodef, "foo")
+ self.assertEqual(op.notype, "Hello World")
+ self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
+
+ def testValidateSetDefaults(self):
+ class OpTest(opcodes.OpCode):
+ OP_PARAMS = [
+ # Static default value
+ ("value1", "default", ht.TMaybeString, None),
+
+ # Default value callback
+ ("value2", lambda: "result", ht.TMaybeString, None),
+ ]
+
+ op = OpTest()
+ before = op.__getstate__()
+ op.Validate(True)
+ self.assertNotEqual(op.__getstate__(), before,
+ msg="Opcode was not modified")
+ self.assertEqual(op.value1, "default")
+ self.assertEqual(op.value2, "result")
+ self.assert_(op.dry_run is None)
+ self.assert_(op.debug_level is None)
+ self.assertEqual(op.priority, constants.OP_PRIO_DEFAULT)
+
+ op = OpTest(value1="hello", value2="world", debug_level=123)
+ before = op.__getstate__()
+ op.Validate(True)
+ self.assertNotEqual(op.__getstate__(), before,
+ msg="Opcode was not modified")
+ self.assertEqual(op.value1, "hello")
+ self.assertEqual(op.value2, "world")
+ self.assertEqual(op.debug_level, 123)
+
+
+class TestOpcodeDepends(unittest.TestCase):
+ def test(self):
+ check_relative = opcodes._BuildJobDepCheck(True)
+ check_norelative = opcodes.TNoRelativeJobDependencies
+
+ for fn in [check_relative, check_norelative]:
+ self.assertTrue(fn(None))
+ self.assertTrue(fn([]))
+ self.assertTrue(fn([(1, [])]))
+ self.assertTrue(fn([(719833, [])]))
+ self.assertTrue(fn([("24879", [])]))
+ self.assertTrue(fn([(2028, [constants.JOB_STATUS_ERROR])]))
+ self.assertTrue(fn([
+ (2028, [constants.JOB_STATUS_ERROR]),
+ (18750, []),
+ (5063, [constants.JOB_STATUS_SUCCESS, constants.JOB_STATUS_ERROR]),
+ ]))
+
+ self.assertFalse(fn(1))
+ self.assertFalse(fn([(9, )]))
+ self.assertFalse(fn([(15194, constants.JOB_STATUS_ERROR)]))
+
+ for i in [
+ [(-1, [])],
+ [(-27740, [constants.JOB_STATUS_CANCELED, constants.JOB_STATUS_ERROR]),
+ (-1, [constants.JOB_STATUS_ERROR]),
+ (9921, [])],
+ ]:
+ self.assertTrue(check_relative(i))
+ self.assertFalse(check_norelative(i))
+
+
+class TestResultChecks(unittest.TestCase):
+ def testJobIdList(self):
+ for i in [[], [(False, "error")], [(False, "")],
+ [(True, 123), (True, "999")]]:
+ self.assertTrue(opcodes.TJobIdList(i))
+
+ for i in ["", [("x", 1)], [[], []], [[False, "", None], [True, 123]]]:
+ self.assertFalse(opcodes.TJobIdList(i))
+
+ def testJobIdListOnly(self):
+ self.assertTrue(opcodes.TJobIdListOnly({
+ constants.JOB_IDS_KEY: [],
+ }))
+ self.assertTrue(opcodes.TJobIdListOnly({
+ constants.JOB_IDS_KEY: [(True, "9282")],
+ }))
+
+ self.assertFalse(opcodes.TJobIdListOnly({
+ "x": None,
+ }))
+ self.assertFalse(opcodes.TJobIdListOnly({
+ constants.JOB_IDS_KEY: [],
+ "x": None,
+ }))
+ self.assertFalse(opcodes.TJobIdListOnly({
+ constants.JOB_IDS_KEY: [("foo", "bar")],
+ }))
+ self.assertFalse(opcodes.TJobIdListOnly({
+ constants.JOB_IDS_KEY: [("one", "two", "three")],
+ }))
+
+
+class TestClusterOsList(unittest.TestCase):
+ def test(self):
+ good = [
+ None,
+ [],
+ [(constants.DDM_ADD, "dos"),
+ (constants.DDM_REMOVE, "linux")],
+ ]
+
+ for i in good:
+ self.assertTrue(opcodes._TestClusterOsList(i))
+
+ wrong = ["", 0, "xy", ["Hello World"], object(),
+ [("foo", "bar")],
+ [("", "")],
+ [[constants.DDM_ADD]],
+ [(constants.DDM_ADD, "")],
+ [(constants.DDM_REMOVE, "")],
+ [(constants.DDM_ADD, None)],
+ [(constants.DDM_REMOVE, None)],
+ ]
+
+ for i in wrong:
+ self.assertFalse(opcodes._TestClusterOsList(i))
+
+
+class TestOpInstanceSetParams(unittest.TestCase):
+ def _GenericTests(self, fn):
+ self.assertTrue(fn([]))
+ self.assertTrue(fn([(constants.DDM_ADD, {})]))
+ self.assertTrue(fn([(constants.DDM_REMOVE, {})]))
+ for i in [0, 1, 2, 3, 9, 10, 1024]:
+ self.assertTrue(fn([(i, {})]))
+
+ self.assertFalse(fn(None))
+ self.assertFalse(fn({}))
+ self.assertFalse(fn(""))
+ self.assertFalse(fn(0))
+ self.assertFalse(fn([(-100, {})]))
+ self.assertFalse(fn([(constants.DDM_ADD, 2, 3)]))
+ self.assertFalse(fn([[constants.DDM_ADD]]))
+
+ def testNicModifications(self):
+ fn = opcodes.OpInstanceSetParams.TestNicModifications
+ self._GenericTests(fn)
+
+ for param in constants.INIC_PARAMS:
+ self.assertTrue(fn([[constants.DDM_ADD, {param: None}]]))
+ self.assertTrue(fn([[constants.DDM_ADD, {param: param}]]))
+
+ def testDiskModifications(self):
+ fn = opcodes.OpInstanceSetParams.TestDiskModifications
+ self._GenericTests(fn)
+
+ for param in constants.IDISK_PARAMS:
+ self.assertTrue(fn([[constants.DDM_ADD, {param: 0}]]))
+ self.assertTrue(fn([[constants.DDM_ADD, {param: param}]]))
+