4 # Copyright (C) 2010, 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 RAPI client module"""
29 from ganeti import opcodes
30 from ganeti import constants
31 from ganeti import http
32 from ganeti import serializer
33 from ganeti import utils
34 from ganeti import query
35 from ganeti import objects
36 from ganeti import rapi
38 import ganeti.rapi.testutils
39 from ganeti.rapi import connector
40 from ganeti.rapi import rlib2
41 from ganeti.rapi import client
46 # List of resource handlers which aren't used by the RAPI client
52 # Global variable for collecting used handlers
56 class RapiMock(object):
58 self._mapper = connector.Mapper()
60 self._last_handler = None
61 self._last_req_data = None
63 def ResetResponses(self):
64 del self._responses[:]
66 def AddResponse(self, response, code=200):
67 self._responses.insert(0, (code, response))
69 def CountPending(self):
70 return len(self._responses)
72 def GetLastHandler(self):
73 return self._last_handler
75 def GetLastRequestData(self):
76 return self._last_req_data
78 def FetchResponse(self, path, method, headers, request_body):
79 self._last_req_data = request_body
82 (handler_cls, items, args) = self._mapper.getController(path)
84 # Record handler as used
85 _used_handlers.add(handler_cls)
87 self._last_handler = handler_cls(items, args, None)
88 if not hasattr(self._last_handler, method.upper()):
89 raise http.HttpNotImplemented(message="Method not implemented")
91 except http.HttpException, ex:
95 if not self._responses:
96 raise Exception("No responses")
98 (code, response) = self._responses.pop()
100 return (code, NotImplemented, response)
103 class TestConstants(unittest.TestCase):
105 self.assertEqual(client.GANETI_RAPI_PORT, constants.DEFAULT_RAPI_PORT)
106 self.assertEqual(client.GANETI_RAPI_VERSION, constants.RAPI_VERSION)
107 self.assertEqual(client.HTTP_APP_JSON, http.HTTP_APP_JSON)
108 self.assertEqual(client._REQ_DATA_VERSION_FIELD, rlib2._REQ_DATA_VERSION)
109 self.assertEqual(client.JOB_STATUS_QUEUED, constants.JOB_STATUS_QUEUED)
110 self.assertEqual(client.JOB_STATUS_WAITING, constants.JOB_STATUS_WAITING)
111 self.assertEqual(client.JOB_STATUS_CANCELING,
112 constants.JOB_STATUS_CANCELING)
113 self.assertEqual(client.JOB_STATUS_RUNNING, constants.JOB_STATUS_RUNNING)
114 self.assertEqual(client.JOB_STATUS_CANCELED, constants.JOB_STATUS_CANCELED)
115 self.assertEqual(client.JOB_STATUS_SUCCESS, constants.JOB_STATUS_SUCCESS)
116 self.assertEqual(client.JOB_STATUS_ERROR, constants.JOB_STATUS_ERROR)
117 self.assertEqual(client.JOB_STATUS_PENDING, constants.JOBS_PENDING)
118 self.assertEqual(client.JOB_STATUS_FINALIZED, constants.JOBS_FINALIZED)
119 self.assertEqual(client.JOB_STATUS_ALL, constants.JOB_STATUS_ALL)
122 self.assertEqual(client.NODE_EVAC_PRI, constants.NODE_EVAC_PRI)
123 self.assertEqual(client.NODE_EVAC_SEC, constants.NODE_EVAC_SEC)
124 self.assertEqual(client.NODE_EVAC_ALL, constants.NODE_EVAC_ALL)
127 self.assertEqual(client.JOB_STATUS_WAITLOCK, constants.JOB_STATUS_WAITING)
129 # RAPI feature strings
130 self.assertEqual(client._INST_CREATE_REQV1, rlib2._INST_CREATE_REQV1)
131 self.assertEqual(client.INST_CREATE_REQV1, rlib2._INST_CREATE_REQV1)
132 self.assertEqual(client._INST_REINSTALL_REQV1, rlib2._INST_REINSTALL_REQV1)
133 self.assertEqual(client.INST_REINSTALL_REQV1, rlib2._INST_REINSTALL_REQV1)
134 self.assertEqual(client._NODE_MIGRATE_REQV1, rlib2._NODE_MIGRATE_REQV1)
135 self.assertEqual(client.NODE_MIGRATE_REQV1, rlib2._NODE_MIGRATE_REQV1)
136 self.assertEqual(client._NODE_EVAC_RES1, rlib2._NODE_EVAC_RES1)
137 self.assertEqual(client.NODE_EVAC_RES1, rlib2._NODE_EVAC_RES1)
140 class RapiMockTest(unittest.TestCase):
142 (code, _, body) = RapiMock().FetchResponse("/foo", "GET", None, None)
143 self.assertEqual(code, 404)
144 self.assertTrue(body is None)
147 (code, _, body) = RapiMock().FetchResponse("/version", "POST", None, None)
148 self.assertEqual(code, 501)
149 self.assertEqual(body, "Method not implemented")
153 rapi.AddResponse("2")
154 (code, _, response) = rapi.FetchResponse("/version", "GET", None, None)
155 self.assertEqual(200, code)
156 self.assertEqual("2", response)
157 self.failUnless(isinstance(rapi.GetLastHandler(), rlib2.R_version))
160 def _FakeNoSslPycurlVersion():
161 # Note: incomplete version tuple
162 return (3, "7.16.0", 462848, "mysystem", 1581, None, 0)
165 def _FakeFancySslPycurlVersion():
166 # Note: incomplete version tuple
167 return (3, "7.16.0", 462848, "mysystem", 1581, "FancySSL/1.2.3", 0)
170 def _FakeOpenSslPycurlVersion():
171 # Note: incomplete version tuple
172 return (2, "7.15.5", 462597, "othersystem", 668, "OpenSSL/0.9.8c", 0)
175 def _FakeGnuTlsPycurlVersion():
176 # Note: incomplete version tuple
177 return (3, "7.18.0", 463360, "somesystem", 1581, "GnuTLS/2.0.4", 0)
180 class TestExtendedConfig(unittest.TestCase):
182 cl = client.GanetiRapiClient("master.example.com",
183 username="user", password="pw",
184 curl_factory=lambda: rapi.testutils.FakeCurl(RapiMock()))
186 curl = cl._CreateCurl()
187 self.assertEqual(curl.getopt(pycurl.HTTPAUTH), pycurl.HTTPAUTH_BASIC)
188 self.assertEqual(curl.getopt(pycurl.USERPWD), "user:pw")
190 def testInvalidAuth(self):
192 self.assertRaises(client.Error, client.GanetiRapiClient,
193 "master-a.example.com", password="pw")
195 self.assertRaises(client.Error, client.GanetiRapiClient,
196 "master-b.example.com", username="user")
198 def testCertVerifyInvalidCombinations(self):
199 self.assertRaises(client.Error, client.GenericCurlConfig,
200 use_curl_cabundle=True, cafile="cert1.pem")
201 self.assertRaises(client.Error, client.GenericCurlConfig,
202 use_curl_cabundle=True, capath="certs/")
203 self.assertRaises(client.Error, client.GenericCurlConfig,
204 use_curl_cabundle=True,
205 cafile="cert1.pem", capath="certs/")
207 def testProxySignalVerifyHostname(self):
208 for use_gnutls in [False, True]:
210 pcverfn = _FakeGnuTlsPycurlVersion
212 pcverfn = _FakeOpenSslPycurlVersion
214 for proxy in ["", "http://127.0.0.1:1234"]:
215 for use_signal in [False, True]:
216 for verify_hostname in [False, True]:
217 cfgfn = client.GenericCurlConfig(proxy=proxy, use_signal=use_signal,
218 verify_hostname=verify_hostname,
219 _pycurl_version_fn=pcverfn)
221 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
222 cl = client.GanetiRapiClient("master.example.com",
223 curl_config_fn=cfgfn,
224 curl_factory=curl_factory)
226 curl = cl._CreateCurl()
227 self.assertEqual(curl.getopt(pycurl.PROXY), proxy)
228 self.assertEqual(curl.getopt(pycurl.NOSIGNAL), not use_signal)
231 self.assertEqual(curl.getopt(pycurl.SSL_VERIFYHOST), 2)
233 self.assertEqual(curl.getopt(pycurl.SSL_VERIFYHOST), 0)
235 def testNoCertVerify(self):
236 cfgfn = client.GenericCurlConfig()
238 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
239 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
240 curl_factory=curl_factory)
242 curl = cl._CreateCurl()
243 self.assertFalse(curl.getopt(pycurl.SSL_VERIFYPEER))
244 self.assertFalse(curl.getopt(pycurl.CAINFO))
245 self.assertFalse(curl.getopt(pycurl.CAPATH))
247 def testCertVerifyCurlBundle(self):
248 cfgfn = client.GenericCurlConfig(use_curl_cabundle=True)
250 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
251 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
252 curl_factory=curl_factory)
254 curl = cl._CreateCurl()
255 self.assert_(curl.getopt(pycurl.SSL_VERIFYPEER))
256 self.assertFalse(curl.getopt(pycurl.CAINFO))
257 self.assertFalse(curl.getopt(pycurl.CAPATH))
259 def testCertVerifyCafile(self):
260 mycert = "/tmp/some/UNUSED/cert/file.pem"
261 cfgfn = client.GenericCurlConfig(cafile=mycert)
263 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
264 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
265 curl_factory=curl_factory)
267 curl = cl._CreateCurl()
268 self.assert_(curl.getopt(pycurl.SSL_VERIFYPEER))
269 self.assertEqual(curl.getopt(pycurl.CAINFO), mycert)
270 self.assertFalse(curl.getopt(pycurl.CAPATH))
272 def testCertVerifyCapath(self):
273 certdir = "/tmp/some/UNUSED/cert/directory"
274 pcverfn = _FakeOpenSslPycurlVersion
275 cfgfn = client.GenericCurlConfig(capath=certdir,
276 _pycurl_version_fn=pcverfn)
278 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
279 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
280 curl_factory=curl_factory)
282 curl = cl._CreateCurl()
283 self.assert_(curl.getopt(pycurl.SSL_VERIFYPEER))
284 self.assertEqual(curl.getopt(pycurl.CAPATH), certdir)
285 self.assertFalse(curl.getopt(pycurl.CAINFO))
287 def testCertVerifyCapathGnuTls(self):
288 certdir = "/tmp/some/UNUSED/cert/directory"
289 pcverfn = _FakeGnuTlsPycurlVersion
290 cfgfn = client.GenericCurlConfig(capath=certdir,
291 _pycurl_version_fn=pcverfn)
293 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
294 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
295 curl_factory=curl_factory)
297 self.assertRaises(client.Error, cl._CreateCurl)
299 def testCertVerifyNoSsl(self):
300 certdir = "/tmp/some/UNUSED/cert/directory"
301 pcverfn = _FakeNoSslPycurlVersion
302 cfgfn = client.GenericCurlConfig(capath=certdir,
303 _pycurl_version_fn=pcverfn)
305 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
306 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
307 curl_factory=curl_factory)
309 self.assertRaises(client.Error, cl._CreateCurl)
311 def testCertVerifyFancySsl(self):
312 certdir = "/tmp/some/UNUSED/cert/directory"
313 pcverfn = _FakeFancySslPycurlVersion
314 cfgfn = client.GenericCurlConfig(capath=certdir,
315 _pycurl_version_fn=pcverfn)
317 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
318 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
319 curl_factory=curl_factory)
321 self.assertRaises(NotImplementedError, cl._CreateCurl)
323 def testCertVerifyCapath(self):
324 for connect_timeout in [None, 1, 5, 10, 30, 60, 300]:
325 for timeout in [None, 1, 30, 60, 3600, 24 * 3600]:
326 cfgfn = client.GenericCurlConfig(connect_timeout=connect_timeout,
329 curl_factory = lambda: rapi.testutils.FakeCurl(RapiMock())
330 cl = client.GanetiRapiClient("master.example.com", curl_config_fn=cfgfn,
331 curl_factory=curl_factory)
333 curl = cl._CreateCurl()
334 self.assertEqual(curl.getopt(pycurl.CONNECTTIMEOUT), connect_timeout)
335 self.assertEqual(curl.getopt(pycurl.TIMEOUT), timeout)
338 class GanetiRapiClientTests(testutils.GanetiTestCase):
340 testutils.GanetiTestCase.setUp(self)
342 self.rapi = RapiMock()
343 self.curl = rapi.testutils.FakeCurl(self.rapi)
344 self.client = client.GanetiRapiClient("master.example.com",
345 curl_factory=lambda: self.curl)
347 def assertHandler(self, handler_cls):
348 self.failUnless(isinstance(self.rapi.GetLastHandler(), handler_cls))
350 def assertQuery(self, key, value):
351 self.assertEqual(value, self.rapi.GetLastHandler().queryargs.get(key, None))
353 def assertItems(self, items):
354 self.assertEqual(items, self.rapi.GetLastHandler().items)
356 def assertBulk(self):
357 self.assertTrue(self.rapi.GetLastHandler().useBulk())
359 def assertDryRun(self):
360 self.assertTrue(self.rapi.GetLastHandler().dryRun())
362 def assertUseForce(self):
363 self.assertTrue(self.rapi.GetLastHandler().useForce())
365 def testEncodeQuery(self):
382 self.assertEqualValues(self.client._EncodeQuery(query),
386 for i in [[1, 2, 3], {"moo": "boo"}, (1, 2, 3)]:
387 self.assertRaises(ValueError, self.client._EncodeQuery, [("x", i)])
389 def testCurlSettings(self):
390 self.rapi.AddResponse("2")
391 self.assertEqual(2, self.client.GetVersion())
392 self.assertHandler(rlib2.R_version)
394 # Signals should be disabled by default
395 self.assert_(self.curl.getopt(pycurl.NOSIGNAL))
397 # No auth and no proxy
398 self.assertFalse(self.curl.getopt(pycurl.USERPWD))
399 self.assert_(self.curl.getopt(pycurl.PROXY) is None)
401 # Content-type is required for requests
402 headers = self.curl.getopt(pycurl.HTTPHEADER)
403 self.assert_("Content-type: application/json" in headers)
405 def testHttpError(self):
406 self.rapi.AddResponse(None, code=404)
408 self.client.GetJobStatus(15140)
409 except client.GanetiApiError, err:
410 self.assertEqual(err.code, 404)
412 self.fail("Didn't raise exception")
414 def testGetVersion(self):
415 self.rapi.AddResponse("2")
416 self.assertEqual(2, self.client.GetVersion())
417 self.assertHandler(rlib2.R_version)
419 def testGetFeatures(self):
420 for features in [[], ["foo", "bar", "baz"]]:
421 self.rapi.AddResponse(serializer.DumpJson(features))
422 self.assertEqual(features, self.client.GetFeatures())
423 self.assertHandler(rlib2.R_2_features)
425 def testGetFeaturesNotFound(self):
426 self.rapi.AddResponse(None, code=404)
427 self.assertEqual([], self.client.GetFeatures())
429 def testGetOperatingSystems(self):
430 self.rapi.AddResponse("[\"beos\"]")
431 self.assertEqual(["beos"], self.client.GetOperatingSystems())
432 self.assertHandler(rlib2.R_2_os)
434 def testGetClusterTags(self):
435 self.rapi.AddResponse("[\"tag\"]")
436 self.assertEqual(["tag"], self.client.GetClusterTags())
437 self.assertHandler(rlib2.R_2_tags)
439 def testAddClusterTags(self):
440 self.rapi.AddResponse("1234")
441 self.assertEqual(1234,
442 self.client.AddClusterTags(["awesome"], dry_run=True))
443 self.assertHandler(rlib2.R_2_tags)
445 self.assertQuery("tag", ["awesome"])
447 def testDeleteClusterTags(self):
448 self.rapi.AddResponse("5107")
449 self.assertEqual(5107, self.client.DeleteClusterTags(["awesome"],
451 self.assertHandler(rlib2.R_2_tags)
453 self.assertQuery("tag", ["awesome"])
455 def testGetInfo(self):
456 self.rapi.AddResponse("{}")
457 self.assertEqual({}, self.client.GetInfo())
458 self.assertHandler(rlib2.R_2_info)
460 def testGetInstances(self):
461 self.rapi.AddResponse("[]")
462 self.assertEqual([], self.client.GetInstances(bulk=True))
463 self.assertHandler(rlib2.R_2_instances)
466 def testGetInstance(self):
467 self.rapi.AddResponse("[]")
468 self.assertEqual([], self.client.GetInstance("instance"))
469 self.assertHandler(rlib2.R_2_instances_name)
470 self.assertItems(["instance"])
472 def testGetInstanceInfo(self):
473 self.rapi.AddResponse("21291")
474 self.assertEqual(21291, self.client.GetInstanceInfo("inst3"))
475 self.assertHandler(rlib2.R_2_instances_name_info)
476 self.assertItems(["inst3"])
477 self.assertQuery("static", None)
479 self.rapi.AddResponse("3428")
480 self.assertEqual(3428, self.client.GetInstanceInfo("inst31", static=False))
481 self.assertHandler(rlib2.R_2_instances_name_info)
482 self.assertItems(["inst31"])
483 self.assertQuery("static", ["0"])
485 self.rapi.AddResponse("15665")
486 self.assertEqual(15665, self.client.GetInstanceInfo("inst32", static=True))
487 self.assertHandler(rlib2.R_2_instances_name_info)
488 self.assertItems(["inst32"])
489 self.assertQuery("static", ["1"])
491 def testInstancesMultiAlloc(self):
493 constants.JOB_IDS_KEY: ["23423"],
494 opcodes.OpInstanceMultiAlloc.ALLOCATABLE_KEY: ["foobar"],
495 opcodes.OpInstanceMultiAlloc.FAILED_KEY: ["foobar2"],
497 self.rapi.AddResponse(serializer.DumpJson(response))
498 insts = [self.client.InstanceAllocation("create", "foobar",
500 self.client.InstanceAllocation("create", "foobar2",
501 "drbd8", [{"size": 100}], [])]
502 resp = self.client.InstancesMultiAlloc(insts)
503 self.assertEqual(resp, response)
504 self.assertHandler(rlib2.R_2_instances_multi_alloc)
506 def testCreateInstanceOldVersion(self):
507 # The old request format, version 0, is no longer supported
508 self.rapi.AddResponse(None, code=404)
509 self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
510 "create", "inst1.example.com", "plain", [], [])
511 self.assertEqual(self.rapi.CountPending(), 0)
513 def testCreateInstance(self):
514 self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
515 self.rapi.AddResponse("23030")
516 job_id = self.client.CreateInstance("create", "inst1.example.com",
517 "plain", [], [], dry_run=True)
518 self.assertEqual(job_id, 23030)
519 self.assertHandler(rlib2.R_2_instances)
522 data = serializer.LoadJson(self.rapi.GetLastRequestData())
524 for field in ["dry_run", "beparams", "hvparams", "start"]:
525 self.assertFalse(field in data)
527 self.assertEqual(data["name"], "inst1.example.com")
528 self.assertEqual(data["disk_template"], "plain")
530 def testCreateInstance2(self):
531 self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
532 self.rapi.AddResponse("24740")
533 job_id = self.client.CreateInstance("import", "inst2.example.com",
534 "drbd8", [{"size": 100,}],
535 [{}, {"bridge": "br1", }],
536 dry_run=False, start=True,
537 pnode="node1", snode="node9",
539 self.assertEqual(job_id, 24740)
540 self.assertHandler(rlib2.R_2_instances)
542 data = serializer.LoadJson(self.rapi.GetLastRequestData())
543 self.assertEqual(data[rlib2._REQ_DATA_VERSION], 1)
544 self.assertEqual(data["name"], "inst2.example.com")
545 self.assertEqual(data["disk_template"], "drbd8")
546 self.assertEqual(data["start"], True)
547 self.assertEqual(data["ip_check"], False)
548 self.assertEqualValues(data["disks"], [{"size": 100,}])
549 self.assertEqualValues(data["nics"], [{}, {"bridge": "br1", }])
551 def testDeleteInstance(self):
552 self.rapi.AddResponse("1234")
553 self.assertEqual(1234, self.client.DeleteInstance("instance", dry_run=True))
554 self.assertHandler(rlib2.R_2_instances_name)
555 self.assertItems(["instance"])
558 def testGetInstanceTags(self):
559 self.rapi.AddResponse("[]")
560 self.assertEqual([], self.client.GetInstanceTags("fooinstance"))
561 self.assertHandler(rlib2.R_2_instances_name_tags)
562 self.assertItems(["fooinstance"])
564 def testAddInstanceTags(self):
565 self.rapi.AddResponse("1234")
566 self.assertEqual(1234,
567 self.client.AddInstanceTags("fooinstance", ["awesome"], dry_run=True))
568 self.assertHandler(rlib2.R_2_instances_name_tags)
569 self.assertItems(["fooinstance"])
571 self.assertQuery("tag", ["awesome"])
573 def testDeleteInstanceTags(self):
574 self.rapi.AddResponse("25826")
575 self.assertEqual(25826, self.client.DeleteInstanceTags("foo", ["awesome"],
577 self.assertHandler(rlib2.R_2_instances_name_tags)
578 self.assertItems(["foo"])
580 self.assertQuery("tag", ["awesome"])
582 def testRebootInstance(self):
583 self.rapi.AddResponse("6146")
584 job_id = self.client.RebootInstance("i-bar", reboot_type="hard",
585 ignore_secondaries=True, dry_run=True)
586 self.assertEqual(6146, job_id)
587 self.assertHandler(rlib2.R_2_instances_name_reboot)
588 self.assertItems(["i-bar"])
590 self.assertQuery("type", ["hard"])
591 self.assertQuery("ignore_secondaries", ["1"])
593 def testShutdownInstance(self):
594 self.rapi.AddResponse("1487")
595 self.assertEqual(1487, self.client.ShutdownInstance("foo-instance",
597 self.assertHandler(rlib2.R_2_instances_name_shutdown)
598 self.assertItems(["foo-instance"])
601 def testStartupInstance(self):
602 self.rapi.AddResponse("27149")
603 self.assertEqual(27149, self.client.StartupInstance("bar-instance",
605 self.assertHandler(rlib2.R_2_instances_name_startup)
606 self.assertItems(["bar-instance"])
609 def testReinstallInstance(self):
610 self.rapi.AddResponse(serializer.DumpJson([]))
611 self.rapi.AddResponse("19119")
612 self.assertEqual(19119, self.client.ReinstallInstance("baz-instance",
615 self.assertHandler(rlib2.R_2_instances_name_reinstall)
616 self.assertItems(["baz-instance"])
617 self.assertQuery("os", ["DOS"])
618 self.assertQuery("nostartup", ["1"])
619 self.assertEqual(self.rapi.CountPending(), 0)
621 def testReinstallInstanceNew(self):
622 self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_REINSTALL_REQV1]))
623 self.rapi.AddResponse("25689")
624 self.assertEqual(25689, self.client.ReinstallInstance("moo-instance",
627 self.assertHandler(rlib2.R_2_instances_name_reinstall)
628 self.assertItems(["moo-instance"])
629 data = serializer.LoadJson(self.rapi.GetLastRequestData())
630 self.assertEqual(len(data), 2)
631 self.assertEqual(data["os"], "Debian")
632 self.assertEqual(data["start"], False)
633 self.assertEqual(self.rapi.CountPending(), 0)
635 def testReinstallInstanceWithOsparams1(self):
636 self.rapi.AddResponse(serializer.DumpJson([]))
637 self.assertRaises(client.GanetiApiError, self.client.ReinstallInstance,
638 "doo-instance", osparams={"x": "y"})
639 self.assertEqual(self.rapi.CountPending(), 0)
641 def testReinstallInstanceWithOsparams2(self):
646 self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_REINSTALL_REQV1]))
647 self.rapi.AddResponse("1717")
648 self.assertEqual(1717, self.client.ReinstallInstance("zoo-instance",
650 self.assertHandler(rlib2.R_2_instances_name_reinstall)
651 self.assertItems(["zoo-instance"])
652 data = serializer.LoadJson(self.rapi.GetLastRequestData())
653 self.assertEqual(len(data), 2)
654 self.assertEqual(data["osparams"], osparams)
655 self.assertEqual(data["start"], True)
656 self.assertEqual(self.rapi.CountPending(), 0)
658 def testReplaceInstanceDisks(self):
659 self.rapi.AddResponse("999")
660 job_id = self.client.ReplaceInstanceDisks("instance-name",
661 disks=[0, 1], iallocator="hail")
662 self.assertEqual(999, job_id)
663 self.assertHandler(rlib2.R_2_instances_name_replace_disks)
664 self.assertItems(["instance-name"])
665 self.assertQuery("disks", ["0,1"])
666 self.assertQuery("mode", ["replace_auto"])
667 self.assertQuery("iallocator", ["hail"])
669 self.rapi.AddResponse("1000")
670 job_id = self.client.ReplaceInstanceDisks("instance-bar",
671 disks=[1], mode="replace_on_secondary", remote_node="foo-node")
672 self.assertEqual(1000, job_id)
673 self.assertItems(["instance-bar"])
674 self.assertQuery("disks", ["1"])
675 self.assertQuery("remote_node", ["foo-node"])
677 self.rapi.AddResponse("5175")
678 self.assertEqual(5175, self.client.ReplaceInstanceDisks("instance-moo"))
679 self.assertItems(["instance-moo"])
680 self.assertQuery("disks", None)
682 def testPrepareExport(self):
683 self.rapi.AddResponse("8326")
684 self.assertEqual(8326, self.client.PrepareExport("inst1", "local"))
685 self.assertHandler(rlib2.R_2_instances_name_prepare_export)
686 self.assertItems(["inst1"])
687 self.assertQuery("mode", ["local"])
689 def testExportInstance(self):
690 self.rapi.AddResponse("19695")
691 job_id = self.client.ExportInstance("inst2", "local", "nodeX",
693 self.assertEqual(job_id, 19695)
694 self.assertHandler(rlib2.R_2_instances_name_export)
695 self.assertItems(["inst2"])
697 data = serializer.LoadJson(self.rapi.GetLastRequestData())
698 self.assertEqual(data["mode"], "local")
699 self.assertEqual(data["destination"], "nodeX")
700 self.assertEqual(data["shutdown"], True)
702 def testMigrateInstanceDefaults(self):
703 self.rapi.AddResponse("24873")
704 job_id = self.client.MigrateInstance("inst91")
705 self.assertEqual(job_id, 24873)
706 self.assertHandler(rlib2.R_2_instances_name_migrate)
707 self.assertItems(["inst91"])
709 data = serializer.LoadJson(self.rapi.GetLastRequestData())
710 self.assertFalse(data)
712 def testMigrateInstance(self):
713 for mode in constants.HT_MIGRATION_MODES:
714 for cleanup in [False, True]:
715 self.rapi.AddResponse("31910")
716 job_id = self.client.MigrateInstance("inst289", mode=mode,
718 self.assertEqual(job_id, 31910)
719 self.assertHandler(rlib2.R_2_instances_name_migrate)
720 self.assertItems(["inst289"])
722 data = serializer.LoadJson(self.rapi.GetLastRequestData())
723 self.assertEqual(len(data), 2)
724 self.assertEqual(data["mode"], mode)
725 self.assertEqual(data["cleanup"], cleanup)
727 def testFailoverInstanceDefaults(self):
728 self.rapi.AddResponse("7639")
729 job_id = self.client.FailoverInstance("inst13579")
730 self.assertEqual(job_id, 7639)
731 self.assertHandler(rlib2.R_2_instances_name_failover)
732 self.assertItems(["inst13579"])
734 data = serializer.LoadJson(self.rapi.GetLastRequestData())
735 self.assertFalse(data)
737 def testFailoverInstance(self):
738 for iallocator in ["dumb", "hail"]:
739 for ignore_consistency in [False, True]:
740 for target_node in ["node-a", "node2"]:
741 self.rapi.AddResponse("19161")
743 self.client.FailoverInstance("inst251", iallocator=iallocator,
744 ignore_consistency=ignore_consistency,
745 target_node=target_node)
746 self.assertEqual(job_id, 19161)
747 self.assertHandler(rlib2.R_2_instances_name_failover)
748 self.assertItems(["inst251"])
750 data = serializer.LoadJson(self.rapi.GetLastRequestData())
751 self.assertEqual(len(data), 3)
752 self.assertEqual(data["iallocator"], iallocator)
753 self.assertEqual(data["ignore_consistency"], ignore_consistency)
754 self.assertEqual(data["target_node"], target_node)
755 self.assertEqual(self.rapi.CountPending(), 0)
757 def testRenameInstanceDefaults(self):
758 new_name = "newnametha7euqu"
759 self.rapi.AddResponse("8791")
760 job_id = self.client.RenameInstance("inst18821", new_name)
761 self.assertEqual(job_id, 8791)
762 self.assertHandler(rlib2.R_2_instances_name_rename)
763 self.assertItems(["inst18821"])
765 data = serializer.LoadJson(self.rapi.GetLastRequestData())
766 self.assertEqualValues(data, {"new_name": new_name, })
768 def testRenameInstance(self):
769 new_name = "new-name-yiux1iin"
770 for ip_check in [False, True]:
771 for name_check in [False, True]:
772 self.rapi.AddResponse("24776")
773 job_id = self.client.RenameInstance("inst20967", new_name,
775 name_check=name_check)
776 self.assertEqual(job_id, 24776)
777 self.assertHandler(rlib2.R_2_instances_name_rename)
778 self.assertItems(["inst20967"])
780 data = serializer.LoadJson(self.rapi.GetLastRequestData())
781 self.assertEqual(len(data), 3)
782 self.assertEqual(data["new_name"], new_name)
783 self.assertEqual(data["ip_check"], ip_check)
784 self.assertEqual(data["name_check"], name_check)
786 def testGetJobs(self):
787 self.rapi.AddResponse('[ { "id": "123", "uri": "\\/2\\/jobs\\/123" },'
788 ' { "id": "124", "uri": "\\/2\\/jobs\\/124" } ]')
789 self.assertEqual([123, 124], self.client.GetJobs())
790 self.assertHandler(rlib2.R_2_jobs)
792 def testGetJobStatus(self):
793 self.rapi.AddResponse("{\"foo\": \"bar\"}")
794 self.assertEqual({"foo": "bar"}, self.client.GetJobStatus(1234))
795 self.assertHandler(rlib2.R_2_jobs_id)
796 self.assertItems(["1234"])
798 def testWaitForJobChange(self):
799 fields = ["id", "summary"]
801 "job_info": [123, "something"],
805 self.rapi.AddResponse(serializer.DumpJson(expected))
806 result = self.client.WaitForJobChange(123, fields, [], -1)
807 self.assertEqualValues(expected, result)
808 self.assertHandler(rlib2.R_2_jobs_id_wait)
809 self.assertItems(["123"])
811 def testCancelJob(self):
812 self.rapi.AddResponse("[true, \"Job 123 will be canceled\"]")
813 self.assertEqual([True, "Job 123 will be canceled"],
814 self.client.CancelJob(999, dry_run=True))
815 self.assertHandler(rlib2.R_2_jobs_id)
816 self.assertItems(["999"])
819 def testGetNodes(self):
820 self.rapi.AddResponse("[ { \"id\": \"node1\", \"uri\": \"uri1\" },"
821 " { \"id\": \"node2\", \"uri\": \"uri2\" } ]")
822 self.assertEqual(["node1", "node2"], self.client.GetNodes())
823 self.assertHandler(rlib2.R_2_nodes)
825 self.rapi.AddResponse("[ { \"id\": \"node1\", \"uri\": \"uri1\" },"
826 " { \"id\": \"node2\", \"uri\": \"uri2\" } ]")
827 self.assertEqual([{"id": "node1", "uri": "uri1"},
828 {"id": "node2", "uri": "uri2"}],
829 self.client.GetNodes(bulk=True))
830 self.assertHandler(rlib2.R_2_nodes)
833 def testGetNode(self):
834 self.rapi.AddResponse("{}")
835 self.assertEqual({}, self.client.GetNode("node-foo"))
836 self.assertHandler(rlib2.R_2_nodes_name)
837 self.assertItems(["node-foo"])
839 def testEvacuateNode(self):
840 self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_EVAC_RES1]))
841 self.rapi.AddResponse("9876")
842 job_id = self.client.EvacuateNode("node-1", remote_node="node-2")
843 self.assertEqual(9876, job_id)
844 self.assertHandler(rlib2.R_2_nodes_name_evacuate)
845 self.assertItems(["node-1"])
846 self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
847 { "remote_node": "node-2", })
848 self.assertEqual(self.rapi.CountPending(), 0)
850 self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_EVAC_RES1]))
851 self.rapi.AddResponse("8888")
852 job_id = self.client.EvacuateNode("node-3", iallocator="hail", dry_run=True,
853 mode=constants.NODE_EVAC_ALL,
855 self.assertEqual(8888, job_id)
856 self.assertItems(["node-3"])
857 self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()), {
858 "iallocator": "hail",
860 "early_release": True,
864 self.assertRaises(client.GanetiApiError,
865 self.client.EvacuateNode,
866 "node-4", iallocator="hail", remote_node="node-5")
867 self.assertEqual(self.rapi.CountPending(), 0)
869 def testEvacuateNodeOldResponse(self):
870 self.rapi.AddResponse(serializer.DumpJson([]))
871 self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
872 "node-4", accept_old=False)
873 self.assertEqual(self.rapi.CountPending(), 0)
875 for mode in [client.NODE_EVAC_PRI, client.NODE_EVAC_ALL]:
876 self.rapi.AddResponse(serializer.DumpJson([]))
877 self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
878 "node-4", accept_old=True, mode=mode)
879 self.assertEqual(self.rapi.CountPending(), 0)
881 self.rapi.AddResponse(serializer.DumpJson([]))
882 self.rapi.AddResponse(serializer.DumpJson("21533"))
883 result = self.client.EvacuateNode("node-3", iallocator="hail",
884 dry_run=True, accept_old=True,
885 mode=client.NODE_EVAC_SEC,
887 self.assertEqual(result, "21533")
888 self.assertItems(["node-3"])
889 self.assertQuery("iallocator", ["hail"])
890 self.assertQuery("early_release", ["1"])
891 self.assertFalse(self.rapi.GetLastRequestData())
893 self.assertEqual(self.rapi.CountPending(), 0)
895 def testMigrateNode(self):
896 self.rapi.AddResponse(serializer.DumpJson([]))
897 self.rapi.AddResponse("1111")
898 self.assertEqual(1111, self.client.MigrateNode("node-a", dry_run=True))
899 self.assertHandler(rlib2.R_2_nodes_name_migrate)
900 self.assertItems(["node-a"])
901 self.assert_("mode" not in self.rapi.GetLastHandler().queryargs)
903 self.assertFalse(self.rapi.GetLastRequestData())
905 self.rapi.AddResponse(serializer.DumpJson([]))
906 self.rapi.AddResponse("1112")
907 self.assertEqual(1112, self.client.MigrateNode("node-a", dry_run=True,
909 self.assertHandler(rlib2.R_2_nodes_name_migrate)
910 self.assertItems(["node-a"])
911 self.assertQuery("mode", ["live"])
913 self.assertFalse(self.rapi.GetLastRequestData())
915 self.rapi.AddResponse(serializer.DumpJson([]))
916 self.assertRaises(client.GanetiApiError, self.client.MigrateNode,
917 "node-c", target_node="foonode")
918 self.assertEqual(self.rapi.CountPending(), 0)
920 def testMigrateNodeBodyData(self):
921 self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_MIGRATE_REQV1]))
922 self.rapi.AddResponse("27539")
923 self.assertEqual(27539, self.client.MigrateNode("node-a", dry_run=False,
925 self.assertHandler(rlib2.R_2_nodes_name_migrate)
926 self.assertItems(["node-a"])
927 self.assertFalse(self.rapi.GetLastHandler().queryargs)
928 self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
931 self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_MIGRATE_REQV1]))
932 self.rapi.AddResponse("14219")
933 self.assertEqual(14219, self.client.MigrateNode("node-x", dry_run=True,
936 self.assertHandler(rlib2.R_2_nodes_name_migrate)
937 self.assertItems(["node-x"])
939 self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
940 { "target_node": "node9", "iallocator": "ial", })
942 self.assertEqual(self.rapi.CountPending(), 0)
944 def testGetNodeRole(self):
945 self.rapi.AddResponse("\"master\"")
946 self.assertEqual("master", self.client.GetNodeRole("node-a"))
947 self.assertHandler(rlib2.R_2_nodes_name_role)
948 self.assertItems(["node-a"])
950 def testSetNodeRole(self):
951 self.rapi.AddResponse("789")
952 self.assertEqual(789,
953 self.client.SetNodeRole("node-foo", "master-candidate", force=True))
954 self.assertHandler(rlib2.R_2_nodes_name_role)
955 self.assertItems(["node-foo"])
956 self.assertQuery("force", ["1"])
957 self.assertEqual("\"master-candidate\"", self.rapi.GetLastRequestData())
959 def testPowercycleNode(self):
960 self.rapi.AddResponse("23051")
961 self.assertEqual(23051,
962 self.client.PowercycleNode("node5468", force=True))
963 self.assertHandler(rlib2.R_2_nodes_name_powercycle)
964 self.assertItems(["node5468"])
965 self.assertQuery("force", ["1"])
966 self.assertFalse(self.rapi.GetLastRequestData())
967 self.assertEqual(self.rapi.CountPending(), 0)
969 def testModifyNode(self):
970 self.rapi.AddResponse("3783")
971 job_id = self.client.ModifyNode("node16979.example.com", drained=True)
972 self.assertEqual(job_id, 3783)
973 self.assertHandler(rlib2.R_2_nodes_name_modify)
974 self.assertItems(["node16979.example.com"])
975 self.assertEqual(self.rapi.CountPending(), 0)
977 def testGetNodeStorageUnits(self):
978 self.rapi.AddResponse("42")
980 self.client.GetNodeStorageUnits("node-x", "lvm-pv", "fields"))
981 self.assertHandler(rlib2.R_2_nodes_name_storage)
982 self.assertItems(["node-x"])
983 self.assertQuery("storage_type", ["lvm-pv"])
984 self.assertQuery("output_fields", ["fields"])
986 def testModifyNodeStorageUnits(self):
987 self.rapi.AddResponse("14")
989 self.client.ModifyNodeStorageUnits("node-z", "lvm-pv", "hda"))
990 self.assertHandler(rlib2.R_2_nodes_name_storage_modify)
991 self.assertItems(["node-z"])
992 self.assertQuery("storage_type", ["lvm-pv"])
993 self.assertQuery("name", ["hda"])
994 self.assertQuery("allocatable", None)
996 for allocatable, query_allocatable in [(True, "1"), (False, "0")]:
997 self.rapi.AddResponse("7205")
998 job_id = self.client.ModifyNodeStorageUnits("node-z", "lvm-pv", "hda",
999 allocatable=allocatable)
1000 self.assertEqual(7205, job_id)
1001 self.assertHandler(rlib2.R_2_nodes_name_storage_modify)
1002 self.assertItems(["node-z"])
1003 self.assertQuery("storage_type", ["lvm-pv"])
1004 self.assertQuery("name", ["hda"])
1005 self.assertQuery("allocatable", [query_allocatable])
1007 def testRepairNodeStorageUnits(self):
1008 self.rapi.AddResponse("99")
1009 self.assertEqual(99, self.client.RepairNodeStorageUnits("node-z", "lvm-pv",
1011 self.assertHandler(rlib2.R_2_nodes_name_storage_repair)
1012 self.assertItems(["node-z"])
1013 self.assertQuery("storage_type", ["lvm-pv"])
1014 self.assertQuery("name", ["hda"])
1016 def testGetNodeTags(self):
1017 self.rapi.AddResponse("[\"fry\", \"bender\"]")
1018 self.assertEqual(["fry", "bender"], self.client.GetNodeTags("node-k"))
1019 self.assertHandler(rlib2.R_2_nodes_name_tags)
1020 self.assertItems(["node-k"])
1022 def testAddNodeTags(self):
1023 self.rapi.AddResponse("1234")
1024 self.assertEqual(1234,
1025 self.client.AddNodeTags("node-v", ["awesome"], dry_run=True))
1026 self.assertHandler(rlib2.R_2_nodes_name_tags)
1027 self.assertItems(["node-v"])
1029 self.assertQuery("tag", ["awesome"])
1031 def testDeleteNodeTags(self):
1032 self.rapi.AddResponse("16861")
1033 self.assertEqual(16861, self.client.DeleteNodeTags("node-w", ["awesome"],
1035 self.assertHandler(rlib2.R_2_nodes_name_tags)
1036 self.assertItems(["node-w"])
1038 self.assertQuery("tag", ["awesome"])
1040 def testGetGroups(self):
1041 groups = [{"name": "group1",
1042 "uri": "/2/groups/group1",
1045 "uri": "/2/groups/group2",
1048 self.rapi.AddResponse(serializer.DumpJson(groups))
1049 self.assertEqual(["group1", "group2"], self.client.GetGroups())
1050 self.assertHandler(rlib2.R_2_groups)
1052 def testGetGroupsBulk(self):
1053 groups = [{"name": "group1",
1054 "uri": "/2/groups/group1",
1056 "node_list": ["gnt1.test",
1061 "uri": "/2/groups/group2",
1063 "node_list": ["gnt3.test",
1067 self.rapi.AddResponse(serializer.DumpJson(groups))
1069 self.assertEqual(groups, self.client.GetGroups(bulk=True))
1070 self.assertHandler(rlib2.R_2_groups)
1073 def testGetGroup(self):
1074 group = {"ctime": None,
1077 self.rapi.AddResponse(serializer.DumpJson(group))
1078 self.assertEqual({"ctime": None, "name": "default"},
1079 self.client.GetGroup("default"))
1080 self.assertHandler(rlib2.R_2_groups_name)
1081 self.assertItems(["default"])
1083 def testCreateGroup(self):
1084 self.rapi.AddResponse("12345")
1085 job_id = self.client.CreateGroup("newgroup", dry_run=True)
1086 self.assertEqual(job_id, 12345)
1087 self.assertHandler(rlib2.R_2_groups)
1090 def testDeleteGroup(self):
1091 self.rapi.AddResponse("12346")
1092 job_id = self.client.DeleteGroup("newgroup", dry_run=True)
1093 self.assertEqual(job_id, 12346)
1094 self.assertHandler(rlib2.R_2_groups_name)
1097 def testRenameGroup(self):
1098 self.rapi.AddResponse("12347")
1099 job_id = self.client.RenameGroup("oldname", "newname")
1100 self.assertEqual(job_id, 12347)
1101 self.assertHandler(rlib2.R_2_groups_name_rename)
1103 def testModifyGroup(self):
1104 self.rapi.AddResponse("12348")
1105 job_id = self.client.ModifyGroup("mygroup", alloc_policy="foo")
1106 self.assertEqual(job_id, 12348)
1107 self.assertHandler(rlib2.R_2_groups_name_modify)
1109 def testAssignGroupNodes(self):
1110 self.rapi.AddResponse("12349")
1111 job_id = self.client.AssignGroupNodes("mygroup", ["node1", "node2"],
1112 force=True, dry_run=True)
1113 self.assertEqual(job_id, 12349)
1114 self.assertHandler(rlib2.R_2_groups_name_assign_nodes)
1116 self.assertUseForce()
1118 def testGetNetworksBulk(self):
1119 networks = [{"name": "network1",
1120 "uri": "/2/networks/network1",
1121 "network": "192.168.0.0/24",
1123 {"name": "network2",
1124 "uri": "/2/networks/network2",
1125 "network": "192.168.0.0/24",
1128 self.rapi.AddResponse(serializer.DumpJson(networks))
1130 self.assertEqual(networks, self.client.GetNetworks(bulk=True))
1131 self.assertHandler(rlib2.R_2_networks)
1134 def testGetNetwork(self):
1135 network = {"ctime": None,
1138 self.rapi.AddResponse(serializer.DumpJson(network))
1139 self.assertEqual({"ctime": None, "name": "network1"},
1140 self.client.GetNetwork("network1"))
1141 self.assertHandler(rlib2.R_2_networks_name)
1142 self.assertItems(["network1"])
1144 def testCreateNetwork(self):
1145 self.rapi.AddResponse("12345")
1146 job_id = self.client.CreateNetwork("newnetwork", network="192.168.0.0/24",
1148 self.assertEqual(job_id, 12345)
1149 self.assertHandler(rlib2.R_2_networks)
1152 def testModifyNetwork(self):
1153 self.rapi.AddResponse("12346")
1154 job_id = self.client.ModifyNetwork("mynetwork", gateway="192.168.0.10",
1156 self.assertEqual(job_id, 12346)
1157 self.assertHandler(rlib2.R_2_networks_name_modify)
1159 def testDeleteNetwork(self):
1160 self.rapi.AddResponse("12347")
1161 job_id = self.client.DeleteNetwork("newnetwork", dry_run=True)
1162 self.assertEqual(job_id, 12347)
1163 self.assertHandler(rlib2.R_2_networks_name)
1166 def testConnectNetwork(self):
1167 self.rapi.AddResponse("12348")
1168 job_id = self.client.ConnectNetwork("mynetwork", "default",
1169 "bridged", "br0", dry_run=True)
1170 self.assertEqual(job_id, 12348)
1171 self.assertHandler(rlib2.R_2_networks_name_connect)
1174 def testDisconnectNetwork(self):
1175 self.rapi.AddResponse("12349")
1176 job_id = self.client.DisconnectNetwork("mynetwork", "default", dry_run=True)
1177 self.assertEqual(job_id, 12349)
1178 self.assertHandler(rlib2.R_2_networks_name_disconnect)
1181 def testGetNetworkTags(self):
1182 self.rapi.AddResponse("[]")
1183 self.assertEqual([], self.client.GetNetworkTags("fooNetwork"))
1184 self.assertHandler(rlib2.R_2_networks_name_tags)
1185 self.assertItems(["fooNetwork"])
1187 def testAddNetworkTags(self):
1188 self.rapi.AddResponse("1234")
1189 self.assertEqual(1234,
1190 self.client.AddNetworkTags("fooNetwork", ["awesome"], dry_run=True))
1191 self.assertHandler(rlib2.R_2_networks_name_tags)
1192 self.assertItems(["fooNetwork"])
1194 self.assertQuery("tag", ["awesome"])
1196 def testDeleteNetworkTags(self):
1197 self.rapi.AddResponse("25826")
1198 self.assertEqual(25826, self.client.DeleteNetworkTags("foo", ["awesome"],
1200 self.assertHandler(rlib2.R_2_networks_name_tags)
1201 self.assertItems(["foo"])
1203 self.assertQuery("tag", ["awesome"])
1205 def testModifyInstance(self):
1206 self.rapi.AddResponse("23681")
1207 job_id = self.client.ModifyInstance("inst7210", os_name="linux")
1208 self.assertEqual(job_id, 23681)
1209 self.assertItems(["inst7210"])
1210 self.assertHandler(rlib2.R_2_instances_name_modify)
1211 self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
1212 { "os_name": "linux", })
1214 def testModifyCluster(self):
1215 for mnh in [None, False, True]:
1216 self.rapi.AddResponse("14470")
1217 self.assertEqual(14470,
1218 self.client.ModifyCluster(maintain_node_health=mnh))
1219 self.assertHandler(rlib2.R_2_cluster_modify)
1220 self.assertItems([])
1221 data = serializer.LoadJson(self.rapi.GetLastRequestData())
1222 self.assertEqual(len(data), 1)
1223 self.assertEqual(data["maintain_node_health"], mnh)
1224 self.assertEqual(self.rapi.CountPending(), 0)
1226 def testRedistributeConfig(self):
1227 self.rapi.AddResponse("3364")
1228 job_id = self.client.RedistributeConfig()
1229 self.assertEqual(job_id, 3364)
1230 self.assertItems([])
1231 self.assertHandler(rlib2.R_2_redist_config)
1233 def testActivateInstanceDisks(self):
1234 self.rapi.AddResponse("23547")
1235 job_id = self.client.ActivateInstanceDisks("inst28204")
1236 self.assertEqual(job_id, 23547)
1237 self.assertItems(["inst28204"])
1238 self.assertHandler(rlib2.R_2_instances_name_activate_disks)
1239 self.assertFalse(self.rapi.GetLastHandler().queryargs)
1241 def testActivateInstanceDisksIgnoreSize(self):
1242 self.rapi.AddResponse("11044")
1243 job_id = self.client.ActivateInstanceDisks("inst28204", ignore_size=True)
1244 self.assertEqual(job_id, 11044)
1245 self.assertItems(["inst28204"])
1246 self.assertHandler(rlib2.R_2_instances_name_activate_disks)
1247 self.assertQuery("ignore_size", ["1"])
1249 def testDeactivateInstanceDisks(self):
1250 self.rapi.AddResponse("14591")
1251 job_id = self.client.DeactivateInstanceDisks("inst28234")
1252 self.assertEqual(job_id, 14591)
1253 self.assertItems(["inst28234"])
1254 self.assertHandler(rlib2.R_2_instances_name_deactivate_disks)
1255 self.assertFalse(self.rapi.GetLastHandler().queryargs)
1257 def testRecreateInstanceDisks(self):
1258 self.rapi.AddResponse("13553")
1259 job_id = self.client.RecreateInstanceDisks("inst23153")
1260 self.assertEqual(job_id, 13553)
1261 self.assertItems(["inst23153"])
1262 self.assertHandler(rlib2.R_2_instances_name_recreate_disks)
1263 self.assertFalse(self.rapi.GetLastHandler().queryargs)
1265 def testGetInstanceConsole(self):
1266 self.rapi.AddResponse("26876")
1267 job_id = self.client.GetInstanceConsole("inst21491")
1268 self.assertEqual(job_id, 26876)
1269 self.assertItems(["inst21491"])
1270 self.assertHandler(rlib2.R_2_instances_name_console)
1271 self.assertFalse(self.rapi.GetLastHandler().queryargs)
1272 self.assertFalse(self.rapi.GetLastRequestData())
1274 def testGrowInstanceDisk(self):
1275 for idx, wait_for_sync in enumerate([None, False, True]):
1276 amount = 128 + (512 * idx)
1277 self.assertEqual(self.rapi.CountPending(), 0)
1278 self.rapi.AddResponse("30783")
1279 self.assertEqual(30783,
1280 self.client.GrowInstanceDisk("eze8ch", idx, amount,
1281 wait_for_sync=wait_for_sync))
1282 self.assertHandler(rlib2.R_2_instances_name_disk_grow)
1283 self.assertItems(["eze8ch", str(idx)])
1284 data = serializer.LoadJson(self.rapi.GetLastRequestData())
1285 if wait_for_sync is None:
1286 self.assertEqual(len(data), 1)
1287 self.assert_("wait_for_sync" not in data)
1289 self.assertEqual(len(data), 2)
1290 self.assertEqual(data["wait_for_sync"], wait_for_sync)
1291 self.assertEqual(data["amount"], amount)
1292 self.assertEqual(self.rapi.CountPending(), 0)
1294 def testGetGroupTags(self):
1295 self.rapi.AddResponse("[]")
1296 self.assertEqual([], self.client.GetGroupTags("fooGroup"))
1297 self.assertHandler(rlib2.R_2_groups_name_tags)
1298 self.assertItems(["fooGroup"])
1300 def testAddGroupTags(self):
1301 self.rapi.AddResponse("1234")
1302 self.assertEqual(1234,
1303 self.client.AddGroupTags("fooGroup", ["awesome"], dry_run=True))
1304 self.assertHandler(rlib2.R_2_groups_name_tags)
1305 self.assertItems(["fooGroup"])
1307 self.assertQuery("tag", ["awesome"])
1309 def testDeleteGroupTags(self):
1310 self.rapi.AddResponse("25826")
1311 self.assertEqual(25826, self.client.DeleteGroupTags("foo", ["awesome"],
1313 self.assertHandler(rlib2.R_2_groups_name_tags)
1314 self.assertItems(["foo"])
1316 self.assertQuery("tag", ["awesome"])
1318 def testQuery(self):
1319 for idx, what in enumerate(constants.QR_VIA_RAPI):
1320 for idx2, qfilter in enumerate([None, ["?", "name"]]):
1321 job_id = 11010 + (idx << 4) + (idx2 << 16)
1322 fields = sorted(query.ALL_FIELDS[what].keys())[:10]
1324 self.rapi.AddResponse(str(job_id))
1325 self.assertEqual(self.client.Query(what, fields, qfilter=qfilter),
1327 self.assertItems([what])
1328 self.assertHandler(rlib2.R_2_query)
1329 self.assertFalse(self.rapi.GetLastHandler().queryargs)
1330 data = serializer.LoadJson(self.rapi.GetLastRequestData())
1331 self.assertEqual(data["fields"], fields)
1333 self.assertTrue("qfilter" not in data)
1335 self.assertEqual(data["qfilter"], qfilter)
1336 self.assertEqual(self.rapi.CountPending(), 0)
1338 def testQueryFields(self):
1339 exp_result = objects.QueryFieldsResponse(fields=[
1340 objects.QueryFieldDefinition(name="pnode", title="PNode",
1341 kind=constants.QFT_NUMBER),
1342 objects.QueryFieldDefinition(name="other", title="Other",
1343 kind=constants.QFT_BOOL),
1346 for what in constants.QR_VIA_RAPI:
1347 for fields in [None, ["name", "_unknown_"], ["&", "?|"]]:
1348 self.rapi.AddResponse(serializer.DumpJson(exp_result.ToDict()))
1349 result = self.client.QueryFields(what, fields=fields)
1350 self.assertItems([what])
1351 self.assertHandler(rlib2.R_2_query_fields)
1352 self.assertFalse(self.rapi.GetLastRequestData())
1354 queryargs = self.rapi.GetLastHandler().queryargs
1356 self.assertFalse(queryargs)
1358 self.assertEqual(queryargs, {
1359 "fields": [",".join(fields)],
1362 self.assertEqual(objects.QueryFieldsResponse.FromDict(result).ToDict(),
1363 exp_result.ToDict())
1365 self.assertEqual(self.rapi.CountPending(), 0)
1367 def testWaitForJobCompletionNoChange(self):
1368 resp = serializer.DumpJson({
1369 "status": constants.JOB_STATUS_WAITING,
1372 for retries in [1, 5, 25]:
1373 for _ in range(retries):
1374 self.rapi.AddResponse(resp)
1376 self.assertFalse(self.client.WaitForJobCompletion(22789, period=None,
1378 self.assertHandler(rlib2.R_2_jobs_id)
1379 self.assertItems(["22789"])
1381 self.assertEqual(self.rapi.CountPending(), 0)
1383 def testWaitForJobCompletionAlreadyFinished(self):
1384 self.rapi.AddResponse(serializer.DumpJson({
1385 "status": constants.JOB_STATUS_SUCCESS,
1388 self.assertTrue(self.client.WaitForJobCompletion(22793, period=None,
1390 self.assertHandler(rlib2.R_2_jobs_id)
1391 self.assertItems(["22793"])
1393 self.assertEqual(self.rapi.CountPending(), 0)
1395 def testWaitForJobCompletionEmptyResponse(self):
1396 self.rapi.AddResponse("{}")
1397 self.assertFalse(self.client.WaitForJobCompletion(22793, period=None,
1399 self.assertHandler(rlib2.R_2_jobs_id)
1400 self.assertItems(["22793"])
1402 self.assertEqual(self.rapi.CountPending(), 0)
1404 def testWaitForJobCompletionOutOfRetries(self):
1405 for retries in [3, 10, 21]:
1406 for _ in range(retries):
1407 self.rapi.AddResponse(serializer.DumpJson({
1408 "status": constants.JOB_STATUS_RUNNING,
1411 self.assertFalse(self.client.WaitForJobCompletion(30948, period=None,
1412 retries=retries - 1))
1413 self.assertHandler(rlib2.R_2_jobs_id)
1414 self.assertItems(["30948"])
1416 self.assertEqual(self.rapi.CountPending(), 1)
1417 self.rapi.ResetResponses()
1419 def testWaitForJobCompletionSuccessAndFailure(self):
1420 for retries in [1, 4, 13]:
1421 for (success, end_status) in [(False, constants.JOB_STATUS_ERROR),
1422 (True, constants.JOB_STATUS_SUCCESS)]:
1423 for _ in range(retries):
1424 self.rapi.AddResponse(serializer.DumpJson({
1425 "status": constants.JOB_STATUS_RUNNING,
1428 self.rapi.AddResponse(serializer.DumpJson({
1429 "status": end_status,
1432 result = self.client.WaitForJobCompletion(3187, period=None,
1433 retries=retries + 1)
1434 self.assertEqual(result, success)
1435 self.assertHandler(rlib2.R_2_jobs_id)
1436 self.assertItems(["3187"])
1438 self.assertEqual(self.rapi.CountPending(), 0)
1441 class RapiTestRunner(unittest.TextTestRunner):
1442 def run(self, *args):
1443 global _used_handlers
1444 assert _used_handlers is None
1446 _used_handlers = set()
1449 result = unittest.TextTestRunner.run(self, *args)
1451 diff = (set(connector.CONNECTOR.values()) - _used_handlers -
1454 raise AssertionError("The following RAPI resources were not used by the"
1455 " RAPI client: %r" % utils.CommaJoin(diff))
1457 # Reset global variable
1458 _used_handlers = None
1463 if __name__ == "__main__":
1464 client.UsesRapiClient(testutils.GanetiTestProgram)(testRunner=RapiTestRunner)