Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.rapi.client_unittest.py @ 48436b97

History | View | Annotate | Download (22.9 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2010 Google Inc.
5
#
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.
10
#
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.
15
#
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
19
# 02110-1301, USA.
20

    
21

    
22
"""Script for unittesting the RAPI client module"""
23

    
24

    
25
import re
26
import unittest
27
import warnings
28

    
29
from ganeti import constants
30
from ganeti import http
31
from ganeti import serializer
32

    
33
from ganeti.rapi import connector
34
from ganeti.rapi import rlib2
35
from ganeti.rapi import client
36

    
37
import testutils
38

    
39

    
40
_URI_RE = re.compile(r"https://(?P<host>.*):(?P<port>\d+)(?P<path>/.*)")
41

    
42

    
43
def _GetPathFromUri(uri):
44
  """Gets the path and query from a URI.
45

46
  """
47
  match = _URI_RE.match(uri)
48
  if match:
49
    return match.groupdict()["path"]
50
  else:
51
    return None
52

    
53

    
54
class HttpResponseMock:
55
  """Dumb mock of httplib.HTTPResponse.
56

57
  """
58

    
59
  def __init__(self, code, data):
60
    self.code = code
61
    self._data = data
62

    
63
  def read(self):
64
    return self._data
65

    
66

    
67
class OpenerDirectorMock:
68
  """Mock for urllib.OpenerDirector.
69

70
  """
71

    
72
  def __init__(self, rapi):
73
    self._rapi = rapi
74
    self.last_request = None
75

    
76
  def open(self, req):
77
    self.last_request = req
78

    
79
    path = _GetPathFromUri(req.get_full_url())
80
    code, resp_body = self._rapi.FetchResponse(path, req.get_method())
81
    return HttpResponseMock(code, resp_body)
82

    
83

    
84
class RapiMock(object):
85
  def __init__(self):
86
    self._mapper = connector.Mapper()
87
    self._responses = []
88
    self._last_handler = None
89

    
90
  def AddResponse(self, response, code=200):
91
    self._responses.insert(0, (code, response))
92

    
93
  def CountPending(self):
94
    return len(self._responses)
95

    
96
  def GetLastHandler(self):
97
    return self._last_handler
98

    
99
  def FetchResponse(self, path, method):
100
    try:
101
      HandlerClass, items, args = self._mapper.getController(path)
102
      self._last_handler = HandlerClass(items, args, None)
103
      if not hasattr(self._last_handler, method.upper()):
104
        raise http.HttpNotImplemented(message="Method not implemented")
105

    
106
    except http.HttpException, ex:
107
      code = ex.code
108
      response = ex.message
109
    else:
110
      if not self._responses:
111
        raise Exception("No responses")
112

    
113
      (code, response) = self._responses.pop()
114

    
115
    return code, response
116

    
117

    
118
class TestConstants(unittest.TestCase):
119
  def test(self):
120
    self.assertEqual(client.GANETI_RAPI_PORT, constants.DEFAULT_RAPI_PORT)
121
    self.assertEqual(client.GANETI_RAPI_VERSION, constants.RAPI_VERSION)
122
    self.assertEqual(client._REQ_DATA_VERSION_FIELD, rlib2._REQ_DATA_VERSION)
123
    self.assertEqual(client._INST_CREATE_REQV1, rlib2._INST_CREATE_REQV1)
124
    self.assertEqual(client._INST_NIC_PARAMS, constants.INIC_PARAMS)
125

    
126

    
127
class RapiMockTest(unittest.TestCase):
128
  def test(self):
129
    rapi = RapiMock()
130
    path = "/version"
131
    self.assertEqual((404, None), rapi.FetchResponse("/foo", "GET"))
132
    self.assertEqual((501, "Method not implemented"),
133
                     rapi.FetchResponse("/version", "POST"))
134
    rapi.AddResponse("2")
135
    code, response = rapi.FetchResponse("/version", "GET")
136
    self.assertEqual(200, code)
137
    self.assertEqual("2", response)
138
    self.failUnless(isinstance(rapi.GetLastHandler(), rlib2.R_version))
139

    
140

    
141
class GanetiRapiClientTests(testutils.GanetiTestCase):
142
  def setUp(self):
143
    testutils.GanetiTestCase.setUp(self)
144

    
145
    self.rapi = RapiMock()
146
    self.http = OpenerDirectorMock(self.rapi)
147
    self.client = client.GanetiRapiClient('master.foo.com')
148
    self.client._http = self.http
149
    # Hard-code the version for easier testing.
150
    self.client._version = 2
151

    
152
  def assertHandler(self, handler_cls):
153
    self.failUnless(isinstance(self.rapi.GetLastHandler(), handler_cls))
154

    
155
  def assertQuery(self, key, value):
156
    self.assertEqual(value, self.rapi.GetLastHandler().queryargs.get(key, None))
157

    
158
  def assertItems(self, items):
159
    self.assertEqual(items, self.rapi.GetLastHandler().items)
160

    
161
  def assertBulk(self):
162
    self.assertTrue(self.rapi.GetLastHandler().useBulk())
163

    
164
  def assertDryRun(self):
165
    self.assertTrue(self.rapi.GetLastHandler().dryRun())
166

    
167
  def testEncodeQuery(self):
168
    query = [
169
      ("a", None),
170
      ("b", 1),
171
      ("c", 2),
172
      ("d", "Foo"),
173
      ("e", True),
174
      ]
175

    
176
    expected = [
177
      ("a", ""),
178
      ("b", 1),
179
      ("c", 2),
180
      ("d", "Foo"),
181
      ("e", 1),
182
      ]
183

    
184
    self.assertEqualValues(self.client._EncodeQuery(query),
185
                           expected)
186

    
187
    # invalid types
188
    for i in [[1, 2, 3], {"moo": "boo"}, (1, 2, 3)]:
189
      self.assertRaises(ValueError, self.client._EncodeQuery, [("x", i)])
190

    
191
  def testHttpError(self):
192
    self.rapi.AddResponse(None, code=404)
193
    try:
194
      self.client.GetJobStatus(15140)
195
    except client.GanetiApiError, err:
196
      self.assertEqual(err.code, 404)
197
    else:
198
      self.fail("Didn't raise exception")
199

    
200
  def testGetVersion(self):
201
    self.client._version = None
202
    self.rapi.AddResponse("2")
203
    self.assertEqual(2, self.client.GetVersion())
204
    self.assertHandler(rlib2.R_version)
205

    
206
  def testGetFeatures(self):
207
    for features in [[], ["foo", "bar", "baz"]]:
208
      self.rapi.AddResponse(serializer.DumpJson(features))
209
      self.assertEqual(features, self.client.GetFeatures())
210
      self.assertHandler(rlib2.R_2_features)
211

    
212
  def testGetFeaturesNotFound(self):
213
    self.rapi.AddResponse(None, code=404)
214
    self.assertEqual([], self.client.GetFeatures())
215

    
216
  def testGetOperatingSystems(self):
217
    self.rapi.AddResponse("[\"beos\"]")
218
    self.assertEqual(["beos"], self.client.GetOperatingSystems())
219
    self.assertHandler(rlib2.R_2_os)
220

    
221
  def testGetClusterTags(self):
222
    self.rapi.AddResponse("[\"tag\"]")
223
    self.assertEqual(["tag"], self.client.GetClusterTags())
224
    self.assertHandler(rlib2.R_2_tags)
225

    
226
  def testAddClusterTags(self):
227
    self.rapi.AddResponse("1234")
228
    self.assertEqual(1234,
229
        self.client.AddClusterTags(["awesome"], dry_run=True))
230
    self.assertHandler(rlib2.R_2_tags)
231
    self.assertDryRun()
232
    self.assertQuery("tag", ["awesome"])
233

    
234
  def testDeleteClusterTags(self):
235
    self.rapi.AddResponse("5107")
236
    self.assertEqual(5107, self.client.DeleteClusterTags(["awesome"],
237
                                                         dry_run=True))
238
    self.assertHandler(rlib2.R_2_tags)
239
    self.assertDryRun()
240
    self.assertQuery("tag", ["awesome"])
241

    
242
  def testGetInfo(self):
243
    self.rapi.AddResponse("{}")
244
    self.assertEqual({}, self.client.GetInfo())
245
    self.assertHandler(rlib2.R_2_info)
246

    
247
  def testGetInstances(self):
248
    self.rapi.AddResponse("[]")
249
    self.assertEqual([], self.client.GetInstances(bulk=True))
250
    self.assertHandler(rlib2.R_2_instances)
251
    self.assertBulk()
252

    
253
  def testGetInstance(self):
254
    self.rapi.AddResponse("[]")
255
    self.assertEqual([], self.client.GetInstance("instance"))
256
    self.assertHandler(rlib2.R_2_instances_name)
257
    self.assertItems(["instance"])
258

    
259
  def testGetInstanceInfo(self):
260
    self.rapi.AddResponse("21291")
261
    self.assertEqual(21291, self.client.GetInstanceInfo("inst3"))
262
    self.assertHandler(rlib2.R_2_instances_name_info)
263
    self.assertItems(["inst3"])
264
    self.assertQuery("static", None)
265

    
266
    self.rapi.AddResponse("3428")
267
    self.assertEqual(3428, self.client.GetInstanceInfo("inst31", static=False))
268
    self.assertHandler(rlib2.R_2_instances_name_info)
269
    self.assertItems(["inst31"])
270
    self.assertQuery("static", ["0"])
271

    
272
    self.rapi.AddResponse("15665")
273
    self.assertEqual(15665, self.client.GetInstanceInfo("inst32", static=True))
274
    self.assertHandler(rlib2.R_2_instances_name_info)
275
    self.assertItems(["inst32"])
276
    self.assertQuery("static", ["1"])
277

    
278
  def testCreateInstanceOldVersion(self):
279
    # No NICs
280
    self.rapi.AddResponse(None, code=404)
281
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
282
                      "create", "inst1.example.com", "plain", [], [])
