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