X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/eb08e09da670bab67dc75802b1010621623cde44..99ccf8b915722aaed2029d189b3d522d5a6c8760:/test/ganeti.rapi.rlib2_unittest.py diff --git a/test/ganeti.rapi.rlib2_unittest.py b/test/ganeti.rapi.rlib2_unittest.py index 0e6b7a7..cde68ce 100755 --- a/test/ganeti.rapi.rlib2_unittest.py +++ b/test/ganeti.rapi.rlib2_unittest.py @@ -272,6 +272,26 @@ class TestNodeEvacuate(unittest.TestCase): self.assertRaises(IndexError, cl.GetNextSubmittedJob) +class TestNodePowercycle(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_nodes_name_powercycle, ["node20744"], { + "force": ["1"], + }, None, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpNodePowercycle)) + self.assertEqual(op.node_name, "node20744") + self.assertTrue(op.force) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + class TestGroupAssignNodes(unittest.TestCase): def test(self): clfactory = _FakeClientFactory(_FakeClient) @@ -446,6 +466,26 @@ class TestInstanceDeactivateDisks(unittest.TestCase): self.assertRaises(IndexError, cl.GetNextSubmittedJob) +class TestInstanceRecreateDisks(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_recreate_disks, + ["inst22357"], {}, {}, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpInstanceRecreateDisks)) + self.assertEqual(op.instance_name, "inst22357") + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + class TestInstanceFailover(unittest.TestCase): def test(self): clfactory = _FakeClientFactory(_FakeClient) @@ -586,13 +626,167 @@ class TestStorageQuery(unittest.TestCase): self.assertRaises(http.HttpBadRequest, handler.GET) -class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) +class TestStorageModify(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + + for allocatable in [None, "1", "0"]: + queryargs = { + "storage_type": constants.ST_LVM_VG, + "name": "pv-a", + } + + if allocatable is not None: + queryargs["allocatable"] = allocatable + + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify, + ["node9292"], queryargs, {}, clfactory) + job_id = handler.PUT() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpNodeModifyStorage)) + self.assertEqual(op.node_name, "node9292") + self.assertEqual(op.storage_type, constants.ST_LVM_VG) + self.assertEqual(op.name, "pv-a") + if allocatable is None: + self.assertFalse(op.changes) + else: + assert allocatable in ("0", "1") + self.assertEqual(op.changes, { + constants.SF_ALLOCATABLE: (allocatable == "1"), + }) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testErrors(self): + clfactory = _FakeClientFactory(_FakeClient) + + # No storage type + queryargs = { + "name": "xyz", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify, + ["node26016"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + + # No name + queryargs = { + "storage_type": constants.ST_LVM_VG, + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify, + ["node21218"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + + # Invalid value + queryargs = { + "storage_type": constants.ST_LVM_VG, + "name": "pv-b", + "allocatable": "noint", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify, + ["node30685"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + + +class TestStorageRepair(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + queryargs = { + "storage_type": constants.ST_LVM_PV, + "name": "pv16611", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_repair, + ["node19265"], queryargs, {}, clfactory) + job_id = handler.PUT() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpRepairNodeStorage)) + self.assertEqual(op.node_name, "node19265") + self.assertEqual(op.storage_type, constants.ST_LVM_PV) + self.assertEqual(op.name, "pv16611") + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) - self.Parse = rlib2._ParseInstanceCreateRequestVersion1 + def testErrors(self): + clfactory = _FakeClientFactory(_FakeClient) + + # No storage type + queryargs = { + "name": "xyz", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_repair, + ["node11275"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + + # No name + queryargs = { + "storage_type": constants.ST_LVM_VG, + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage_repair, + ["node21218"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + + +class TestTags(unittest.TestCase): + TAG_HANDLERS = [ + rlib2.R_2_instances_name_tags, + rlib2.R_2_nodes_name_tags, + rlib2.R_2_groups_name_tags, + rlib2.R_2_tags, + ] + + def testSetAndDelete(self): + clfactory = _FakeClientFactory(_FakeClient) + for method, opcls in [("PUT", opcodes.OpTagsSet), + ("DELETE", opcodes.OpTagsDel)]: + for idx, handler in enumerate(self.TAG_HANDLERS): + dry_run = bool(idx % 2) + name = "test%s" % idx + queryargs = { + "tag": ["foo", "bar", "baz"], + "dry-run": str(int(dry_run)), + } + + handler = _CreateHandler(handler, [name], queryargs, {}, clfactory) + job_id = getattr(handler, method)() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcls)) + self.assertEqual(op.kind, handler.TAG_LEVEL) + if handler.TAG_LEVEL == constants.TAG_CLUSTER: + self.assertTrue(op.name is None) + else: + self.assertEqual(op.name, name) + self.assertEqual(op.tags, ["foo", "bar", "baz"]) + self.assertEqual(op.dry_run, dry_run) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceCreation(testutils.GanetiTestCase): def test(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "inst863.example.com" + disk_variants = [ # No disks [], @@ -624,10 +818,13 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): None, {}, { constants.BE_VCPUS: 2, }, - { constants.BE_MEMORY: 123, }, + { constants.BE_MAXMEM: 200, }, + { constants.BE_MEMORY: 256, }, { constants.BE_VCPUS: 2, - constants.BE_MEMORY: 1024, - constants.BE_AUTO_BALANCE: True, } + constants.BE_MAXMEM: 1024, + constants.BE_MINMEM: 1024, + constants.BE_AUTO_BALANCE: True, + constants.BE_ALWAYS_FAILOVER: True, } ] hvparam_variants = [ @@ -643,25 +840,41 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): for disks in disk_variants: for beparams in beparam_variants: for hvparams in hvparam_variants: - data = { - "name": "inst1.example.com", - "hypervisor": constants.HT_FAKE, - "disks": disks, - "nics": nics, - "mode": mode, - "disk_template": disk_template, - "os": "debootstrap", - } - - if beparams is not None: - data["beparams"] = beparams - - if hvparams is not None: - data["hvparams"] = hvparams - for dry_run in [False, True]: - op = self.Parse(data, dry_run) - self.assert_(isinstance(op, opcodes.OpInstanceCreate)) + queryargs = { + "dry-run": str(int(dry_run)), + } + + data = { + rlib2._REQ_DATA_VERSION: 1, + "name": name, + "hypervisor": constants.HT_FAKE, + "disks": disks, + "nics": nics, + "mode": mode, + "disk_template": disk_template, + "os": "debootstrap", + } + + if beparams is not None: + data["beparams"] = beparams + + if hvparams is not None: + data["hvparams"] = hvparams + + handler = _CreateHandler(rlib2.R_2_instances, [], + queryargs, data, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + self.assertTrue(isinstance(op, opcodes.OpInstanceCreate)) + self.assertEqual(op.instance_name, name) self.assertEqual(op.mode, mode) self.assertEqual(op.disk_template, disk_template) self.assertEqual(op.dry_run, dry_run) @@ -690,34 +903,47 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): self.assertEqualValues(op.hvparams, hvparams) def testLegacyName(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "inst29128.example.com" data = { + rlib2._REQ_DATA_VERSION: 1, "name": name, "disks": [], "nics": [], "mode": constants.INSTANCE_CREATE, "disk_template": constants.DT_PLAIN, } - op = self.Parse(data, False) - self.assert_(isinstance(op, opcodes.OpInstanceCreate)) + + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpInstanceCreate)) self.assertEqual(op.instance_name, name) self.assertFalse(hasattr(op, "name")) + self.assertFalse(op.dry_run) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) # Define both - data = { - "name": name, - "instance_name": "other.example.com", - "disks": [], - "nics": [], - "mode": constants.INSTANCE_CREATE, - "disk_template": constants.DT_PLAIN, - } - self.assertRaises(http.HttpBadRequest, self.Parse, data, False) + data["instance_name"] = "other.example.com" + assert "name" in data and "instance_name" in data + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + self.assertRaises(IndexError, clfactory.GetNextClient) def testLegacyOs(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "inst4673.example.com" os = "linux29206" data = { + rlib2._REQ_DATA_VERSION: 1, "name": name, "os_type": os, "disks": [], @@ -725,27 +951,35 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): "mode": constants.INSTANCE_CREATE, "disk_template": constants.DT_PLAIN, } - op = self.Parse(data, False) - self.assert_(isinstance(op, opcodes.OpInstanceCreate)) + + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpInstanceCreate)) self.assertEqual(op.instance_name, name) self.assertEqual(op.os_type, os) self.assertFalse(hasattr(op, "os")) + self.assertFalse(op.dry_run) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) # Define both - data = { - "instance_name": name, - "os": os, - "os_type": "linux9584", - "disks": [], - "nics": [], - "mode": constants.INSTANCE_CREATE, - "disk_template": constants.DT_PLAIN, - } - self.assertRaises(http.HttpBadRequest, self.Parse, data, False) + data["os"] = "linux9584" + assert "os" in data and "os_type" in data + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) def testErrors(self): + clfactory = _FakeClientFactory(_FakeClient) + # Test all required fields reqfields = { + rlib2._REQ_DATA_VERSION: 1, "name": "inst1.example.com", "disks": [], "nics": [], @@ -754,9 +988,11 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): } for name in reqfields.keys(): - self.assertRaises(http.HttpBadRequest, self.Parse, - dict(i for i in reqfields.iteritems() if i[0] != name), - False) + data = dict(i for i in reqfields.iteritems() if i[0] != name) + + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + self.assertRaises(IndexError, clfactory.GetNextClient) # Invalid disks and nics for field in ["disks", "nics"]: @@ -766,7 +1002,46 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): for invvalue in invalid_values: data = reqfields.copy() data[field] = invvalue - self.assertRaises(http.HttpBadRequest, self.Parse, data, False) + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + self.assertRaises(IndexError, clfactory.GetNextClient) + + def testVersion(self): + clfactory = _FakeClientFactory(_FakeClient) + + # No version field + data = { + "name": "inst1.example.com", + "disks": [], + "nics": [], + "mode": constants.INSTANCE_CREATE, + "disk_template": constants.DT_PLAIN, + } + + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + + # Old and incorrect versions + for version in [0, -1, 10483, "Hello World"]: + data[rlib2._REQ_DATA_VERSION] = version + + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + + self.assertRaises(IndexError, clfactory.GetNextClient) + + # Correct version + data[rlib2._REQ_DATA_VERSION] = 1 + handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpInstanceCreate)) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) class TestBackupExport(unittest.TestCase): @@ -976,7 +1251,7 @@ class TestParseModifyInstanceRequest(unittest.TestCase): for osparams in [{}, { "some": "value", "other": "Hello World", }]: for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]: - for beparams in [{}, { constants.BE_MEMORY: 128, }]: + for beparams in [{}, { constants.BE_MAXMEM: 128, }]: for force in [False, True]: for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]: for disks in test_disks: @@ -1088,6 +1363,10 @@ class TestParseInstanceReinstallRequest(testutils.GanetiTestCase): self.assertEqual(ops[1].os_type, "linux1") self.assertFalse(ops[1].osparams) + def testErrors(self): + self.assertRaises(http.HttpBadRequest, self.Parse, + "foo", "not a dictionary") + class TestGroupRename(unittest.TestCase): def test(self): @@ -1195,6 +1474,20 @@ class TestInstanceReplaceDisks(unittest.TestCase): self.assertFalse(hasattr(op, "disks")) self.assertRaises(IndexError, cl.GetNextSubmittedJob) + def testNoDisks(self): + clfactory = _FakeClientFactory(_FakeClient) + + handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks, + ["inst20661"], {}, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + + for disks in [None, "", {}]: + handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks, + ["inst20661"], {}, { + "disks": disks, + }, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + def testWrong(self): clfactory = _FakeClientFactory(_FakeClient) @@ -1398,5 +1691,45 @@ class TestNodeRole(unittest.TestCase): self.assertRaises(IndexError, cl.GetNextSubmittedJob) +class TestSimpleResources(unittest.TestCase): + def setUp(self): + self.clfactory = _FakeClientFactory(_FakeClient) + + def tearDown(self): + self.assertRaises(IndexError, self.clfactory.GetNextClient) + + def testFeatures(self): + handler = _CreateHandler(rlib2.R_2_features, [], {}, None, self.clfactory) + self.assertEqual(set(handler.GET()), rlib2.ALL_FEATURES) + + def testEmpty(self): + for cls in [rlib2.R_root, rlib2.R_2]: + handler = _CreateHandler(cls, [], {}, None, self.clfactory) + self.assertTrue(handler.GET() is None) + + def testVersion(self): + handler = _CreateHandler(rlib2.R_version, [], {}, None, self.clfactory) + self.assertEqual(handler.GET(), constants.RAPI_VERSION) + + +class TestClusterInfo(unittest.TestCase): + class _ClusterInfoClient: + def __init__(self): + self.cluster_info = None + + def QueryClusterInfo(self): + assert self.cluster_info is None + self.cluster_info = object() + return self.cluster_info + + def test(self): + clfactory = _FakeClientFactory(self._ClusterInfoClient) + handler = _CreateHandler(rlib2.R_2_info, [], {}, None, clfactory) + result = handler.GET() + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + self.assertEqual(result, cl.cluster_info) + + if __name__ == '__main__': testutils.GanetiTestProgram()