283
    self.assertEqual(self.rapi.CountPending(), 0)
284

    
285
    # More than one NIC
286
    self.rapi.AddResponse(None, code=404)
287
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
288
                      "create", "inst1.example.com", "plain", [],
289
                      [{}, {}, {}])
290
    self.assertEqual(self.rapi.CountPending(), 0)
291

    
292
    # Unsupported NIC fields
293
    self.rapi.AddResponse(None, code=404)
294
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
295
                      "create", "inst1.example.com", "plain", [],
296
                      [{"x": True, "y": False}])
297
    self.assertEqual(self.rapi.CountPending(), 0)
298

    
299
    # Unsupported disk fields
300
    self.rapi.AddResponse(None, code=404)
301
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
302
                      "create", "inst1.example.com", "plain",
303
                      [{}, {"moo": "foo",}], [{}])
304
    self.assertEqual(self.rapi.CountPending(), 0)
305

    
306
    # Unsupported fields
307
    self.rapi.AddResponse(None, code=404)
308
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
309
                      "create", "inst1.example.com", "plain", [], [{}],
310
                      hello_world=123)
311
    self.assertEqual(self.rapi.CountPending(), 0)
312

    
313
    self.rapi.AddResponse(None, code=404)
314
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
315
                      "create", "inst1.example.com", "plain", [], [{}],
