Move python test files to test/py
[ganeti-local] / test / py / ganeti.rapi.rlib2_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2010, 2012 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 rlib2 module
23
24 """
25
26
27 import unittest
28 import itertools
29 import random
30
31 from ganeti import constants
32 from ganeti import opcodes
33 from ganeti import compat
34 from ganeti import http
35 from ganeti import query
36 from ganeti import luxi
37 from ganeti import errors
38 from ganeti import rapi
39
40 from ganeti.rapi import rlib2
41 from ganeti.rapi import baserlib
42 from ganeti.rapi import connector
43
44 import testutils
45
46
47 class _FakeRequestPrivateData:
48   def __init__(self, body_data):
49     self.body_data = body_data
50
51
52 class _FakeRequest:
53   def __init__(self, body_data):
54     self.private = _FakeRequestPrivateData(body_data)
55
56
57 def _CreateHandler(cls, items, queryargs, body_data, client_cls):
58   return cls(items, queryargs, _FakeRequest(body_data),
59              _client_cls=client_cls)
60
61
62 class _FakeClient:
63   def __init__(self, address=None):
64     self._jobs = []
65
66   def GetNextSubmittedJob(self):
67     return self._jobs.pop(0)
68
69   def SubmitJob(self, ops):
70     job_id = str(1 + int(random.random() * 1000000))
71     self._jobs.append((job_id, ops))
72     return job_id
73
74
75 class _FakeClientFactory:
76   def __init__(self, cls):
77     self._client_cls = cls
78     self._clients = []
79
80   def GetNextClient(self):
81     return self._clients.pop(0)
82
83   def __call__(self, address=None):
84     cl = self._client_cls(address=address)
85     self._clients.append(cl)
86     return cl
87
88
89 class TestConstants(unittest.TestCase):
90   def testConsole(self):
91     # Exporting the console field without authentication might expose
92     # information
93     assert "console" in query.INSTANCE_FIELDS
94     self.assertTrue("console" not in rlib2.I_FIELDS)
95
96   def testFields(self):
97     checks = {
98       constants.QR_INSTANCE: rlib2.I_FIELDS,
99       constants.QR_NODE: rlib2.N_FIELDS,
100       constants.QR_GROUP: rlib2.G_FIELDS,
101       }
102
103     for (qr, fields) in checks.items():
104       self.assertFalse(set(fields) - set(query.ALL_FIELDS[qr].keys()))
105
106
107 class TestClientConnectError(unittest.TestCase):
108   @staticmethod
109   def _FailingClient(address=None):
110     raise luxi.NoMasterError("test")
111
112   def test(self):
113     resources = [
114       rlib2.R_2_groups,
115       rlib2.R_2_instances,
116       rlib2.R_2_nodes,
117       ]
118     for cls in resources:
119       handler = _CreateHandler(cls, ["name"], [], None, self._FailingClient)
120       self.assertRaises(http.HttpBadGateway, handler.GET)
121
122
123 class TestJobSubmitError(unittest.TestCase):
124   class _SubmitErrorClient:
125     def __init__(self, address=None):
126       pass
127
128     @staticmethod
129     def SubmitJob(ops):
130       raise errors.JobQueueFull("test")
131
132   def test(self):
133     handler = _CreateHandler(rlib2.R_2_redist_config, [], [], None,
134                              self._SubmitErrorClient)
135     self.assertRaises(http.HttpServiceUnavailable, handler.PUT)
136
137
138 class TestClusterModify(unittest.TestCase):
139   def test(self):
140     clfactory = _FakeClientFactory(_FakeClient)
141     handler = _CreateHandler(rlib2.R_2_cluster_modify, [], [], {
142       "vg_name": "testvg",
143       "candidate_pool_size": 100,
144       }, clfactory)
145     job_id = handler.PUT()
146
147     cl = clfactory.GetNextClient()
148     self.assertRaises(IndexError, clfactory.GetNextClient)
149
150     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
151     self.assertEqual(job_id, exp_job_id)
152     self.assertTrue(isinstance(op, opcodes.OpClusterSetParams))
153     self.assertEqual(op.vg_name, "testvg")
154     self.assertEqual(op.candidate_pool_size, 100)
155
156     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
157
158   def testInvalidValue(self):
159     for attr in ["vg_name", "candidate_pool_size", "beparams", "_-Unknown#"]:
160       clfactory = _FakeClientFactory(_FakeClient)
161       handler = _CreateHandler(rlib2.R_2_cluster_modify, [], [], {
162         attr: True,
163         }, clfactory)
164       self.assertRaises(http.HttpBadRequest, handler.PUT)
165       self.assertRaises(IndexError, clfactory.GetNextClient)
166
167
168 class TestRedistConfig(unittest.TestCase):
169   def test(self):
170     clfactory = _FakeClientFactory(_FakeClient)
171     handler = _CreateHandler(rlib2.R_2_redist_config, [], [], None, clfactory)
172     job_id = handler.PUT()
173
174     cl = clfactory.GetNextClient()
175     self.assertRaises(IndexError, clfactory.GetNextClient)
176
177     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
178     self.assertEqual(job_id, exp_job_id)
179     self.assertTrue(isinstance(op, opcodes.OpClusterRedistConf))
180
181     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
182
183
184 class TestNodeMigrate(unittest.TestCase):
185   def test(self):
186     clfactory = _FakeClientFactory(_FakeClient)
187     handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node1"], {}, {
188       "iallocator": "fooalloc",
189       }, clfactory)
190     job_id = handler.POST()
191
192     cl = clfactory.GetNextClient()
193     self.assertRaises(IndexError, clfactory.GetNextClient)
194
195     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
196     self.assertEqual(job_id, exp_job_id)
197     self.assertTrue(isinstance(op, opcodes.OpNodeMigrate))
198     self.assertEqual(op.node_name, "node1")
199     self.assertEqual(op.iallocator, "fooalloc")
200
201     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
202
203   def testQueryArgsConflict(self):
204     clfactory = _FakeClientFactory(_FakeClient)
205     handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node2"], {
206       "live": True,
207       "mode": constants.HT_MIGRATION_NONLIVE,
208       }, None, clfactory)
209     self.assertRaises(http.HttpBadRequest, handler.POST)
210     self.assertRaises(IndexError, clfactory.GetNextClient)
211
212   def testQueryArgsMode(self):
213     clfactory = _FakeClientFactory(_FakeClient)
214     queryargs = {
215       "mode": [constants.HT_MIGRATION_LIVE],
216       }
217     handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node17292"],
218                              queryargs, None, clfactory)
219     job_id = handler.POST()
220
221     cl = clfactory.GetNextClient()
222     self.assertRaises(IndexError, clfactory.GetNextClient)
223
224     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
225     self.assertEqual(job_id, exp_job_id)
226     self.assertTrue(isinstance(op, opcodes.OpNodeMigrate))
227     self.assertEqual(op.node_name, "node17292")
228     self.assertEqual(op.mode, constants.HT_MIGRATION_LIVE)
229
230     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
231
232   def testQueryArgsLive(self):
233     clfactory = _FakeClientFactory(_FakeClient)
234
235     for live in [False, True]:
236       queryargs = {
237         "live": [str(int(live))],
238         }
239       handler = _CreateHandler(rlib2.R_2_nodes_name_migrate, ["node6940"],
240                                queryargs, None, clfactory)
241       job_id = handler.POST()
242
243       cl = clfactory.GetNextClient()
244       self.assertRaises(IndexError, clfactory.GetNextClient)
245
246       (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
247       self.assertEqual(job_id, exp_job_id)
248       self.assertTrue(isinstance(op, opcodes.OpNodeMigrate))
249       self.assertEqual(op.node_name, "node6940")
250       if live:
251         self.assertEqual(op.mode, constants.HT_MIGRATION_LIVE)
252       else:
253         self.assertEqual(op.mode, constants.HT_MIGRATION_NONLIVE)
254
255       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
256
257
258 class TestNodeEvacuate(unittest.TestCase):
259   def test(self):
260     clfactory = _FakeClientFactory(_FakeClient)
261     handler = _CreateHandler(rlib2.R_2_nodes_name_evacuate, ["node92"], {
262       "dry-run": ["1"],
263       }, {
264       "mode": constants.IALLOCATOR_NEVAC_SEC,
265       }, clfactory)
266     job_id = handler.POST()
267
268     cl = clfactory.GetNextClient()
269     self.assertRaises(IndexError, clfactory.GetNextClient)
270
271     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
272     self.assertEqual(job_id, exp_job_id)
273     self.assertTrue(isinstance(op, opcodes.OpNodeEvacuate))
274     self.assertEqual(op.node_name, "node92")
275     self.assertEqual(op.mode, constants.IALLOCATOR_NEVAC_SEC)
276     self.assertTrue(op.dry_run)
277
278     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
279
280
281 class TestNodePowercycle(unittest.TestCase):
282   def test(self):
283     clfactory = _FakeClientFactory(_FakeClient)
284     handler = _CreateHandler(rlib2.R_2_nodes_name_powercycle, ["node20744"], {
285       "force": ["1"],
286       }, None, clfactory)
287     job_id = handler.POST()
288
289     cl = clfactory.GetNextClient()
290     self.assertRaises(IndexError, clfactory.GetNextClient)
291
292     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
293     self.assertEqual(job_id, exp_job_id)
294     self.assertTrue(isinstance(op, opcodes.OpNodePowercycle))
295     self.assertEqual(op.node_name, "node20744")
296     self.assertTrue(op.force)
297
298     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
299
300
301 class TestGroupAssignNodes(unittest.TestCase):
302   def test(self):
303     clfactory = _FakeClientFactory(_FakeClient)
304     handler = _CreateHandler(rlib2.R_2_groups_name_assign_nodes, ["grp-a"], {
305       "dry-run": ["1"],
306       "force": ["1"],
307       }, {
308       "nodes": ["n2", "n3"],
309       }, clfactory)
310     job_id = handler.PUT()
311
312     cl = clfactory.GetNextClient()
313     self.assertRaises(IndexError, clfactory.GetNextClient)
314
315     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
316     self.assertEqual(job_id, exp_job_id)
317     self.assertTrue(isinstance(op, opcodes.OpGroupAssignNodes))
318     self.assertEqual(op.group_name, "grp-a")
319     self.assertEqual(op.nodes, ["n2", "n3"])
320     self.assertTrue(op.dry_run)
321     self.assertTrue(op.force)
322
323     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
324
325
326 class TestInstanceDelete(unittest.TestCase):
327   def test(self):
328     clfactory = _FakeClientFactory(_FakeClient)
329     handler = _CreateHandler(rlib2.R_2_instances_name, ["inst30965"], {
330       "dry-run": ["1"],
331       }, {}, clfactory)
332     job_id = handler.DELETE()
333
334     cl = clfactory.GetNextClient()
335     self.assertRaises(IndexError, clfactory.GetNextClient)
336
337     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
338     self.assertEqual(job_id, exp_job_id)
339     self.assertTrue(isinstance(op, opcodes.OpInstanceRemove))
340     self.assertEqual(op.instance_name, "inst30965")
341     self.assertTrue(op.dry_run)
342     self.assertFalse(op.ignore_failures)
343
344     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
345
346
347 class TestInstanceInfo(unittest.TestCase):
348   def test(self):
349     clfactory = _FakeClientFactory(_FakeClient)
350     handler = _CreateHandler(rlib2.R_2_instances_name_info, ["inst31217"], {
351       "static": ["1"],
352       }, {}, clfactory)
353     job_id = handler.GET()
354
355     cl = clfactory.GetNextClient()
356     self.assertRaises(IndexError, clfactory.GetNextClient)
357
358     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
359     self.assertEqual(job_id, exp_job_id)
360     self.assertTrue(isinstance(op, opcodes.OpInstanceQueryData))
361     self.assertEqual(op.instances, ["inst31217"])
362     self.assertTrue(op.static)
363
364     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
365
366
367 class TestInstanceReboot(unittest.TestCase):
368   def test(self):
369     clfactory = _FakeClientFactory(_FakeClient)
370     handler = _CreateHandler(rlib2.R_2_instances_name_reboot, ["inst847"], {
371       "dry-run": ["1"],
372       "ignore_secondaries": ["1"],
373       }, {}, clfactory)
374     job_id = handler.POST()
375
376     cl = clfactory.GetNextClient()
377     self.assertRaises(IndexError, clfactory.GetNextClient)
378
379     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
380     self.assertEqual(job_id, exp_job_id)
381     self.assertTrue(isinstance(op, opcodes.OpInstanceReboot))
382     self.assertEqual(op.instance_name, "inst847")
383     self.assertEqual(op.reboot_type, constants.INSTANCE_REBOOT_HARD)
384     self.assertTrue(op.ignore_secondaries)
385     self.assertTrue(op.dry_run)
386
387     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
388
389
390 class TestInstanceStartup(unittest.TestCase):
391   def test(self):
392     clfactory = _FakeClientFactory(_FakeClient)
393     handler = _CreateHandler(rlib2.R_2_instances_name_startup, ["inst31083"], {
394       "force": ["1"],
395       "no_remember": ["1"],
396       }, {}, clfactory)
397     job_id = handler.PUT()
398
399     cl = clfactory.GetNextClient()
400     self.assertRaises(IndexError, clfactory.GetNextClient)
401
402     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
403     self.assertEqual(job_id, exp_job_id)
404     self.assertTrue(isinstance(op, opcodes.OpInstanceStartup))
405     self.assertEqual(op.instance_name, "inst31083")
406     self.assertTrue(op.no_remember)
407     self.assertTrue(op.force)
408     self.assertFalse(op.dry_run)
409
410     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
411
412
413 class TestInstanceShutdown(unittest.TestCase):
414   def test(self):
415     clfactory = _FakeClientFactory(_FakeClient)
416     handler = _CreateHandler(rlib2.R_2_instances_name_shutdown, ["inst26791"], {
417       "no_remember": ["0"],
418       }, {}, clfactory)
419     job_id = handler.PUT()
420
421     cl = clfactory.GetNextClient()
422     self.assertRaises(IndexError, clfactory.GetNextClient)
423
424     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
425     self.assertEqual(job_id, exp_job_id)
426     self.assertTrue(isinstance(op, opcodes.OpInstanceShutdown))
427     self.assertEqual(op.instance_name, "inst26791")
428     self.assertFalse(op.no_remember)
429     self.assertFalse(op.dry_run)
430
431     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
432
433
434 class TestInstanceActivateDisks(unittest.TestCase):
435   def test(self):
436     clfactory = _FakeClientFactory(_FakeClient)
437     handler = _CreateHandler(rlib2.R_2_instances_name_activate_disks, ["xyz"], {
438       "ignore_size": ["1"],
439       }, {}, clfactory)
440     job_id = handler.PUT()
441
442     cl = clfactory.GetNextClient()
443     self.assertRaises(IndexError, clfactory.GetNextClient)
444
445     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
446     self.assertEqual(job_id, exp_job_id)
447     self.assertTrue(isinstance(op, opcodes.OpInstanceActivateDisks))
448     self.assertEqual(op.instance_name, "xyz")
449     self.assertTrue(op.ignore_size)
450     self.assertFalse(hasattr(op, "dry_run"))
451
452     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
453
454
455 class TestInstanceDeactivateDisks(unittest.TestCase):
456   def test(self):
457     clfactory = _FakeClientFactory(_FakeClient)
458     handler = _CreateHandler(rlib2.R_2_instances_name_deactivate_disks,
459                              ["inst22357"], {}, {}, clfactory)
460     job_id = handler.PUT()
461
462     cl = clfactory.GetNextClient()
463     self.assertRaises(IndexError, clfactory.GetNextClient)
464
465     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
466     self.assertEqual(job_id, exp_job_id)
467     self.assertTrue(isinstance(op, opcodes.OpInstanceDeactivateDisks))
468     self.assertEqual(op.instance_name, "inst22357")
469     self.assertFalse(hasattr(op, "dry_run"))
470     self.assertFalse(hasattr(op, "force"))
471
472     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
473
474
475 class TestInstanceRecreateDisks(unittest.TestCase):
476   def test(self):
477     clfactory = _FakeClientFactory(_FakeClient)
478     handler = _CreateHandler(rlib2.R_2_instances_name_recreate_disks,
479                              ["inst22357"], {}, {}, clfactory)
480     job_id = handler.POST()
481
482     cl = clfactory.GetNextClient()
483     self.assertRaises(IndexError, clfactory.GetNextClient)
484
485     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
486     self.assertEqual(job_id, exp_job_id)
487     self.assertTrue(isinstance(op, opcodes.OpInstanceRecreateDisks))
488     self.assertEqual(op.instance_name, "inst22357")
489     self.assertFalse(hasattr(op, "dry_run"))
490     self.assertFalse(hasattr(op, "force"))
491
492     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
493
494
495 class TestInstanceFailover(unittest.TestCase):
496   def test(self):
497     clfactory = _FakeClientFactory(_FakeClient)
498     handler = _CreateHandler(rlib2.R_2_instances_name_failover,
499                              ["inst12794"], {}, {}, clfactory)
500     job_id = handler.PUT()
501
502     cl = clfactory.GetNextClient()
503     self.assertRaises(IndexError, clfactory.GetNextClient)
504
505     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
506     self.assertEqual(job_id, exp_job_id)
507     self.assertTrue(isinstance(op, opcodes.OpInstanceFailover))
508     self.assertEqual(op.instance_name, "inst12794")
509     self.assertFalse(hasattr(op, "dry_run"))
510     self.assertFalse(hasattr(op, "force"))
511
512     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
513
514
515 class TestInstanceDiskGrow(unittest.TestCase):
516   def test(self):
517     clfactory = _FakeClientFactory(_FakeClient)
518     data = {
519       "amount": 1024,
520       }
521     handler = _CreateHandler(rlib2.R_2_instances_name_disk_grow,
522                              ["inst10742", "3"], {}, data, clfactory)
523     job_id = handler.POST()
524
525     cl = clfactory.GetNextClient()
526     self.assertRaises(IndexError, clfactory.GetNextClient)
527
528     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
529     self.assertEqual(job_id, exp_job_id)
530     self.assertTrue(isinstance(op, opcodes.OpInstanceGrowDisk))
531     self.assertEqual(op.instance_name, "inst10742")
532     self.assertEqual(op.disk, 3)
533     self.assertEqual(op.amount, 1024)
534     self.assertFalse(hasattr(op, "dry_run"))
535     self.assertFalse(hasattr(op, "force"))
536
537     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
538
539
540 class TestBackupPrepare(unittest.TestCase):
541   def test(self):
542     clfactory = _FakeClientFactory(_FakeClient)
543     queryargs = {
544       "mode": constants.EXPORT_MODE_REMOTE,
545       }
546     handler = _CreateHandler(rlib2.R_2_instances_name_prepare_export,
547                              ["inst17925"], queryargs, {}, clfactory)
548     job_id = handler.PUT()
549
550     cl = clfactory.GetNextClient()
551     self.assertRaises(IndexError, clfactory.GetNextClient)
552
553     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
554     self.assertEqual(job_id, exp_job_id)
555     self.assertTrue(isinstance(op, opcodes.OpBackupPrepare))
556     self.assertEqual(op.instance_name, "inst17925")
557     self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE)
558     self.assertFalse(hasattr(op, "dry_run"))
559     self.assertFalse(hasattr(op, "force"))
560
561     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
562
563
564 class TestGroupRemove(unittest.TestCase):
565   def test(self):
566     clfactory = _FakeClientFactory(_FakeClient)
567     handler = _CreateHandler(rlib2.R_2_groups_name,
568                              ["grp28575"], {}, {}, clfactory)
569     job_id = handler.DELETE()
570
571     cl = clfactory.GetNextClient()
572     self.assertRaises(IndexError, clfactory.GetNextClient)
573
574     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
575     self.assertEqual(job_id, exp_job_id)
576     self.assertTrue(isinstance(op, opcodes.OpGroupRemove))
577     self.assertEqual(op.group_name, "grp28575")
578     self.assertFalse(op.dry_run)
579     self.assertFalse(hasattr(op, "force"))
580
581     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
582
583
584 class TestStorageQuery(unittest.TestCase):
585   def test(self):
586     clfactory = _FakeClientFactory(_FakeClient)
587     queryargs = {
588       "storage_type": constants.ST_LVM_PV,
589       "output_fields": "name,other",
590       }
591     handler = _CreateHandler(rlib2.R_2_nodes_name_storage,
592                              ["node21075"], queryargs, {}, clfactory)
593     job_id = handler.GET()
594
595     cl = clfactory.GetNextClient()
596     self.assertRaises(IndexError, clfactory.GetNextClient)
597
598     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
599     self.assertEqual(job_id, exp_job_id)
600     self.assertTrue(isinstance(op, opcodes.OpNodeQueryStorage))
601     self.assertEqual(op.nodes, ["node21075"])
602     self.assertEqual(op.storage_type, constants.ST_LVM_PV)
603     self.assertEqual(op.output_fields, ["name", "other"])
604     self.assertFalse(hasattr(op, "dry_run"))
605     self.assertFalse(hasattr(op, "force"))
606
607     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
608
609   def testErrors(self):
610     clfactory = _FakeClientFactory(_FakeClient)
611
612     queryargs = {
613       "output_fields": "name,other",
614       }
615     handler = _CreateHandler(rlib2.R_2_nodes_name_storage,
616                              ["node10538"], queryargs, {}, clfactory)
617     self.assertRaises(http.HttpBadRequest, handler.GET)
618
619     queryargs = {
620       "storage_type": constants.ST_LVM_VG,
621       }
622     handler = _CreateHandler(rlib2.R_2_nodes_name_storage,
623                              ["node21273"], queryargs, {}, clfactory)
624     self.assertRaises(http.HttpBadRequest, handler.GET)
625
626     queryargs = {
627       "storage_type": "##unknown_storage##",
628       "output_fields": "name,other",
629       }
630     handler = _CreateHandler(rlib2.R_2_nodes_name_storage,
631                              ["node10315"], queryargs, {}, clfactory)
632     self.assertRaises(http.HttpBadRequest, handler.GET)
633
634
635 class TestStorageModify(unittest.TestCase):
636   def test(self):
637     clfactory = _FakeClientFactory(_FakeClient)
638
639     for allocatable in [None, "1", "0"]:
640       queryargs = {
641         "storage_type": constants.ST_LVM_VG,
642         "name": "pv-a",
643         }
644
645       if allocatable is not None:
646         queryargs["allocatable"] = allocatable
647
648       handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify,
649                                ["node9292"], queryargs, {}, clfactory)
650       job_id = handler.PUT()
651
652       cl = clfactory.GetNextClient()
653       self.assertRaises(IndexError, clfactory.GetNextClient)
654
655       (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
656       self.assertEqual(job_id, exp_job_id)
657       self.assertTrue(isinstance(op, opcodes.OpNodeModifyStorage))
658       self.assertEqual(op.node_name, "node9292")
659       self.assertEqual(op.storage_type, constants.ST_LVM_VG)
660       self.assertEqual(op.name, "pv-a")
661       if allocatable is None:
662         self.assertFalse(op.changes)
663       else:
664         assert allocatable in ("0", "1")
665         self.assertEqual(op.changes, {
666           constants.SF_ALLOCATABLE: (allocatable == "1"),
667           })
668       self.assertFalse(hasattr(op, "dry_run"))
669       self.assertFalse(hasattr(op, "force"))
670
671       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
672
673   def testErrors(self):
674     clfactory = _FakeClientFactory(_FakeClient)
675
676     # No storage type
677     queryargs = {
678       "name": "xyz",
679       }
680     handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify,
681                              ["node26016"], queryargs, {}, clfactory)
682     self.assertRaises(http.HttpBadRequest, handler.PUT)
683
684     # No name
685     queryargs = {
686       "storage_type": constants.ST_LVM_VG,
687       }
688     handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify,
689                              ["node21218"], queryargs, {}, clfactory)
690     self.assertRaises(http.HttpBadRequest, handler.PUT)
691
692     # Invalid value
693     queryargs = {
694       "storage_type": constants.ST_LVM_VG,
695       "name": "pv-b",
696       "allocatable": "noint",
697       }
698     handler = _CreateHandler(rlib2.R_2_nodes_name_storage_modify,
699                              ["node30685"], queryargs, {}, clfactory)
700     self.assertRaises(http.HttpBadRequest, handler.PUT)
701
702
703 class TestStorageRepair(unittest.TestCase):
704   def test(self):
705     clfactory = _FakeClientFactory(_FakeClient)
706     queryargs = {
707       "storage_type": constants.ST_LVM_PV,
708       "name": "pv16611",
709       }
710     handler = _CreateHandler(rlib2.R_2_nodes_name_storage_repair,
711                              ["node19265"], queryargs, {}, clfactory)
712     job_id = handler.PUT()
713
714     cl = clfactory.GetNextClient()
715     self.assertRaises(IndexError, clfactory.GetNextClient)
716
717     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
718     self.assertEqual(job_id, exp_job_id)
719     self.assertTrue(isinstance(op, opcodes.OpRepairNodeStorage))
720     self.assertEqual(op.node_name, "node19265")
721     self.assertEqual(op.storage_type, constants.ST_LVM_PV)
722     self.assertEqual(op.name, "pv16611")
723     self.assertFalse(hasattr(op, "dry_run"))
724     self.assertFalse(hasattr(op, "force"))
725
726     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
727
728   def testErrors(self):
729     clfactory = _FakeClientFactory(_FakeClient)
730
731     # No storage type
732     queryargs = {
733       "name": "xyz",
734       }
735     handler = _CreateHandler(rlib2.R_2_nodes_name_storage_repair,
736                              ["node11275"], queryargs, {}, clfactory)
737     self.assertRaises(http.HttpBadRequest, handler.PUT)
738
739     # No name
740     queryargs = {
741       "storage_type": constants.ST_LVM_VG,
742       }
743     handler = _CreateHandler(rlib2.R_2_nodes_name_storage_repair,
744                              ["node21218"], queryargs, {}, clfactory)
745     self.assertRaises(http.HttpBadRequest, handler.PUT)
746
747
748 class TestTags(unittest.TestCase):
749   TAG_HANDLERS = [
750     rlib2.R_2_instances_name_tags,
751     rlib2.R_2_nodes_name_tags,
752     rlib2.R_2_groups_name_tags,
753     rlib2.R_2_tags,
754     ]
755
756   def testSetAndDelete(self):
757     clfactory = _FakeClientFactory(_FakeClient)
758
759     for method, opcls in [("PUT", opcodes.OpTagsSet),
760                           ("DELETE", opcodes.OpTagsDel)]:
761       for idx, handler in enumerate(self.TAG_HANDLERS):
762         dry_run = bool(idx % 2)
763         name = "test%s" % idx
764         queryargs = {
765           "tag": ["foo", "bar", "baz"],
766           "dry-run": str(int(dry_run)),
767           }
768
769         handler = _CreateHandler(handler, [name], queryargs, {}, clfactory)
770         job_id = getattr(handler, method)()
771
772         cl = clfactory.GetNextClient()
773         self.assertRaises(IndexError, clfactory.GetNextClient)
774
775         (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
776         self.assertEqual(job_id, exp_job_id)
777         self.assertTrue(isinstance(op, opcls))
778         self.assertEqual(op.kind, handler.TAG_LEVEL)
779         if handler.TAG_LEVEL == constants.TAG_CLUSTER:
780           self.assertTrue(op.name is None)
781         else:
782           self.assertEqual(op.name, name)
783         self.assertEqual(op.tags, ["foo", "bar", "baz"])
784         self.assertEqual(op.dry_run, dry_run)
785         self.assertFalse(hasattr(op, "force"))
786
787         self.assertRaises(IndexError, cl.GetNextSubmittedJob)
788
789
790 class TestInstanceCreation(testutils.GanetiTestCase):
791   def test(self):
792     clfactory = _FakeClientFactory(_FakeClient)
793
794     name = "inst863.example.com"
795
796     disk_variants = [
797       # No disks
798       [],
799
800       # Two disks
801       [{"size": 5, }, {"size": 100, }],
802
803       # Disk with mode
804       [{"size": 123, "mode": constants.DISK_RDWR, }],
805       ]
806
807     nic_variants = [
808       # No NIC
809       [],
810
811       # Three NICs
812       [{}, {}, {}],
813
814       # Two NICs
815       [
816         { "ip": "192.0.2.6", "mode": constants.NIC_MODE_ROUTED,
817           "mac": "01:23:45:67:68:9A",
818         },
819         { "mode": constants.NIC_MODE_BRIDGED, "link": "br1" },
820       ],
821       ]
822
823     beparam_variants = [
824       None,
825       {},
826       { constants.BE_VCPUS: 2, },
827       { constants.BE_MAXMEM: 200, },
828       { constants.BE_MEMORY: 256, },
829       { constants.BE_VCPUS: 2,
830         constants.BE_MAXMEM: 1024,
831         constants.BE_MINMEM: 1024,
832         constants.BE_AUTO_BALANCE: True,
833         constants.BE_ALWAYS_FAILOVER: True, }
834       ]
835
836     hvparam_variants = [
837       None,
838       { constants.HV_BOOT_ORDER: "anc", },
839       { constants.HV_KERNEL_PATH: "/boot/fookernel",
840         constants.HV_ROOT_PATH: "/dev/hda1", },
841       ]
842
843     for mode in [constants.INSTANCE_CREATE, constants.INSTANCE_IMPORT]:
844       for nics in nic_variants:
845         for disk_template in constants.DISK_TEMPLATES:
846           for disks in disk_variants:
847             for beparams in beparam_variants:
848               for hvparams in hvparam_variants:
849                 for dry_run in [False, True]:
850                   queryargs = {
851                     "dry-run": str(int(dry_run)),
852                     }
853
854                   data = {
855                     rlib2._REQ_DATA_VERSION: 1,
856                     "name": name,
857                     "hypervisor": constants.HT_FAKE,
858                     "disks": disks,
859                     "nics": nics,
860                     "mode": mode,
861                     "disk_template": disk_template,
862                     "os": "debootstrap",
863                     }
864
865                   if beparams is not None:
866                     data["beparams"] = beparams
867
868                   if hvparams is not None:
869                     data["hvparams"] = hvparams
870
871                   handler = _CreateHandler(rlib2.R_2_instances, [],
872                                            queryargs, data, clfactory)
873                   job_id = handler.POST()
874
875                   cl = clfactory.GetNextClient()
876                   self.assertRaises(IndexError, clfactory.GetNextClient)
877
878                   (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
879                   self.assertEqual(job_id, exp_job_id)
880                   self.assertRaises(IndexError, cl.GetNextSubmittedJob)
881
882                   self.assertTrue(isinstance(op, opcodes.OpInstanceCreate))
883                   self.assertEqual(op.instance_name, name)
884                   self.assertEqual(op.mode, mode)
885                   self.assertEqual(op.disk_template, disk_template)
886                   self.assertEqual(op.dry_run, dry_run)
887                   self.assertEqual(len(op.disks), len(disks))
888                   self.assertEqual(len(op.nics), len(nics))
889
890                   for opdisk, disk in zip(op.disks, disks):
891                     for key in constants.IDISK_PARAMS:
892                       self.assertEqual(opdisk.get(key), disk.get(key))
893                     self.assertFalse("unknown" in opdisk)
894
895                   for opnic, nic in zip(op.nics, nics):
896                     for key in constants.INIC_PARAMS:
897                       self.assertEqual(opnic.get(key), nic.get(key))
898                     self.assertFalse("unknown" in opnic)
899                     self.assertFalse("foobar" in opnic)
900
901                   if beparams is None:
902                     self.assertFalse(hasattr(op, "beparams"))
903                   else:
904                     self.assertEqualValues(op.beparams, beparams)
905
906                   if hvparams is None:
907                     self.assertFalse(hasattr(op, "hvparams"))
908                   else:
909                     self.assertEqualValues(op.hvparams, hvparams)
910
911   def testLegacyName(self):
912     clfactory = _FakeClientFactory(_FakeClient)
913
914     name = "inst29128.example.com"
915     data = {
916       rlib2._REQ_DATA_VERSION: 1,
917       "name": name,
918       "disks": [],
919       "nics": [],
920       "mode": constants.INSTANCE_CREATE,
921       "disk_template": constants.DT_PLAIN,
922       }
923
924     handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
925     job_id = handler.POST()
926
927     cl = clfactory.GetNextClient()
928     self.assertRaises(IndexError, clfactory.GetNextClient)
929
930     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
931     self.assertEqual(job_id, exp_job_id)
932     self.assertTrue(isinstance(op, opcodes.OpInstanceCreate))
933     self.assertEqual(op.instance_name, name)
934     self.assertFalse(hasattr(op, "name"))
935     self.assertFalse(op.dry_run)
936
937     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
938
939     # Define both
940     data["instance_name"] = "other.example.com"
941     assert "name" in data and "instance_name" in data
942     handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
943     self.assertRaises(http.HttpBadRequest, handler.POST)
944     self.assertRaises(IndexError, clfactory.GetNextClient)
945
946   def testLegacyOs(self):
947     clfactory = _FakeClientFactory(_FakeClient)
948
949     name = "inst4673.example.com"
950     os = "linux29206"
951     data = {
952       rlib2._REQ_DATA_VERSION: 1,
953       "name": name,
954       "os_type": os,
955       "disks": [],
956       "nics": [],
957       "mode": constants.INSTANCE_CREATE,
958       "disk_template": constants.DT_PLAIN,
959       }
960
961     handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
962     job_id = handler.POST()
963
964     cl = clfactory.GetNextClient()
965     self.assertRaises(IndexError, clfactory.GetNextClient)
966
967     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
968     self.assertEqual(job_id, exp_job_id)
969     self.assertTrue(isinstance(op, opcodes.OpInstanceCreate))
970     self.assertEqual(op.instance_name, name)
971     self.assertEqual(op.os_type, os)
972     self.assertFalse(hasattr(op, "os"))
973     self.assertFalse(op.dry_run)
974
975     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
976
977     # Define both
978     data["os"] = "linux9584"
979     assert "os" in data and "os_type" in data
980     handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
981     self.assertRaises(http.HttpBadRequest, handler.POST)
982
983   def testErrors(self):
984     clfactory = _FakeClientFactory(_FakeClient)
985
986     # Test all required fields
987     reqfields = {
988       rlib2._REQ_DATA_VERSION: 1,
989       "name": "inst1.example.com",
990       "disks": [],
991       "nics": [],
992       "mode": constants.INSTANCE_CREATE,
993       "disk_template": constants.DT_PLAIN,
994       }
995
996     for name in reqfields.keys():
997       data = dict(i for i in reqfields.iteritems() if i[0] != name)
998
999       handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
1000       self.assertRaises(http.HttpBadRequest, handler.POST)
1001       self.assertRaises(IndexError, clfactory.GetNextClient)
1002
1003     # Invalid disks and nics
1004     for field in ["disks", "nics"]:
1005       invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"],
1006                         [{"_unknown_": False, }]]
1007
1008       for invvalue in invalid_values:
1009         data = reqfields.copy()
1010         data[field] = invvalue
1011         handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
1012         self.assertRaises(http.HttpBadRequest, handler.POST)
1013         self.assertRaises(IndexError, clfactory.GetNextClient)
1014
1015   def testVersion(self):
1016     clfactory = _FakeClientFactory(_FakeClient)
1017
1018     # No version field
1019     data = {
1020       "name": "inst1.example.com",
1021       "disks": [],
1022       "nics": [],
1023       "mode": constants.INSTANCE_CREATE,
1024       "disk_template": constants.DT_PLAIN,
1025       }
1026
1027     handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
1028     self.assertRaises(http.HttpBadRequest, handler.POST)
1029
1030     # Old and incorrect versions
1031     for version in [0, -1, 10483, "Hello World"]:
1032       data[rlib2._REQ_DATA_VERSION] = version
1033
1034       handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
1035       self.assertRaises(http.HttpBadRequest, handler.POST)
1036
1037       self.assertRaises(IndexError, clfactory.GetNextClient)
1038
1039     # Correct version
1040     data[rlib2._REQ_DATA_VERSION] = 1
1041     handler = _CreateHandler(rlib2.R_2_instances, [], {}, data, clfactory)
1042     job_id = handler.POST()
1043
1044     cl = clfactory.GetNextClient()
1045     self.assertRaises(IndexError, clfactory.GetNextClient)
1046
1047     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1048     self.assertEqual(job_id, exp_job_id)
1049     self.assertTrue(isinstance(op, opcodes.OpInstanceCreate))
1050     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1051
1052
1053 class TestBackupExport(unittest.TestCase):
1054   def test(self):
1055     clfactory = _FakeClientFactory(_FakeClient)
1056
1057     name = "instmoo"
1058     data = {
1059       "mode": constants.EXPORT_MODE_REMOTE,
1060       "destination": [(1, 2, 3), (99, 99, 99)],
1061       "shutdown": True,
1062       "remove_instance": True,
1063       "x509_key_name": ["name", "hash"],
1064       "destination_x509_ca": "---cert---"
1065       }
1066
1067     handler = _CreateHandler(rlib2.R_2_instances_name_export, [name], {},
1068                              data, clfactory)
1069     job_id = handler.PUT()
1070
1071     cl = clfactory.GetNextClient()
1072     self.assertRaises(IndexError, clfactory.GetNextClient)
1073
1074     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1075     self.assertEqual(job_id, exp_job_id)
1076     self.assertTrue(isinstance(op, opcodes.OpBackupExport))
1077     self.assertEqual(op.instance_name, name)
1078     self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE)
1079     self.assertEqual(op.target_node, [(1, 2, 3), (99, 99, 99)])
1080     self.assertEqual(op.shutdown, True)
1081     self.assertEqual(op.remove_instance, True)
1082     self.assertEqual(op.x509_key_name, ["name", "hash"])
1083     self.assertEqual(op.destination_x509_ca, "---cert---")
1084     self.assertFalse(hasattr(op, "dry_run"))
1085     self.assertFalse(hasattr(op, "force"))
1086
1087     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1088
1089   def testDefaults(self):
1090     clfactory = _FakeClientFactory(_FakeClient)
1091
1092     name = "inst1"
1093     data = {
1094       "destination": "node2",
1095       "shutdown": False,
1096       }
1097
1098     handler = _CreateHandler(rlib2.R_2_instances_name_export, [name], {},
1099                              data, clfactory)
1100     job_id = handler.PUT()
1101
1102     cl = clfactory.GetNextClient()
1103     self.assertRaises(IndexError, clfactory.GetNextClient)
1104
1105     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1106     self.assertEqual(job_id, exp_job_id)
1107     self.assertTrue(isinstance(op, opcodes.OpBackupExport))
1108     self.assertEqual(op.instance_name, name)
1109     self.assertEqual(op.target_node, "node2")
1110     self.assertFalse(hasattr(op, "mode"))
1111     self.assertFalse(hasattr(op, "remove_instance"))
1112     self.assertFalse(hasattr(op, "destination"))
1113     self.assertFalse(hasattr(op, "dry_run"))
1114     self.assertFalse(hasattr(op, "force"))
1115
1116     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1117
1118   def testErrors(self):
1119     clfactory = _FakeClientFactory(_FakeClient)
1120
1121     for value in ["True", "False"]:
1122       handler = _CreateHandler(rlib2.R_2_instances_name_export, ["err1"], {}, {
1123         "remove_instance": value,
1124         }, clfactory)
1125       self.assertRaises(http.HttpBadRequest, handler.PUT)
1126
1127
1128 class TestInstanceMigrate(testutils.GanetiTestCase):
1129   def test(self):
1130     clfactory = _FakeClientFactory(_FakeClient)
1131
1132     name = "instYooho6ek"
1133
1134     for cleanup in [False, True]:
1135       for mode in constants.HT_MIGRATION_MODES:
1136         data = {
1137           "cleanup": cleanup,
1138           "mode": mode,
1139           }
1140
1141         handler = _CreateHandler(rlib2.R_2_instances_name_migrate, [name], {},
1142                                  data, clfactory)
1143         job_id = handler.PUT()
1144
1145         cl = clfactory.GetNextClient()
1146         self.assertRaises(IndexError, clfactory.GetNextClient)
1147
1148         (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1149         self.assertEqual(job_id, exp_job_id)
1150         self.assertTrue(isinstance(op, opcodes.OpInstanceMigrate))
1151         self.assertEqual(op.instance_name, name)
1152         self.assertEqual(op.mode, mode)
1153         self.assertEqual(op.cleanup, cleanup)
1154         self.assertFalse(hasattr(op, "dry_run"))
1155         self.assertFalse(hasattr(op, "force"))
1156
1157         self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1158
1159   def testDefaults(self):
1160     clfactory = _FakeClientFactory(_FakeClient)
1161
1162     name = "instnohZeex0"
1163
1164     handler = _CreateHandler(rlib2.R_2_instances_name_migrate, [name], {}, {},
1165                              clfactory)
1166     job_id = handler.PUT()
1167
1168     cl = clfactory.GetNextClient()
1169     self.assertRaises(IndexError, clfactory.GetNextClient)
1170
1171     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1172     self.assertEqual(job_id, exp_job_id)
1173     self.assertTrue(isinstance(op, opcodes.OpInstanceMigrate))
1174     self.assertEqual(op.instance_name, name)
1175     self.assertFalse(hasattr(op, "mode"))
1176     self.assertFalse(hasattr(op, "cleanup"))
1177     self.assertFalse(hasattr(op, "dry_run"))
1178     self.assertFalse(hasattr(op, "force"))
1179
1180     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1181
1182
1183 class TestParseRenameInstanceRequest(testutils.GanetiTestCase):
1184   def test(self):
1185     clfactory = _FakeClientFactory(_FakeClient)
1186
1187     name = "instij0eeph7"
1188
1189     for new_name in ["ua0aiyoo", "fai3ongi"]:
1190       for ip_check in [False, True]:
1191         for name_check in [False, True]:
1192           data = {
1193             "new_name": new_name,
1194             "ip_check": ip_check,
1195             "name_check": name_check,
1196             }
1197
1198           handler = _CreateHandler(rlib2.R_2_instances_name_rename, [name],
1199                                    {}, data, clfactory)
1200           job_id = handler.PUT()
1201
1202           cl = clfactory.GetNextClient()
1203           self.assertRaises(IndexError, clfactory.GetNextClient)
1204
1205           (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1206           self.assertEqual(job_id, exp_job_id)
1207           self.assertTrue(isinstance(op, opcodes.OpInstanceRename))
1208           self.assertEqual(op.instance_name, name)
1209           self.assertEqual(op.new_name, new_name)
1210           self.assertEqual(op.ip_check, ip_check)
1211           self.assertEqual(op.name_check, name_check)
1212           self.assertFalse(hasattr(op, "dry_run"))
1213           self.assertFalse(hasattr(op, "force"))
1214
1215           self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1216
1217   def testDefaults(self):
1218     clfactory = _FakeClientFactory(_FakeClient)
1219
1220     name = "instahchie3t"
1221
1222     for new_name in ["thag9mek", "quees7oh"]:
1223       data = {
1224         "new_name": new_name,
1225         }
1226
1227       handler = _CreateHandler(rlib2.R_2_instances_name_rename, [name],
1228                                {}, data, clfactory)
1229       job_id = handler.PUT()
1230
1231       cl = clfactory.GetNextClient()
1232       self.assertRaises(IndexError, clfactory.GetNextClient)
1233
1234       (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1235       self.assertEqual(job_id, exp_job_id)
1236       self.assertTrue(isinstance(op, opcodes.OpInstanceRename))
1237       self.assertEqual(op.instance_name, name)
1238       self.assertEqual(op.new_name, new_name)
1239       self.assertFalse(hasattr(op, "ip_check"))
1240       self.assertFalse(hasattr(op, "name_check"))
1241       self.assertFalse(hasattr(op, "dry_run"))
1242       self.assertFalse(hasattr(op, "force"))
1243
1244       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1245
1246
1247 class TestParseModifyInstanceRequest(unittest.TestCase):
1248   def test(self):
1249     clfactory = _FakeClientFactory(_FakeClient)
1250
1251     name = "instush8gah"
1252
1253     test_disks = [
1254       [],
1255       [(1, { constants.IDISK_MODE: constants.DISK_RDWR, })],
1256       ]
1257
1258     for osparams in [{}, { "some": "value", "other": "Hello World", }]:
1259       for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]:
1260         for beparams in [{}, { constants.BE_MAXMEM: 128, }]:
1261           for force in [False, True]:
1262             for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]:
1263               for disks in test_disks:
1264                 for disk_template in constants.DISK_TEMPLATES:
1265                   data = {
1266                     "osparams": osparams,
1267                     "hvparams": hvparams,
1268                     "beparams": beparams,
1269                     "nics": nics,
1270                     "disks": disks,
1271                     "force": force,
1272                     "disk_template": disk_template,
1273                     }
1274
1275                   handler = _CreateHandler(rlib2.R_2_instances_name_modify,
1276                                            [name], {}, data, clfactory)
1277                   job_id = handler.PUT()
1278
1279                   cl = clfactory.GetNextClient()
1280                   self.assertRaises(IndexError, clfactory.GetNextClient)
1281
1282                   (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1283                   self.assertEqual(job_id, exp_job_id)
1284                   self.assertTrue(isinstance(op, opcodes.OpInstanceSetParams))
1285                   self.assertEqual(op.instance_name, name)
1286                   self.assertEqual(op.hvparams, hvparams)
1287                   self.assertEqual(op.beparams, beparams)
1288                   self.assertEqual(op.osparams, osparams)
1289                   self.assertEqual(op.force, force)
1290                   self.assertEqual(op.nics, nics)
1291                   self.assertEqual(op.disks, disks)
1292                   self.assertEqual(op.disk_template, disk_template)
1293                   self.assertFalse(hasattr(op, "remote_node"))
1294                   self.assertFalse(hasattr(op, "os_name"))
1295                   self.assertFalse(hasattr(op, "force_variant"))
1296                   self.assertFalse(hasattr(op, "dry_run"))
1297
1298                   self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1299
1300   def testDefaults(self):
1301     clfactory = _FakeClientFactory(_FakeClient)
1302
1303     name = "instir8aish31"
1304
1305     handler = _CreateHandler(rlib2.R_2_instances_name_modify,
1306                              [name], {}, {}, clfactory)
1307     job_id = handler.PUT()
1308
1309     cl = clfactory.GetNextClient()
1310     self.assertRaises(IndexError, clfactory.GetNextClient)
1311
1312     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1313     self.assertEqual(job_id, exp_job_id)
1314     self.assertTrue(isinstance(op, opcodes.OpInstanceSetParams))
1315     self.assertEqual(op.instance_name, name)
1316
1317     for i in ["hvparams", "beparams", "osparams", "force", "nics", "disks",
1318               "disk_template", "remote_node", "os_name", "force_variant"]:
1319       self.assertFalse(hasattr(op, i))
1320
1321
1322 class TestParseInstanceReinstallRequest(testutils.GanetiTestCase):
1323   def setUp(self):
1324     testutils.GanetiTestCase.setUp(self)
1325
1326     self.Parse = rlib2._ParseInstanceReinstallRequest
1327
1328   def _Check(self, ops, name):
1329     expcls = [
1330       opcodes.OpInstanceShutdown,
1331       opcodes.OpInstanceReinstall,
1332       opcodes.OpInstanceStartup,
1333       ]
1334
1335     self.assert_(compat.all(isinstance(op, exp)
1336                             for op, exp in zip(ops, expcls)))
1337     self.assert_(compat.all(op.instance_name == name for op in ops))
1338
1339   def test(self):
1340     name = "shoo0tihohma"
1341
1342     ops = self.Parse(name, {"os": "sys1", "start": True,})
1343     self.assertEqual(len(ops), 3)
1344     self._Check(ops, name)
1345     self.assertEqual(ops[1].os_type, "sys1")
1346     self.assertFalse(ops[1].osparams)
1347
1348     ops = self.Parse(name, {"os": "sys2", "start": False,})
1349     self.assertEqual(len(ops), 2)
1350     self._Check(ops, name)
1351     self.assertEqual(ops[1].os_type, "sys2")
1352
1353     osparams = {
1354       "reformat": "1",
1355       }
1356     ops = self.Parse(name, {"os": "sys4035", "start": True,
1357                             "osparams": osparams,})
1358     self.assertEqual(len(ops), 3)
1359     self._Check(ops, name)
1360     self.assertEqual(ops[1].os_type, "sys4035")
1361     self.assertEqual(ops[1].osparams, osparams)
1362
1363   def testDefaults(self):
1364     name = "noolee0g"
1365
1366     ops = self.Parse(name, {"os": "linux1"})
1367     self.assertEqual(len(ops), 3)
1368     self._Check(ops, name)
1369     self.assertEqual(ops[1].os_type, "linux1")
1370     self.assertFalse(ops[1].osparams)
1371
1372   def testErrors(self):
1373     self.assertRaises(http.HttpBadRequest, self.Parse,
1374                       "foo", "not a dictionary")
1375
1376
1377 class TestGroupRename(unittest.TestCase):
1378   def test(self):
1379     clfactory = _FakeClientFactory(_FakeClient)
1380
1381     name = "group608242564"
1382     data = {
1383       "new_name": "ua0aiyoo15112",
1384       }
1385
1386     handler = _CreateHandler(rlib2.R_2_groups_name_rename, [name], {}, data,
1387                              clfactory)
1388     job_id = handler.PUT()
1389
1390     cl = clfactory.GetNextClient()
1391     self.assertRaises(IndexError, clfactory.GetNextClient)
1392
1393     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1394     self.assertEqual(job_id, exp_job_id)
1395
1396     self.assertTrue(isinstance(op, opcodes.OpGroupRename))
1397     self.assertEqual(op.group_name, name)
1398     self.assertEqual(op.new_name, "ua0aiyoo15112")
1399     self.assertFalse(op.dry_run)
1400     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1401
1402   def testDryRun(self):
1403     clfactory = _FakeClientFactory(_FakeClient)
1404
1405     name = "group28548"
1406     data = {
1407       "new_name": "ua0aiyoo",
1408       }
1409
1410     handler = _CreateHandler(rlib2.R_2_groups_name_rename, [name], {
1411       "dry-run": ["1"],
1412       }, data, clfactory)
1413     job_id = handler.PUT()
1414
1415     cl = clfactory.GetNextClient()
1416     self.assertRaises(IndexError, clfactory.GetNextClient)
1417
1418     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1419     self.assertEqual(job_id, exp_job_id)
1420
1421     self.assertTrue(isinstance(op, opcodes.OpGroupRename))
1422     self.assertEqual(op.group_name, name)
1423     self.assertEqual(op.new_name, "ua0aiyoo")
1424     self.assertTrue(op.dry_run)
1425     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1426
1427
1428 class TestInstanceReplaceDisks(unittest.TestCase):
1429   def test(self):
1430     clfactory = _FakeClientFactory(_FakeClient)
1431
1432     name = "inst22568"
1433
1434     for disks in [range(1, 4), "1,2,3", "1, 2, 3"]:
1435       data = {
1436         "mode": constants.REPLACE_DISK_SEC,
1437         "disks": disks,
1438         "iallocator": "myalloc",
1439         }
1440
1441       handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
1442                                [name], {}, data, clfactory)
1443       job_id = handler.POST()
1444
1445       cl = clfactory.GetNextClient()
1446       self.assertRaises(IndexError, clfactory.GetNextClient)
1447
1448       (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1449       self.assertEqual(job_id, exp_job_id)
1450
1451       self.assertTrue(isinstance(op, opcodes.OpInstanceReplaceDisks))
1452       self.assertEqual(op.instance_name, name)
1453       self.assertEqual(op.mode, constants.REPLACE_DISK_SEC)
1454       self.assertEqual(op.disks, [1, 2, 3])
1455       self.assertEqual(op.iallocator, "myalloc")
1456       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1457
1458   def testDefaults(self):
1459     clfactory = _FakeClientFactory(_FakeClient)
1460
1461     name = "inst11413"
1462     data = {
1463       "mode": constants.REPLACE_DISK_AUTO,
1464       }
1465
1466     handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
1467                              [name], {}, data, clfactory)
1468     job_id = handler.POST()
1469
1470     cl = clfactory.GetNextClient()
1471     self.assertRaises(IndexError, clfactory.GetNextClient)
1472
1473     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1474     self.assertEqual(job_id, exp_job_id)
1475
1476     self.assertTrue(isinstance(op, opcodes.OpInstanceReplaceDisks))
1477     self.assertEqual(op.instance_name, name)
1478     self.assertEqual(op.mode, constants.REPLACE_DISK_AUTO)
1479     self.assertFalse(hasattr(op, "iallocator"))
1480     self.assertFalse(hasattr(op, "disks"))
1481     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1482
1483   def testNoDisks(self):
1484     clfactory = _FakeClientFactory(_FakeClient)
1485
1486     handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
1487                              ["inst20661"], {}, {}, clfactory)
1488     self.assertRaises(http.HttpBadRequest, handler.POST)
1489
1490     for disks in [None, "", {}]:
1491       handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
1492                                ["inst20661"], {}, {
1493         "disks": disks,
1494         }, clfactory)
1495       self.assertRaises(http.HttpBadRequest, handler.POST)
1496
1497   def testWrong(self):
1498     clfactory = _FakeClientFactory(_FakeClient)
1499
1500     data = {
1501       "mode": constants.REPLACE_DISK_AUTO,
1502       "disks": "hello world",
1503       }
1504
1505     handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
1506                              ["foo"], {}, data, clfactory)
1507     self.assertRaises(http.HttpBadRequest, handler.POST)
1508
1509
1510 class TestGroupModify(unittest.TestCase):
1511   def test(self):
1512     clfactory = _FakeClientFactory(_FakeClient)
1513
1514     name = "group6002"
1515
1516     for policy in constants.VALID_ALLOC_POLICIES:
1517       data = {
1518         "alloc_policy": policy,
1519         }
1520
1521       handler = _CreateHandler(rlib2.R_2_groups_name_modify, [name], {}, data,
1522                                clfactory)
1523       job_id = handler.PUT()
1524
1525       cl = clfactory.GetNextClient()
1526       self.assertRaises(IndexError, clfactory.GetNextClient)
1527
1528       (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1529       self.assertEqual(job_id, exp_job_id)
1530
1531       self.assertTrue(isinstance(op, opcodes.OpGroupSetParams))
1532       self.assertEqual(op.group_name, name)
1533       self.assertEqual(op.alloc_policy, policy)
1534       self.assertFalse(hasattr(op, "dry_run"))
1535       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1536
1537   def testUnknownPolicy(self):
1538     clfactory = _FakeClientFactory(_FakeClient)
1539
1540     data = {
1541       "alloc_policy": "_unknown_policy_",
1542       }
1543
1544     handler = _CreateHandler(rlib2.R_2_groups_name_modify, ["xyz"], {}, data,
1545                              clfactory)
1546     self.assertRaises(http.HttpBadRequest, handler.PUT)
1547     self.assertRaises(IndexError, clfactory.GetNextClient)
1548
1549   def testDefaults(self):
1550     clfactory = _FakeClientFactory(_FakeClient)
1551
1552     name = "group6679"
1553
1554     handler = _CreateHandler(rlib2.R_2_groups_name_modify, [name], {}, {},
1555                              clfactory)
1556     job_id = handler.PUT()
1557
1558     cl = clfactory.GetNextClient()
1559     self.assertRaises(IndexError, clfactory.GetNextClient)
1560
1561     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1562     self.assertEqual(job_id, exp_job_id)
1563
1564     self.assertTrue(isinstance(op, opcodes.OpGroupSetParams))
1565     self.assertEqual(op.group_name, name)
1566     self.assertFalse(hasattr(op, "alloc_policy"))
1567     self.assertFalse(hasattr(op, "dry_run"))
1568     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1569
1570
1571 class TestGroupAdd(unittest.TestCase):
1572   def test(self):
1573     name = "group3618"
1574     clfactory = _FakeClientFactory(_FakeClient)
1575
1576     for policy in constants.VALID_ALLOC_POLICIES:
1577       data = {
1578         "group_name": name,
1579         "alloc_policy": policy,
1580         }
1581
1582       handler = _CreateHandler(rlib2.R_2_groups, [], {}, data,
1583                                clfactory)
1584       job_id = handler.POST()
1585
1586       cl = clfactory.GetNextClient()
1587       self.assertRaises(IndexError, clfactory.GetNextClient)
1588
1589       (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1590       self.assertEqual(job_id, exp_job_id)
1591
1592       self.assertTrue(isinstance(op, opcodes.OpGroupAdd))
1593       self.assertEqual(op.group_name, name)
1594       self.assertEqual(op.alloc_policy, policy)
1595       self.assertFalse(op.dry_run)
1596       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1597
1598   def testUnknownPolicy(self):
1599     clfactory = _FakeClientFactory(_FakeClient)
1600
1601     data = {
1602       "alloc_policy": "_unknown_policy_",
1603       }
1604
1605     handler = _CreateHandler(rlib2.R_2_groups, [], {}, data, clfactory)
1606     self.assertRaises(http.HttpBadRequest, handler.POST)
1607     self.assertRaises(IndexError, clfactory.GetNextClient)
1608
1609   def testDefaults(self):
1610     clfactory = _FakeClientFactory(_FakeClient)
1611
1612     name = "group15395"
1613     data = {
1614       "group_name": name,
1615       }
1616
1617     handler = _CreateHandler(rlib2.R_2_groups, [], {}, data, clfactory)
1618     job_id = handler.POST()
1619
1620     cl = clfactory.GetNextClient()
1621     self.assertRaises(IndexError, clfactory.GetNextClient)
1622
1623     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1624     self.assertEqual(job_id, exp_job_id)
1625
1626     self.assertTrue(isinstance(op, opcodes.OpGroupAdd))
1627     self.assertEqual(op.group_name, name)
1628     self.assertFalse(hasattr(op, "alloc_policy"))
1629     self.assertFalse(op.dry_run)
1630
1631   def testLegacyName(self):
1632     clfactory = _FakeClientFactory(_FakeClient)
1633
1634     name = "group29852"
1635     data = {
1636       "name": name,
1637       }
1638
1639     handler = _CreateHandler(rlib2.R_2_groups, [], {
1640       "dry-run": ["1"],
1641       }, data, clfactory)
1642     job_id = handler.POST()
1643
1644     cl = clfactory.GetNextClient()
1645     self.assertRaises(IndexError, clfactory.GetNextClient)
1646
1647     (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1648     self.assertEqual(job_id, exp_job_id)
1649
1650     self.assertTrue(isinstance(op, opcodes.OpGroupAdd))
1651     self.assertEqual(op.group_name, name)
1652     self.assertFalse(hasattr(op, "alloc_policy"))
1653     self.assertTrue(op.dry_run)
1654
1655
1656 class TestNodeRole(unittest.TestCase):
1657   def test(self):
1658     clfactory = _FakeClientFactory(_FakeClient)
1659
1660     for role in rlib2._NR_MAP.values():
1661       handler = _CreateHandler(rlib2.R_2_nodes_name_role,
1662                                ["node-z"], {}, role, clfactory)
1663       if role == rlib2._NR_MASTER:
1664         self.assertRaises(http.HttpBadRequest, handler.PUT)
1665       else:
1666         job_id = handler.PUT()
1667
1668         cl = clfactory.GetNextClient()
1669         self.assertRaises(IndexError, clfactory.GetNextClient)
1670
1671         (exp_job_id, (op, )) = cl.GetNextSubmittedJob()
1672         self.assertEqual(job_id, exp_job_id)
1673         self.assertTrue(isinstance(op, opcodes.OpNodeSetParams))
1674         self.assertEqual(op.node_name, "node-z")
1675         self.assertFalse(op.force)
1676         self.assertFalse(hasattr(op, "dry_run"))
1677
1678         if role == rlib2._NR_REGULAR:
1679           self.assertFalse(op.drained)
1680           self.assertFalse(op.offline)
1681           self.assertFalse(op.master_candidate)
1682         elif role == rlib2._NR_MASTER_CANDIDATE:
1683           self.assertFalse(op.drained)
1684           self.assertFalse(op.offline)
1685           self.assertTrue(op.master_candidate)
1686         elif role == rlib2._NR_DRAINED:
1687           self.assertTrue(op.drained)
1688           self.assertFalse(op.offline)
1689           self.assertFalse(op.master_candidate)
1690         elif role == rlib2._NR_OFFLINE:
1691           self.assertFalse(op.drained)
1692           self.assertTrue(op.offline)
1693           self.assertFalse(op.master_candidate)
1694         else:
1695           self.fail("Unknown role '%s'" % role)
1696
1697       self.assertRaises(IndexError, cl.GetNextSubmittedJob)
1698
1699
1700 class TestSimpleResources(unittest.TestCase):
1701   def setUp(self):
1702     self.clfactory = _FakeClientFactory(_FakeClient)
1703
1704   def tearDown(self):
1705     self.assertRaises(IndexError, self.clfactory.GetNextClient)
1706
1707   def testFeatures(self):
1708     handler = _CreateHandler(rlib2.R_2_features, [], {}, None, self.clfactory)
1709     self.assertEqual(set(handler.GET()), rlib2.ALL_FEATURES)
1710
1711   def testEmpty(self):
1712     for cls in [rlib2.R_root, rlib2.R_2]:
1713       handler = _CreateHandler(cls, [], {}, None, self.clfactory)
1714       self.assertTrue(handler.GET() is None)
1715
1716   def testVersion(self):
1717     handler = _CreateHandler(rlib2.R_version, [], {}, None, self.clfactory)
1718     self.assertEqual(handler.GET(), constants.RAPI_VERSION)
1719
1720
1721 class TestClusterInfo(unittest.TestCase):
1722   class _ClusterInfoClient:
1723     def __init__(self, address=None):
1724       self.cluster_info = None
1725
1726     def QueryClusterInfo(self):
1727       assert self.cluster_info is None
1728       self.cluster_info = object()
1729       return self.cluster_info
1730
1731   def test(self):
1732     clfactory = _FakeClientFactory(self._ClusterInfoClient)
1733     handler = _CreateHandler(rlib2.R_2_info, [], {}, None, clfactory)
1734     result = handler.GET()
1735     cl = clfactory.GetNextClient()
1736     self.assertRaises(IndexError, clfactory.GetNextClient)
1737     self.assertEqual(result, cl.cluster_info)
1738
1739
1740 class TestInstancesMultiAlloc(unittest.TestCase):
1741   def testInstanceUpdate(self):
1742     clfactory = _FakeClientFactory(_FakeClient)
1743     data = {
1744       "instances": [{
1745         "instance_name": "bar",
1746         "mode": "create",
1747         }, {
1748         "instance_name": "foo",
1749         "mode": "create",
1750         }],
1751       }
1752     handler = _CreateHandler(rlib2.R_2_instances_multi_alloc, [], {}, data,
1753                              clfactory)
1754     (body, _) = handler.GetPostOpInput()
1755     self.assertTrue(compat.all([inst["OP_ID"] == handler.POST_OPCODE.OP_ID
1756                                 for inst in body["instances"]]))
1757
1758
1759 class TestPermissions(unittest.TestCase):
1760   def testEquality(self):
1761     self.assertEqual(rlib2.R_2_query.GET_ACCESS, rlib2.R_2_query.PUT_ACCESS)
1762     self.assertEqual(rlib2.R_2_query.GET_ACCESS,
1763                      rlib2.R_2_instances_name_console.GET_ACCESS)
1764
1765   def testMethodAccess(self):
1766     for handler in connector.CONNECTOR.values():
1767       for method in baserlib._SUPPORTED_METHODS:
1768         access = getattr(handler, "%s_ACCESS" % method)
1769         self.assertFalse(set(access) - rapi.RAPI_ACCESS_ALL,
1770                          msg=("Handler '%s' uses unknown access options for"
1771                               " method %s" % (handler, method)))
1772         self.assertTrue(rapi.RAPI_ACCESS_READ not in access or
1773                         rapi.RAPI_ACCESS_WRITE in access,
1774                         msg=("Handler '%s' gives query, but not write access"
1775                              " for method %s (the latter includes query and"
1776                              " should therefore be given as well)" %
1777                              (handler, method)))
1778
1779
1780 if __name__ == "__main__":
1781   testutils.GanetiTestProgram()