X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/07ce3e70f04ccd7d59d4c0463397dbc1cc7e45af..43c16a8a1adfd543751fcaf60ad4c8e04cf83688:/test/ganeti.rapi.rlib2_unittest.py diff --git a/test/ganeti.rapi.rlib2_unittest.py b/test/ganeti.rapi.rlib2_unittest.py index 1b7fd51..cde68ce 100755 --- a/test/ganeti.rapi.rlib2_unittest.py +++ b/test/ganeti.rapi.rlib2_unittest.py @@ -25,25 +25,768 @@ import unittest -import tempfile +import itertools +import random from ganeti import constants from ganeti import opcodes from ganeti import compat from ganeti import http +from ganeti import query +from ganeti import luxi +from ganeti import errors from ganeti.rapi import rlib2 import testutils -class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) +class _FakeRequestPrivateData: + def __init__(self, body_data): + self.body_data = body_data + + +class _FakeRequest: + def __init__(self, body_data): + self.private = _FakeRequestPrivateData(body_data) + + +def _CreateHandler(cls, items, queryargs, body_data, client_cls): + return cls(items, queryargs, _FakeRequest(body_data), + _client_cls=client_cls) + + +class _FakeClient: + def __init__(self): + self._jobs = [] + + def GetNextSubmittedJob(self): + return self._jobs.pop(0) + + def SubmitJob(self, ops): + job_id = str(1 + int(random.random() * 1000000)) + self._jobs.append((job_id, ops)) + return job_id + + +class _FakeClientFactory: + def __init__(self, cls): + self._client_cls = cls + self._clients = [] + + def GetNextClient(self): + return self._clients.pop(0) + + def __call__(self): + cl = self._client_cls() + self._clients.append(cl) + return cl + + +class TestConstants(unittest.TestCase): + def testConsole(self): + # Exporting the console field without authentication might expose + # information + assert "console" in query.INSTANCE_FIELDS + self.assertTrue("console" not in rlib2.I_FIELDS) + + def testFields(self): + checks = { + constants.QR_INSTANCE: rlib2.I_FIELDS, + constants.QR_NODE: rlib2.N_FIELDS, + constants.QR_GROUP: rlib2.G_FIELDS, + } + + for (qr, fields) in checks.items(): + self.assertFalse(set(fields) - set(query.ALL_FIELDS[qr].keys())) + + +class TestClientConnectError(unittest.TestCase): + @staticmethod + def _FailingClient(): + raise luxi.NoMasterError("test") + + def test(self): + resources = [ + rlib2.R_2_groups, + rlib2.R_2_instances, + rlib2.R_2_nodes, + ] + for cls in resources: + handler = _CreateHandler(cls, ["name"], [], None, self._FailingClient) + self.assertRaises(http.HttpBadGateway, handler.GET) + + +class TestJobSubmitError(unittest.TestCase): + class _SubmitErrorClient: + @staticmethod + def SubmitJob(ops): + raise errors.JobQueueFull("test") + + def test(self): + handler = _CreateHandler(rlib2.R_2_redist_config, [], [], None, + self._SubmitErrorClient) + self.assertRaises(http.HttpServiceUnavailable, handler.PUT) + + +class TestClusterModify(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_cluster_modify, [], [], { + "vg_name": "testvg", + "candidate_pool_size": 100, + }, 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.OpClusterSetParams)) + self.assertEqual(op.vg_name, "testvg") + self.assertEqual(op.candidate_pool_size, 100) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testInvalidValue(self): + for attr in ["vg_name", "candidate_pool_size", "beparams", "_-Unknown#"]: + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_cluster_modify, [], [], { + attr: True, + }, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + self.assertRaises(IndexError, clfactory.GetNextClient) + + +class TestRedistConfig(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_redist_config, [], [], None, 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.OpClusterRedistConf)) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestNodeMigrate(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node1"], {}, { + "iallocator": "fooalloc", + }, 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.OpNodeMigrate)) + self.assertEqual(op.node_name, "node1") + self.assertEqual(op.iallocator, "fooalloc") + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testQueryArgsConflict(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node2"], { + "live": True, + "mode": constants.HT_MIGRATION_NONLIVE, + }, None, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + self.assertRaises(IndexError, clfactory.GetNextClient) + + def testQueryArgsMode(self): + clfactory = _FakeClientFactory(_FakeClient) + queryargs = { + "mode": [constants.HT_MIGRATION_LIVE], + } + handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node17292"], + queryargs, 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.OpNodeMigrate)) + self.assertEqual(op.node_name, "node17292") + self.assertEqual(op.mode, constants.HT_MIGRATION_LIVE) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testQueryArgsLive(self): + clfactory = _FakeClientFactory(_FakeClient) + + for live in [False, True]: + queryargs = { + "live": [str(int(live))], + } + handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node6940"], + queryargs, 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.OpNodeMigrate)) + self.assertEqual(op.node_name, "node6940") + if live: + self.assertEqual(op.mode, constants.HT_MIGRATION_LIVE) + else: + self.assertEqual(op.mode, constants.HT_MIGRATION_NONLIVE) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestNodeEvacuate(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_nodes_name_evacuate, ["node92"], { + "dry-run": ["1"], + }, { + "mode": constants.IALLOCATOR_NEVAC_SEC, + }, 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.OpNodeEvacuate)) + self.assertEqual(op.node_name, "node92") + self.assertEqual(op.mode, constants.IALLOCATOR_NEVAC_SEC) + self.assertTrue(op.dry_run) + + 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) + handler = _CreateHandler(rlib2.R_2_groups_name_assign_nodes, ["grp-a"], { + "dry-run": ["1"], + "force": ["1"], + }, { + "nodes": ["n2", "n3"], + }, 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.OpGroupAssignNodes)) + self.assertEqual(op.group_name, "grp-a") + self.assertEqual(op.nodes, ["n2", "n3"]) + self.assertTrue(op.dry_run) + self.assertTrue(op.force) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceDelete(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name, ["inst30965"], { + "dry-run": ["1"], + }, {}, clfactory) + job_id = handler.DELETE() + + 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.OpInstanceRemove)) + self.assertEqual(op.instance_name, "inst30965") + self.assertTrue(op.dry_run) + self.assertFalse(op.ignore_failures) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceInfo(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_info, ["inst31217"], { + "static": ["1"], + }, {}, clfactory) + job_id = handler.GET() + + 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.OpInstanceQueryData)) + self.assertEqual(op.instances, ["inst31217"]) + self.assertTrue(op.static) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceReboot(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_reboot, ["inst847"], { + "dry-run": ["1"], + "ignore_secondaries": ["1"], + }, {}, 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.OpInstanceReboot)) + self.assertEqual(op.instance_name, "inst847") + self.assertEqual(op.reboot_type, constants.INSTANCE_REBOOT_HARD) + self.assertTrue(op.ignore_secondaries) + self.assertTrue(op.dry_run) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceStartup(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_startup, ["inst31083"], { + "force": ["1"], + "no_remember": ["1"], + }, {}, 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.OpInstanceStartup)) + self.assertEqual(op.instance_name, "inst31083") + self.assertTrue(op.no_remember) + self.assertTrue(op.force) + self.assertFalse(op.dry_run) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceShutdown(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_shutdown, ["inst26791"], { + "no_remember": ["0"], + }, {}, 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.OpInstanceShutdown)) + self.assertEqual(op.instance_name, "inst26791") + self.assertFalse(op.no_remember) + self.assertFalse(op.dry_run) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceActivateDisks(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_activate_disks, ["xyz"], { + "ignore_size": ["1"], + }, {}, 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.OpInstanceActivateDisks)) + self.assertEqual(op.instance_name, "xyz") + self.assertTrue(op.ignore_size) + self.assertFalse(hasattr(op, "dry_run")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceDeactivateDisks(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_deactivate_disks, + ["inst22357"], {}, {}, 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.OpInstanceDeactivateDisks)) + self.assertEqual(op.instance_name, "inst22357") + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + - self.Parse = rlib2._ParseInstanceCreateRequestVersion1 +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) + handler = _CreateHandler(rlib2.R_2_instances_name_failover, + ["inst12794"], {}, {}, 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.OpInstanceFailover)) + self.assertEqual(op.instance_name, "inst12794") + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceDiskGrow(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + data = { + "amount": 1024, + } + handler = _CreateHandler(rlib2.R_2_instances_name_disk_grow, + ["inst10742", "3"], {}, 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.OpInstanceGrowDisk)) + self.assertEqual(op.instance_name, "inst10742") + self.assertEqual(op.disk, 3) + self.assertEqual(op.amount, 1024) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestBackupPrepare(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + queryargs = { + "mode": constants.EXPORT_MODE_REMOTE, + } + handler = _CreateHandler(rlib2.R_2_instances_name_prepare_export, + ["inst17925"], 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.OpBackupPrepare)) + self.assertEqual(op.instance_name, "inst17925") + self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestGroupRemove(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_groups_name, + ["grp28575"], {}, {}, clfactory) + job_id = handler.DELETE() + + 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.OpGroupRemove)) + self.assertEqual(op.group_name, "grp28575") + self.assertFalse(op.dry_run) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestStorageQuery(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + queryargs = { + "storage_type": constants.ST_LVM_PV, + "output_fields": "name,other", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage, + ["node21075"], queryargs, {}, clfactory) + job_id = handler.GET() + + 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.OpNodeQueryStorage)) + self.assertEqual(op.nodes, ["node21075"]) + self.assertEqual(op.storage_type, constants.ST_LVM_PV) + self.assertEqual(op.output_fields, ["name", "other"]) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testErrors(self): + clfactory = _FakeClientFactory(_FakeClient) + + queryargs = { + "output_fields": "name,other", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage, + ["node10538"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.GET) + + queryargs = { + "storage_type": constants.ST_LVM_VG, + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage, + ["node21273"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.GET) + + queryargs = { + "storage_type": "##unknown_storage##", + "output_fields": "name,other", + } + handler = _CreateHandler(rlib2.R_2_nodes_name_storage, + ["node10315"], queryargs, {}, clfactory) + self.assertRaises(http.HttpBadRequest, handler.GET) + + +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) + + 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 [], @@ -53,9 +796,6 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): # Disk with mode [{"size": 123, "mode": constants.DISK_RDWR, }], - - # With unknown setting - [{"size": 123, "unknown": 999 }], ] nic_variants = [ @@ -70,21 +810,21 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): { "ip": "192.0.2.6", "mode": constants.NIC_MODE_ROUTED, "mac": "01:23:45:67:68:9A", }, - { "mode": constants.NIC_MODE_BRIDGED, "link": "n0", "bridge": "br1", }, + { "mode": constants.NIC_MODE_BRIDGED, "link": "br1" }, ], - - # Unknown settings - [{ "unknown": 999, }, { "foobar": "Hello World", }], ] beparam_variants = [ 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 = [ @@ -100,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) @@ -137,55 +893,161 @@ class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase): self.assertFalse("foobar" in opnic) if beparams is None: - self.assertEqualValues(op.beparams, {}) + self.assertFalse(hasattr(op, "beparams")) else: self.assertEqualValues(op.beparams, beparams) if hvparams is None: - self.assertEqualValues(op.hvparams, {}) + self.assertFalse(hasattr(op, "hvparams")) else: 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, + } + + 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["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": [], + "nics": [], + "mode": constants.INSTANCE_CREATE, + "disk_template": constants.DT_PLAIN, + } + + 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["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": [], "mode": constants.INSTANCE_CREATE, "disk_template": constants.DT_PLAIN, - "os": "debootstrap", } 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"]: - invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"]] - - if field == "disks": - invalid_values.append([ - # Disks without size - {}, - { "mode": constants.DISK_RDWR, }, - ]) + invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"], + [{"_unknown_": 999, }]] 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) -class TestParseExportInstanceRequest(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) + # 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) - self.Parse = rlib2._ParseExportInstanceRequest + # 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): def test(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instmoo" data = { "mode": constants.EXPORT_MODE_REMOTE, @@ -195,43 +1057,72 @@ class TestParseExportInstanceRequest(testutils.GanetiTestCase): "x509_key_name": ["name", "hash"], "destination_x509_ca": "---cert---" } - op = self.Parse(name, data) - self.assert_(isinstance(op, opcodes.OpBackupExport)) + + handler = _CreateHandler(rlib2.R_2_instances_name_export, [name], {}, + data, 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.OpBackupExport)) self.assertEqual(op.instance_name, name) self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE) + self.assertEqual(op.target_node, [(1, 2, 3), (99, 99, 99)]) self.assertEqual(op.shutdown, True) self.assertEqual(op.remove_instance, True) - self.assertEqualValues(op.x509_key_name, ("name", "hash")) + self.assertEqual(op.x509_key_name, ["name", "hash"]) self.assertEqual(op.destination_x509_ca, "---cert---") + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "inst1" data = { "destination": "node2", "shutdown": False, } - op = self.Parse(name, data) - self.assert_(isinstance(op, opcodes.OpBackupExport)) + + handler = _CreateHandler(rlib2.R_2_instances_name_export, [name], {}, + data, 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.OpBackupExport)) self.assertEqual(op.instance_name, name) self.assertEqual(op.target_node, "node2") self.assertFalse(hasattr(op, "mode")) self.assertFalse(hasattr(op, "remove_instance")) self.assertFalse(hasattr(op, "destination")) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) - def testErrors(self): - self.assertRaises(http.HttpBadRequest, self.Parse, "err1", - { "remove_instance": "True", }) - self.assertRaises(http.HttpBadRequest, self.Parse, "err1", - { "remove_instance": "False", }) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + def testErrors(self): + clfactory = _FakeClientFactory(_FakeClient) -class TestParseMigrateInstanceRequest(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) + for value in ["True", "False"]: + handler = _CreateHandler(rlib2.R_2_instances_name_export, ["err1"], {}, { + "remove_instance": value, + }, clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) - self.Parse = rlib2._ParseMigrateInstanceRequest +class TestInstanceMigrate(testutils.GanetiTestCase): def test(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instYooho6ek" for cleanup in [False, True]: @@ -240,29 +1131,53 @@ class TestParseMigrateInstanceRequest(testutils.GanetiTestCase): "cleanup": cleanup, "mode": mode, } - op = self.Parse(name, data) - self.assert_(isinstance(op, opcodes.OpInstanceMigrate)) + + handler = _CreateHandler(rlib2.R_2_instances_name_migrate, [name], {}, + data, 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.OpInstanceMigrate)) self.assertEqual(op.instance_name, name) self.assertEqual(op.mode, mode) self.assertEqual(op.cleanup, cleanup) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instnohZeex0" - op = self.Parse(name, {}) - self.assert_(isinstance(op, opcodes.OpInstanceMigrate)) - self.assertEqual(op.instance_name, name) - self.assertEqual(op.mode, None) - self.assertFalse(op.cleanup) + handler = _CreateHandler(rlib2.R_2_instances_name_migrate, [name], {}, {}, + clfactory) + job_id = handler.PUT() + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) -class TestParseRenameInstanceRequest(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpInstanceMigrate)) + self.assertEqual(op.instance_name, name) + self.assertFalse(hasattr(op, "mode")) + self.assertFalse(hasattr(op, "cleanup")) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) - self.Parse = rlib2._ParseRenameInstanceRequest +class TestParseRenameInstanceRequest(testutils.GanetiTestCase): def test(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instij0eeph7" for new_name in ["ua0aiyoo", "fai3ongi"]: @@ -274,14 +1189,28 @@ class TestParseRenameInstanceRequest(testutils.GanetiTestCase): "name_check": name_check, } - op = self.Parse(name, data) - self.assert_(isinstance(op, opcodes.OpInstanceRename)) + handler = _CreateHandler(rlib2.R_2_instances_name_rename, [name], + {}, data, 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.OpInstanceRename)) self.assertEqual(op.instance_name, name) self.assertEqual(op.new_name, new_name) self.assertEqual(op.ip_check, ip_check) self.assertEqual(op.name_check, name_check) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instahchie3t" for new_name in ["thag9mek", "quees7oh"]: @@ -289,21 +1218,30 @@ class TestParseRenameInstanceRequest(testutils.GanetiTestCase): "new_name": new_name, } - op = self.Parse(name, data) - self.assert_(isinstance(op, opcodes.OpInstanceRename)) + handler = _CreateHandler(rlib2.R_2_instances_name_rename, [name], + {}, data, 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.OpInstanceRename)) self.assertEqual(op.instance_name, name) self.assertEqual(op.new_name, new_name) - self.assert_(op.ip_check) - self.assert_(op.name_check) + self.assertFalse(hasattr(op, "ip_check")) + self.assertFalse(hasattr(op, "name_check")) + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) -class TestParseModifyInstanceRequest(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) - - self.Parse = rlib2._ParseModifyInstanceRequest +class TestParseModifyInstanceRequest(unittest.TestCase): def test(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instush8gah" test_disks = [ @@ -313,7 +1251,7 @@ class TestParseModifyInstanceRequest(testutils.GanetiTestCase): 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: @@ -328,8 +1266,16 @@ class TestParseModifyInstanceRequest(testutils.GanetiTestCase): "disk_template": disk_template, } - op = self.Parse(name, data) - self.assert_(isinstance(op, opcodes.OpInstanceSetParams)) + handler = _CreateHandler(rlib2.R_2_instances_name_modify, + [name], {}, data, 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.OpInstanceSetParams)) self.assertEqual(op.instance_name, name) self.assertEqual(op.hvparams, hvparams) self.assertEqual(op.beparams, beparams) @@ -338,26 +1284,33 @@ class TestParseModifyInstanceRequest(testutils.GanetiTestCase): self.assertEqual(op.nics, nics) self.assertEqual(op.disks, disks) self.assertEqual(op.disk_template, disk_template) - self.assert_(op.remote_node is None) - self.assert_(op.os_name is None) - self.assertFalse(op.force_variant) + self.assertFalse(hasattr(op, "remote_node")) + self.assertFalse(hasattr(op, "os_name")) + self.assertFalse(hasattr(op, "force_variant")) + self.assertFalse(hasattr(op, "dry_run")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + name = "instir8aish31" - op = self.Parse(name, {}) - self.assert_(isinstance(op, opcodes.OpInstanceSetParams)) + handler = _CreateHandler(rlib2.R_2_instances_name_modify, + [name], {}, {}, 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.OpInstanceSetParams)) self.assertEqual(op.instance_name, name) - self.assertEqual(op.hvparams, {}) - self.assertEqual(op.beparams, {}) - self.assertEqual(op.osparams, {}) - self.assertFalse(op.force) - self.assertEqual(op.nics, []) - self.assertEqual(op.disks, []) - self.assert_(op.disk_template is None) - self.assert_(op.remote_node is None) - self.assert_(op.os_name is None) - self.assertFalse(op.force_variant) + + for i in ["hvparams", "beparams", "osparams", "force", "nics", "disks", + "disk_template", "remote_node", "os_name", "force_variant"]: + self.assertFalse(hasattr(op, i)) class TestParseInstanceReinstallRequest(testutils.GanetiTestCase): @@ -410,38 +1363,372 @@ 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 TestParseRenameGroupRequest(testutils.GanetiTestCase): - def setUp(self): - testutils.GanetiTestCase.setUp(self) - - self.Parse = rlib2._ParseRenameGroupRequest +class TestGroupRename(unittest.TestCase): def test(self): - name = "instij0eeph7" + clfactory = _FakeClientFactory(_FakeClient) + + name = "group608242564" data = { - "new_name": "ua0aiyoo", + "new_name": "ua0aiyoo15112", } - op = self.Parse(name, data, False) + handler = _CreateHandler(rlib2.R_2_groups_name_rename, [name], {}, data, + clfactory) + job_id = handler.PUT() - self.assert_(isinstance(op, opcodes.OpGroupRename)) - self.assertEqual(op.old_name, name) - self.assertEqual(op.new_name, "ua0aiyoo") + 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.OpGroupRename)) + self.assertEqual(op.group_name, name) + self.assertEqual(op.new_name, "ua0aiyoo15112") self.assertFalse(op.dry_run) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) def testDryRun(self): - name = "instij0eeph7" + clfactory = _FakeClientFactory(_FakeClient) + + name = "group28548" data = { "new_name": "ua0aiyoo", } - op = self.Parse(name, data, True) + handler = _CreateHandler(rlib2.R_2_groups_name_rename, [name], { + "dry-run": ["1"], + }, data, clfactory) + job_id = handler.PUT() - self.assert_(isinstance(op, opcodes.OpGroupRename)) - self.assertEqual(op.old_name, name) + 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.OpGroupRename)) + self.assertEqual(op.group_name, name) self.assertEqual(op.new_name, "ua0aiyoo") - self.assert_(op.dry_run) + self.assertTrue(op.dry_run) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestInstanceReplaceDisks(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "inst22568" + + for disks in [range(1, 4), "1,2,3", "1, 2, 3"]: + data = { + "mode": constants.REPLACE_DISK_SEC, + "disks": disks, + "iallocator": "myalloc", + } + + handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks, + [name], {}, 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.OpInstanceReplaceDisks)) + self.assertEqual(op.instance_name, name) + self.assertEqual(op.mode, constants.REPLACE_DISK_SEC) + self.assertEqual(op.disks, [1, 2, 3]) + self.assertEqual(op.iallocator, "myalloc") + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "inst11413" + data = { + "mode": constants.REPLACE_DISK_AUTO, + } + + handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks, + [name], {}, 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.OpInstanceReplaceDisks)) + self.assertEqual(op.instance_name, name) + self.assertEqual(op.mode, constants.REPLACE_DISK_AUTO) + self.assertFalse(hasattr(op, "iallocator")) + 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) + + data = { + "mode": constants.REPLACE_DISK_AUTO, + "disks": "hello world", + } + + handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks, + ["foo"], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + + +class TestGroupModify(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "group6002" + + for policy in constants.VALID_ALLOC_POLICIES: + data = { + "alloc_policy": policy, + } + + handler = _CreateHandler(rlib2.R_2_groups_name_modify, [name], {}, data, + 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.OpGroupSetParams)) + self.assertEqual(op.group_name, name) + self.assertEqual(op.alloc_policy, policy) + self.assertFalse(hasattr(op, "dry_run")) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testUnknownPolicy(self): + clfactory = _FakeClientFactory(_FakeClient) + + data = { + "alloc_policy": "_unknown_policy_", + } + + handler = _CreateHandler(rlib2.R_2_groups_name_modify, ["xyz"], {}, data, + clfactory) + self.assertRaises(http.HttpBadRequest, handler.PUT) + self.assertRaises(IndexError, clfactory.GetNextClient) + + def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "group6679" + + handler = _CreateHandler(rlib2.R_2_groups_name_modify, [name], {}, {}, + 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.OpGroupSetParams)) + self.assertEqual(op.group_name, name) + self.assertFalse(hasattr(op, "alloc_policy")) + self.assertFalse(hasattr(op, "dry_run")) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + +class TestGroupAdd(unittest.TestCase): + def test(self): + name = "group3618" + clfactory = _FakeClientFactory(_FakeClient) + + for policy in constants.VALID_ALLOC_POLICIES: + data = { + "group_name": name, + "alloc_policy": policy, + } + + handler = _CreateHandler(rlib2.R_2_groups, [], {}, 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.OpGroupAdd)) + self.assertEqual(op.group_name, name) + self.assertEqual(op.alloc_policy, policy) + self.assertFalse(op.dry_run) + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + def testUnknownPolicy(self): + clfactory = _FakeClientFactory(_FakeClient) + + data = { + "alloc_policy": "_unknown_policy_", + } + + handler = _CreateHandler(rlib2.R_2_groups, [], {}, data, clfactory) + self.assertRaises(http.HttpBadRequest, handler.POST) + self.assertRaises(IndexError, clfactory.GetNextClient) + + def testDefaults(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "group15395" + data = { + "group_name": name, + } + + handler = _CreateHandler(rlib2.R_2_groups, [], {}, 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.OpGroupAdd)) + self.assertEqual(op.group_name, name) + self.assertFalse(hasattr(op, "alloc_policy")) + self.assertFalse(op.dry_run) + + def testLegacyName(self): + clfactory = _FakeClientFactory(_FakeClient) + + name = "group29852" + data = { + "name": name, + } + + handler = _CreateHandler(rlib2.R_2_groups, [], { + "dry-run": ["1"], + }, 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.OpGroupAdd)) + self.assertEqual(op.group_name, name) + self.assertFalse(hasattr(op, "alloc_policy")) + self.assertTrue(op.dry_run) + + +class TestNodeRole(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + + for role in rlib2._NR_MAP.values(): + handler = _CreateHandler(rlib2.R_2_nodes_name_role, + ["node-z"], {}, role, clfactory) + if role == rlib2._NR_MASTER: + self.assertRaises(http.HttpBadRequest, handler.PUT) + else: + 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.OpNodeSetParams)) + self.assertEqual(op.node_name, "node-z") + self.assertFalse(op.force) + self.assertFalse(hasattr(op, "dry_run")) + + if role == rlib2._NR_REGULAR: + self.assertFalse(op.drained) + self.assertFalse(op.offline) + self.assertFalse(op.master_candidate) + elif role == rlib2._NR_MASTER_CANDIDATE: + self.assertFalse(op.drained) + self.assertFalse(op.offline) + self.assertTrue(op.master_candidate) + elif role == rlib2._NR_DRAINED: + self.assertTrue(op.drained) + self.assertFalse(op.offline) + self.assertFalse(op.master_candidate) + elif role == rlib2._NR_OFFLINE: + self.assertFalse(op.drained) + self.assertTrue(op.offline) + self.assertFalse(op.master_candidate) + else: + self.fail("Unknown role '%s'" % role) + + 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__':