316
                      memory=128)
317
    self.assertEqual(self.rapi.CountPending(), 0)
318

    
319
    # Normal creation
320
    testnics = [
321
      [{}],
322
      [{ "mac": constants.VALUE_AUTO, }],
323
      [{ "ip": "192.0.2.99", "mode": constants.NIC_MODE_ROUTED, }],
324
      ]
325

    
326
    testdisks = [
327
      [],
328
      [{ "size": 128, }],
329
      [{ "size": 321, }, { "size": 4096, }],
330
      ]
331

    
332
    for idx, nics in enumerate(testnics):
333
      for disks in testdisks:
334
        beparams = {
335
          constants.BE_MEMORY: 512,
336
          constants.BE_AUTO_BALANCE: False,
337
          }
338
        hvparams = {
339
          constants.HV_MIGRATION_PORT: 9876,
340
          constants.HV_VNC_TLS: True,
341
          }
342

    
343
        self.rapi.AddResponse(None, code=404)
344
        self.rapi.AddResponse(serializer.DumpJson(3122617 + idx))
345
        job_id = self.client.CreateInstance("create", "inst1.example.com",
346
                                            "plain", disks, nics,
347
                                            pnode="node99", dry_run=True,
348
                                            hvparams=hvparams,
349
                                            beparams=beparams)
