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