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