350
        self.assertEqual(job_id, 3122617 + idx)
351
        self.assertHandler(rlib2.R_2_instances)
352
        self.assertDryRun()
353
        self.assertEqual(self.rapi.CountPending(), 0)
354

    
355
        data = serializer.LoadJson(self.http.last_request.data)
356
        self.assertEqual(data["name"], "inst1.example.com")
357
        self.assertEqual(data["disk_template"], "plain")
358
        self.assertEqual(data["pnode"], "node99")
359
        self.assertEqual(data[constants.BE_MEMORY], 512)
360
        self.assertEqual(data[constants.BE_AUTO_BALANCE], False)
361
        self.assertEqual(data[constants.HV_MIGRATION_PORT], 9876)
362
        self.assertEqual(data[constants.HV_VNC_TLS], True)
363
        self.assertEqual(data["disks"], [disk["size"] for disk in disks])
364

    
365
  def testCreateInstance(self):
366
    self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
367
    self.rapi.AddResponse("23030")
368
    job_id = self.client.CreateInstance("create", "inst1.example.com",
369
                                        "plain", [], [], dry_run=True)
370
    self.assertEqual(job_id, 23030)
371
    self.assertHandler(rlib2.R_2_instances)
372
    self.assertDryRun()
373

    
374
    data = serializer.LoadJson(self.http.last_request.data)
375

    
376
    for field in ["dry_run", "beparams", "hvparams", "start"]:
377
      self.assertFalse(field in data)
378

    
379
    self.assertEqual(data["name"], "inst1.example.com")
380
    self.assertEqual(data["disk_template"], "plain")
381

    
382
  def testCreateInstance2(self):
383
    self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
384
    self.rapi.AddResponse("24740")
385
    job_id = self.client.CreateInstance("import", "inst2.example.com",
386
                                        "drbd8", [{"size": 100,}],
387
                                        [{}, {"bridge": "br1", }],
388
                                        dry_run=False, start=True,
389
                                        pnode="node1", snode="node9",
390
                                        ip_check=False)
391
    self.assertEqual(job_id, 24740)
392
    self.assertHandler(rlib2.R_2_instances)
393

    
394
    data = serializer.LoadJson(self.http.last_request.data)
395
    self.assertEqual(data[rlib2._REQ_DATA_VERSION], 1)
396
    self.assertEqual(data["name"], "inst2.example.com")
397
    self.assertEqual(data["disk_template"], "drbd8")
398
    self.assertEqual(data["start"], True)
399
    self.assertEqual(data["ip_check"], False)
400
    self.assertEqualValues(data["disks"], [{"size": 100,}])
401
    self.assertEqualValues(data["nics"], [{}, {"bridge": "br1", }])
402

    
403
  def testDeleteInstance(self):
404
    self.rapi.AddResponse("1234")
405
    self.assertEqual(1234, self.client.DeleteInstance("instance", dry_run=True))
406
    self.assertHandler(rlib2.R_2_instances_name)
407
    self.assertItems(["instance"])
408
    self.assertDryRun()
409

    
410
  def testGetInstanceTags(self):
411
    self.rapi.AddResponse("[]")
412
    self.assertEqual([], self.client.GetInstanceTags("fooinstance"))
413
    self.assertHandler(rlib2.R_2_instances_name_tags)
414
    self.assertItems(["fooinstance"])
415

    
416
  def testAddInstanceTags(self):
417
    self.rapi.AddResponse("1234")
