X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/752df8bb5fcc0c8ebb4570dc3f9d9b3c91e0858f..c08d76f5f297ead72045c8dc7212bc76195f47e6:/test/ganeti.rapi.client_unittest.py?ds=sidebyside diff --git a/test/ganeti.rapi.client_unittest.py b/test/ganeti.rapi.client_unittest.py index 9da775c..10c23d0 100755 --- a/test/ganeti.rapi.client_unittest.py +++ b/test/ganeti.rapi.client_unittest.py @@ -27,6 +27,7 @@ import unittest import warnings from ganeti import http +from ganeti import serializer from ganeti.rapi import connector from ganeti.rapi import rlib2 @@ -80,51 +81,42 @@ class OpenerDirectorMock: class RapiMock(object): - def __init__(self): self._mapper = connector.Mapper() self._responses = [] self._last_handler = None - def AddResponse(self, response): - self._responses.insert(0, response) - - def PopResponse(self): - if len(self._responses) > 0: - return self._responses.pop() - else: - return None + def AddResponse(self, response, code=200): + self._responses.insert(0, (code, response)) def GetLastHandler(self): return self._last_handler def FetchResponse(self, path, method): - code = 200 - response = None - try: HandlerClass, items, args = self._mapper.getController(path) self._last_handler = HandlerClass(items, args, None) if not hasattr(self._last_handler, method.upper()): - code = 400 - response = "Bad request" + raise http.HttpNotImplemented(message="Method not implemented") + except http.HttpException, ex: code = ex.code response = ex.message + else: + if not self._responses: + raise Exception("No responses") - if not response: - response = self.PopResponse() + (code, response) = self._responses.pop() return code, response class RapiMockTest(unittest.TestCase): - def test(self): rapi = RapiMock() path = "/version" self.assertEqual((404, None), rapi.FetchResponse("/foo", "GET")) - self.assertEqual((400, "Bad request"), + self.assertEqual((501, "Method not implemented"), rapi.FetchResponse("/version", "POST")) rapi.AddResponse("2") code, response = rapi.FetchResponse("/version", "GET") @@ -133,12 +125,10 @@ class RapiMockTest(unittest.TestCase): self.failUnless(isinstance(rapi.GetLastHandler(), rlib2.R_version)) -class GanetiRapiClientTests(unittest.TestCase): - """Tests for remote API client. - - """ - +class GanetiRapiClientTests(testutils.GanetiTestCase): def setUp(self): + testutils.GanetiTestCase.setUp(self) + self.rapi = RapiMock() self.http = OpenerDirectorMock(self.rapi) self.client = client.GanetiRapiClient('master.foo.com') @@ -161,12 +151,51 @@ class GanetiRapiClientTests(unittest.TestCase): def assertDryRun(self): self.assertTrue(self.rapi.GetLastHandler().dryRun()) + def testEncodeQuery(self): + query = [ + ("a", None), + ("b", 1), + ("c", 2), + ("d", "Foo"), + ("e", True), + ] + + expected = [ + ("a", ""), + ("b", 1), + ("c", 2), + ("d", "Foo"), + ("e", 1), + ] + + self.assertEqualValues(self.client._EncodeQuery(query), + expected) + + # invalid types + for i in [[1, 2, 3], {"moo": "boo"}, (1, 2, 3)]: + self.assertRaises(ValueError, self.client._EncodeQuery, [("x", i)]) + + def testHttpError(self): + self.rapi.AddResponse(None, code=404) + try: + self.client.GetJobStatus(15140) + except client.GanetiApiError, err: + self.assertEqual(err.code, 404) + else: + self.fail("Didn't raise exception") + def testGetVersion(self): self.client._version = None self.rapi.AddResponse("2") self.assertEqual(2, self.client.GetVersion()) self.assertHandler(rlib2.R_version) + def testGetFeatures(self): + for features in [[], ["foo", "bar", "baz"]]: + self.rapi.AddResponse(serializer.DumpJson(features)) + self.assertEqual(features, self.client.GetFeatures()) + self.assertHandler(rlib2.R_2_features) + def testGetOperatingSystems(self): self.rapi.AddResponse("[\"beos\"]") self.assertEqual(["beos"], self.client.GetOperatingSystems()) @@ -204,18 +233,75 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertHandler(rlib2.R_2_instances) self.assertBulk() - def testGetInstanceInfo(self): + def testGetInstance(self): self.rapi.AddResponse("[]") - self.assertEqual([], self.client.GetInstanceInfo("instance")) + self.assertEqual([], self.client.GetInstance("instance")) self.assertHandler(rlib2.R_2_instances_name) self.assertItems(["instance"]) + def testGetInstanceInfo(self): + self.rapi.AddResponse("21291") + self.assertEqual(21291, self.client.GetInstanceInfo("inst3")) + self.assertHandler(rlib2.R_2_instances_name_info) + self.assertItems(["inst3"]) + self.assertQuery("static", None) + + self.rapi.AddResponse("3428") + self.assertEqual(3428, self.client.GetInstanceInfo("inst31", static=False)) + self.assertHandler(rlib2.R_2_instances_name_info) + self.assertItems(["inst31"]) + self.assertQuery("static", ["0"]) + + self.rapi.AddResponse("15665") + self.assertEqual(15665, self.client.GetInstanceInfo("inst32", static=True)) + self.assertHandler(rlib2.R_2_instances_name_info) + self.assertItems(["inst32"]) + self.assertQuery("static", ["1"]) + + def testCreateInstanceOldVersion(self): + self.rapi.AddResponse(serializer.DumpJson([])) + self.assertRaises(NotImplementedError, self.client.CreateInstance, + "create", "inst1.example.com", "plain", [], [], + dry_run=True) + def testCreateInstance(self): - self.rapi.AddResponse("1234") - self.assertEqual(1234, self.client.CreateInstance(dry_run=True)) + self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1])) + self.rapi.AddResponse("23030") + job_id = self.client.CreateInstance("create", "inst1.example.com", + "plain", [], [], dry_run=True) + self.assertEqual(job_id, 23030) self.assertHandler(rlib2.R_2_instances) self.assertDryRun() + data = serializer.LoadJson(self.http.last_request.data) + + for field in ["dry_run", "beparams", "hvparams", "start"]: + self.assertFalse(field in data) + + self.assertEqual(data["name"], "inst1.example.com") + self.assertEqual(data["disk_template"], "plain") + + def testCreateInstance2(self): + self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1])) + self.rapi.AddResponse("24740") + job_id = self.client.CreateInstance("import", "inst2.example.com", + "drbd8", [{"size": 100,}], + [{}, {"bridge": "br1", }], + dry_run=False, start=True, + pnode="node1", snode="node9", + ip_check=False) + self.assertEqual(job_id, 24740) + self.assertHandler(rlib2.R_2_instances) + + data = serializer.LoadJson(self.http.last_request.data) + self.assertEqual(data[rlib2._REQ_DATA_VERSION], 1) + self.assertEqual(data["name"], "inst2.example.com") + self.assertEqual(data["disk_template"], "drbd8") + self.assertEqual(data["start"], True) + self.assertEqual(data["ip_check"], False) + self.assertEqualValues(data["disks"], [{"size": 100,}]) + self.assertEqualValues(data["nics"], [{}, {"bridge": "br1", }]) + def testDeleteInstance(self): self.rapi.AddResponse("1234") self.assertEqual(1234, self.client.DeleteInstance("instance", dry_run=True)) @@ -256,7 +342,7 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertItems(["i-bar"]) self.assertDryRun() self.assertQuery("type", ["hard"]) - self.assertQuery("ignore_secondaries", ["True"]) + self.assertQuery("ignore_secondaries", ["1"]) def testShutdownInstance(self): self.rapi.AddResponse("1487") @@ -286,32 +372,50 @@ class GanetiRapiClientTests(unittest.TestCase): def testReplaceInstanceDisks(self): self.rapi.AddResponse("999") job_id = self.client.ReplaceInstanceDisks("instance-name", - ["hda", "hdc"], dry_run=True) + disks=[0, 1], dry_run=True, iallocator="hail") self.assertEqual(999, job_id) self.assertHandler(rlib2.R_2_instances_name_replace_disks) self.assertItems(["instance-name"]) - self.assertQuery("disks", ["hda,hdc"]) + self.assertQuery("disks", ["0,1"]) self.assertQuery("mode", ["replace_auto"]) self.assertQuery("iallocator", ["hail"]) self.assertDryRun() - self.assertRaises(client.InvalidReplacementMode, - self.client.ReplaceInstanceDisks, - "instance_a", ["hda"], mode="invalid_mode") - self.assertRaises(client.GanetiApiError, - self.client.ReplaceInstanceDisks, - "instance-foo", ["hda"], mode="replace_on_secondary") - self.rapi.AddResponse("1000") job_id = self.client.ReplaceInstanceDisks("instance-bar", - ["hda"], mode="replace_on_secondary", remote_node="foo-node", + disks=[1], mode="replace_on_secondary", remote_node="foo-node", dry_run=True) self.assertEqual(1000, job_id) self.assertItems(["instance-bar"]) - self.assertQuery("disks", ["hda"]) + self.assertQuery("disks", ["1"]) self.assertQuery("remote_node", ["foo-node"]) self.assertDryRun() + self.rapi.AddResponse("5175") + self.assertEqual(5175, self.client.ReplaceInstanceDisks("instance-moo")) + self.assertItems(["instance-moo"]) + self.assertQuery("disks", None) + + def testPrepareExport(self): + self.rapi.AddResponse("8326") + self.assertEqual(8326, self.client.PrepareExport("inst1", "local")) + self.assertHandler(rlib2.R_2_instances_name_prepare_export) + self.assertItems(["inst1"]) + self.assertQuery("mode", ["local"]) + + def testExportInstance(self): + self.rapi.AddResponse("19695") + job_id = self.client.ExportInstance("inst2", "local", "nodeX", + shutdown=True) + self.assertEqual(job_id, 19695) + self.assertHandler(rlib2.R_2_instances_name_export) + self.assertItems(["inst2"]) + + data = serializer.LoadJson(self.http.last_request.data) + self.assertEqual(data["mode"], "local") + self.assertEqual(data["destination"], "nodeX") + self.assertEqual(data["shutdown"], True) + def testGetJobs(self): self.rapi.AddResponse('[ { "id": "123", "uri": "\\/2\\/jobs\\/123" },' ' { "id": "124", "uri": "\\/2\\/jobs\\/124" } ]') @@ -324,10 +428,23 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertHandler(rlib2.R_2_jobs_id) self.assertItems(["1234"]) - def testDeleteJob(self): + def testWaitForJobChange(self): + fields = ["id", "summary"] + expected = { + "job_info": [123, "something"], + "log_entries": [], + } + + self.rapi.AddResponse(serializer.DumpJson(expected)) + result = self.client.WaitForJobChange(123, fields, [], -1) + self.assertEqualValues(expected, result) + self.assertHandler(rlib2.R_2_jobs_id_wait) + self.assertItems(["123"]) + + def testCancelJob(self): self.rapi.AddResponse("[true, \"Job 123 will be canceled\"]") self.assertEqual([True, "Job 123 will be canceled"], - self.client.DeleteJob(999, dry_run=True)) + self.client.CancelJob(999, dry_run=True)) self.assertHandler(rlib2.R_2_jobs_id) self.assertItems(["999"]) self.assertDryRun() @@ -346,9 +463,9 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertHandler(rlib2.R_2_nodes) self.assertBulk() - def testGetNodeInfo(self): + def testGetNode(self): self.rapi.AddResponse("{}") - self.assertEqual({}, self.client.GetNodeInfo("node-foo")) + self.assertEqual({}, self.client.GetNode("node-foo")) self.assertHandler(rlib2.R_2_nodes_name) self.assertItems(["node-foo"]) @@ -391,12 +508,9 @@ class GanetiRapiClientTests(unittest.TestCase): self.client.SetNodeRole("node-foo", "master-candidate", force=True)) self.assertHandler(rlib2.R_2_nodes_name_role) self.assertItems(["node-foo"]) - self.assertQuery("force", ["True"]) + self.assertQuery("force", ["1"]) self.assertEqual("\"master-candidate\"", self.http.last_request.data) - self.assertRaises(client.InvalidNodeRole, - self.client.SetNodeRole, "node-bar", "fake-role") - def testGetNodeStorageUnits(self): self.rapi.AddResponse("42") self.assertEqual(42, @@ -406,10 +520,6 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertQuery("storage_type", ["lvm-pv"]) self.assertQuery("output_fields", ["fields"]) - self.assertRaises(client.InvalidStorageType, - self.client.GetNodeStorageUnits, - "node-y", "floppy-disk", "fields") - def testModifyNodeStorageUnits(self): self.rapi.AddResponse("14") self.assertEqual(14, @@ -418,10 +528,18 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertItems(["node-z"]) self.assertQuery("storage_type", ["lvm-pv"]) self.assertQuery("name", ["hda"]) - - self.assertRaises(client.InvalidStorageType, - self.client.ModifyNodeStorageUnits, - "node-n", "floppy-disk", "hdc") + self.assertQuery("allocatable", None) + + for allocatable, query_allocatable in [(True, "1"), (False, "0")]: + self.rapi.AddResponse("7205") + job_id = self.client.ModifyNodeStorageUnits("node-z", "lvm-pv", "hda", + allocatable=allocatable) + self.assertEqual(7205, job_id) + self.assertHandler(rlib2.R_2_nodes_name_storage_modify) + self.assertItems(["node-z"]) + self.assertQuery("storage_type", ["lvm-pv"]) + self.assertQuery("name", ["hda"]) + self.assertQuery("allocatable", [query_allocatable]) def testRepairNodeStorageUnits(self): self.rapi.AddResponse("99") @@ -432,10 +550,6 @@ class GanetiRapiClientTests(unittest.TestCase): self.assertQuery("storage_type", ["lvm-pv"]) self.assertQuery("name", ["hda"]) - self.assertRaises(client.InvalidStorageType, - self.client.RepairNodeStorageUnits, - "node-n", "floppy-disk", "hdc") - def testGetNodeTags(self): self.rapi.AddResponse("[\"fry\", \"bender\"]") self.assertEqual(["fry", "bender"], self.client.GetNodeTags("node-k"))