418
    self.assertEqual(1234,
419
        self.client.AddInstanceTags("fooinstance", ["awesome"], dry_run=True))
420
    self.assertHandler(rlib2.R_2_instances_name_tags)
421
    self.assertItems(["fooinstance"])
422
    self.assertDryRun()
423
    self.assertQuery("tag", ["awesome"])
424

    
425
  def testDeleteInstanceTags(self):
426
    self.rapi.AddResponse("25826")
427
    self.assertEqual(25826, self.client.DeleteInstanceTags("foo", ["awesome"],
428
                                                           dry_run=True))
429
    self.assertHandler(rlib2.R_2_instances_name_tags)
430
    self.assertItems(["foo"])
431
    self.assertDryRun()
432
    self.assertQuery("tag", ["awesome"])
433

    
434
  def testRebootInstance(self):
435
    self.rapi.AddResponse("6146")
436
    job_id = self.client.RebootInstance("i-bar", reboot_type="hard",
437
                                        ignore_secondaries=True, dry_run=True)
438
    self.assertEqual(6146, job_id)
439
    self.assertHandler(rlib2.R_2_instances_name_reboot)
440
    self.assertItems(["i-bar"])
441
    self.assertDryRun()
442
    self.assertQuery("type", ["hard"])
443
    self.assertQuery("ignore_secondaries", ["1"])
444

    
445
  def testShutdownInstance(self):
446
    self.rapi.AddResponse("1487")
447
    self.assertEqual(1487, self.client.ShutdownInstance("foo-instance",
448
                                                        dry_run=True))
449
    self.assertHandler(rlib2.R_2_instances_name_shutdown)
450
    self.assertItems(["foo-instance"])
451
    self.assertDryRun()
452

    
453
  def testStartupInstance(self):
454
    self.rapi.AddResponse("27149")
455
    self.assertEqual(27149, self.client.StartupInstance("bar-instance",
456
                                                        dry_run=True))
457
    self.assertHandler(rlib2.R_2_instances_name_startup)
458
    self.assertItems(["bar-instance"])
459
    self.assertDryRun()
460

    
461
  def testReinstallInstance(self):
462
    self.rapi.AddResponse("19119")
463
    self.assertEqual(19119, self.client.ReinstallInstance("baz-instance", "DOS",
464
                                                          no_startup=True))
465
    self.assertHandler(rlib2.R_2_instances_name_reinstall)
466
    self.assertItems(["baz-instance"])
467
    self.assertQuery("os", ["DOS"])
468
    self.assertQuery("nostartup", ["1"])
469

    
470
  def testReplaceInstanceDisks(self):
471
    self.rapi.AddResponse("999")
472
    job_id = self.client.ReplaceInstanceDisks("instance-name",
473
        disks=[0, 1], dry_run=True, iallocator="hail")
474
    self.assertEqual(999, job_id)
475
    self.assertHandler(rlib2.R_2_instances_name_replace_disks)
476
    self.assertItems(["instance-name"])
477
    self.assertQuery("disks", ["0,1"])
478
    self.assertQuery("mode", ["replace_auto"])
479
    self.assertQuery("iallocator", ["hail"])
480
    self.assertDryRun()
481

    
482
    self.rapi.AddResponse("1000")
483
    job_id = self.client.ReplaceInstanceDisks("instance-bar",
484
        disks=[1], mode="replace_on_secondary", remote_node="foo-node",
485
        dry_run=True)
486
    self.assertEqual(1000, job_id)
487
    self.assertItems(["instance-bar"])
488
    self.assertQuery("disks", ["1"])
489
    self.assertQuery("remote_node", ["foo-node"])
490
    self.assertDryRun()
491

    
492
    self.rapi.AddResponse("5175")
493
    self.assertEqual(5175, self.client.ReplaceInstanceDisks("instance-moo"))
494
    self.assertItems(["instance-moo"])
495
    self.assertQuery("disks", None)
496

    
497
  def testGetJobs(self):
498
    self.rapi.AddResponse('[ { "id": "123", "uri": "\\/2\\/jobs\\/123" },'
499
                          '  { "id": "124", "uri": "\\/2\\/jobs\\/124" } ]')
500
    self.assertEqual([123, 124], self.client.GetJobs())
501
    self.assertHandler(rlib2.R_2_jobs)
502

    
503
  def testGetJobStatus(self):
504
    self.rapi.AddResponse("{\"foo\": \"bar\"}")
505
    self.assertEqual({"foo": "bar"}, self.client.GetJobStatus(1234))
506
    self.assertHandler(rlib2.R_2_jobs_id)
507
    self.assertItems(["1234"])
508

    
509
  def testWaitForJobChange(self):
510
    fields = ["id", "summary"]
511
    expected = {
512
      "job_info": [123, "something"],
513
      "log_entries": [],
514
      }
515

    
516
    self.rapi.AddResponse(serializer.DumpJson(expected))
517
    result = self.client.WaitForJobChange(123, fields, [], -1)
518
    self.assertEqualValues(expected, result)
519
    self.assertHandler(rlib2.R_2_jobs_id_wait)
520
    self.assertItems(["123"])
521

    
522
  def testCancelJob(self):
523
    self.rapi.AddResponse("[true, \"Job 123 will be canceled\"]")
524
    self.assertEqual([True, "Job 123 will be canceled"],
525
                     self.client.CancelJob(999, dry_run=True))
526
    self.assertHandler(rlib2.R_2_jobs_id)
527
    self.assertItems(["999"])
528
    self.assertDryRun()
529

    
530
  def testGetNodes(self):
531
    self.rapi.AddResponse("[ { \"id\": \"node1\", \"uri\": \"uri1\" },"
532
                          " { \"id\": \"node2\", \"uri\": \"uri2\" } ]")
533
    self.assertEqual(["node1", "node2"], self.client.GetNodes())
534
    self.assertHandler(rlib2.R_2_nodes)
535

    
536
    self.rapi.AddResponse("[ { \"id\": \"node1\", \"uri\": \"uri1\" },"
537
                          " { \"id\": \"node2\", \"uri\": \"uri2\" } ]")
538
    self.assertEqual([{"id": "node1", "uri": "uri1"},
539
                      {"id": "node2", "uri": "uri2"}],
540
                     self.client.GetNodes(bulk=True))
541
    self.assertHandler(rlib2.R_2_nodes)
542
    self.assertBulk()
543

    
544
  def testGetNode(self):
545
    self.rapi.AddResponse("{}")
546
    self.assertEqual({}, self.client.GetNode("node-foo"))
547
    self.assertHandler(rlib2.R_2_nodes_name)
548
    self.assertItems(["node-foo"])
549

    
550
  def testEvacuateNode(self):
551
    self.rapi.AddResponse("9876")
552
    job_id = self.client.EvacuateNode("node-1", remote_node="node-2")
553
    self.assertEqual(9876, job_id)
554
    self.assertHandler(rlib2.R_2_nodes_name_evacuate)
555
    self.assertItems(["node-1"])
556
    self.assertQuery("remote_node", ["node-2"])
557

    
558
    self.rapi.AddResponse("8888")
559
    job_id = self.client.EvacuateNode("node-3", iallocator="hail", dry_run=True)
560
    self.assertEqual(8888, job_id)
561
    self.assertItems(["node-3"])
562
    self.assertQuery("iallocator", ["hail"])
563
    self.assertDryRun()
564

    
565
    self.assertRaises(client.GanetiApiError,
566
                      self.client.EvacuateNode,
567
                      "node-4", iallocator="hail", remote_node="node-5")
568

    
569
  def testMigrateNode(self):
570
    self.rapi.AddResponse("1111")
571
    self.assertEqual(1111, self.client.MigrateNode("node-a", dry_run=True))
572
    self.assertHandler(rlib2.R_2_nodes_name_migrate)
573
    self.assertItems(["node-a"])
574
    self.assertQuery("live", ["1"])
575
    self.assertDryRun()
576

    
577
  def testGetNodeRole(self):
578
    self.rapi.AddResponse("\"master\"")
579
    self.assertEqual("master", self.client.GetNodeRole("node-a"))
580
    self.assertHandler(rlib2.R_2_nodes_name_role)
581
    self.assertItems(["node-a"])
582

    
583
  def testSetNodeRole(self):
584
    self.rapi.AddResponse("789")
585
    self.assertEqual(789,
586
        self.client.SetNodeRole("node-foo", "master-candidate", force=True))
587
    self.assertHandler(rlib2.R_2_nodes_name_role)
588
    self.assertItems(["node-foo"])
589
    self.assertQuery("force", ["1"])
590
    self.assertEqual("\"master-candidate\"", self.http.last_request.data)
591

    
592
  def testGetNodeStorageUnits(self):
593
    self.rapi.AddResponse("42")
594
    self.assertEqual(42,
595
        self.client.GetNodeStorageUnits("node-x", "lvm-pv", "fields"))
596
    self.assertHandler(rlib2.R_2_nodes_name_storage)
597
    self.assertItems(["node-x"])
598
    self.assertQuery("storage_type", ["lvm-pv"])
599
    self.assertQuery("output_fields", ["fields"])
600

    
601
  def testModifyNodeStorageUnits(self):
602
    self.rapi.AddResponse("14")
603
    self.assertEqual(14,
604
        self.client.ModifyNodeStorageUnits("node-z", "lvm-pv", "hda"))
605
    self.assertHandler(rlib2.R_2_nodes_name_storage_modify)
606
    self.assertItems(["node-z"])
607
    self.assertQuery("storage_type", ["lvm-pv"])
608
    self.assertQuery("name", ["hda"])
609
    self.assertQuery("allocatable", None)
610

    
611
    for allocatable, query_allocatable in [(True, "1"), (False, "0")]:
612
      self.rapi.AddResponse("7205")
613
      job_id = self.client.ModifyNodeStorageUnits("node-z", "lvm-pv", "hda",
614
                                                  allocatable=allocatable)
615
      self.assertEqual(7205, job_id)
616
      self.assertHandler(rlib2.R_2_nodes_name_storage_modify)
617
      self.assertItems(["node-z"])
618
      self.assertQuery("storage_type", ["lvm-pv"])
619
      self.assertQuery("name", ["hda"])
620
      self.assertQuery("allocatable", [query_allocatable])
621

    
622
  def testRepairNodeStorageUnits(self):
623
    self.rapi.AddResponse("99")
624
    self.assertEqual(99, self.client.RepairNodeStorageUnits("node-z", "lvm-pv",
625
                                                            "hda"))
626
    self.assertHandler(rlib2.R_2_nodes_name_storage_repair)
627
    self.assertItems(["node-z"])
628
    self.assertQuery("storage_type", ["lvm-pv"])
629
    self.assertQuery("name", ["hda"])
630

    
631
  def testGetNodeTags(self):
632
    self.rapi.AddResponse("[\"fry\", \"bender\"]")
633
    self.assertEqual(["fry", "bender"], self.client.GetNodeTags("node-k"))
634
    self.assertHandler(rlib2.R_2_nodes_name_tags)
635
    self.assertItems(["node-k"])
636

    
637
  def testAddNodeTags(self):
638
    self.rapi.AddResponse("1234")
639
    self.assertEqual(1234,
640
        self.client.AddNodeTags("node-v", ["awesome"], dry_run=True))
641
    self.assertHandler(rlib2.R_2_nodes_name_tags)
642
    self.assertItems(["node-v"])
643
    self.assertDryRun()
644
    self.assertQuery("tag", ["awesome"])
645

    
646
  def testDeleteNodeTags(self):
647
    self.rapi.AddResponse("16861")
648
    self.assertEqual(16861, self.client.DeleteNodeTags("node-w", ["awesome"],
649
                                                       dry_run=True))
650
    self.assertHandler(rlib2.R_2_nodes_name_tags)
651
    self.assertItems(["node-w"])
652
    self.assertDryRun()
653
    self.assertQuery("tag", ["awesome"])
654

    
655

    
656
if __name__ == '__main__':
657
  testutils.GanetiTestProgram()