Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.rapi.rlib2_unittest.py @ 3b877f08

History | View | Annotate | Download (18 kB)

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

    
4
# Copyright (C) 2010 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

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

24
"""
25

    
26

    
27
import unittest
28
import tempfile
29

    
30
from ganeti import constants
31
from ganeti import opcodes
32
from ganeti import compat
33
from ganeti import http
34
from ganeti import query
35

    
36
from ganeti.rapi import rlib2
37

    
38
import testutils
39

    
40

    
41
class TestConstants(unittest.TestCase):
42
  def testConsole(self):
43
    # Exporting the console field without authentication might expose
44
    # information
45
    assert "console" in query.INSTANCE_FIELDS
46
    self.assertTrue("console" not in rlib2.I_FIELDS)
47

    
48

    
49
class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase):
50
  def setUp(self):
51
    testutils.GanetiTestCase.setUp(self)
52

    
53
    self.Parse = rlib2._ParseInstanceCreateRequestVersion1
54

    
55
  def test(self):
56
    disk_variants = [
57
      # No disks
58
      [],
59

    
60
      # Two disks
61
      [{"size": 5, }, {"size": 100, }],
62

    
63
      # Disk with mode
64
      [{"size": 123, "mode": constants.DISK_RDWR, }],
65
      ]
66

    
67
    nic_variants = [
68
      # No NIC
69
      [],
70

    
71
      # Three NICs
72
      [{}, {}, {}],
73

    
74
      # Two NICs
75
      [
76
        { "ip": "192.0.2.6", "mode": constants.NIC_MODE_ROUTED,
77
          "mac": "01:23:45:67:68:9A",
78
        },
79
        { "mode": constants.NIC_MODE_BRIDGED, "link": "br1" },
80
      ],
81
      ]
82

    
83
    beparam_variants = [
84
      None,
85
      {},
86
      { constants.BE_VCPUS: 2, },
87
      { constants.BE_MEMORY: 123, },
88
      { constants.BE_VCPUS: 2,
89
        constants.BE_MEMORY: 1024,
90
        constants.BE_AUTO_BALANCE: True, }
91
      ]
92

    
93
    hvparam_variants = [
94
      None,
95
      { constants.HV_BOOT_ORDER: "anc", },
96
      { constants.HV_KERNEL_PATH: "/boot/fookernel",
97
        constants.HV_ROOT_PATH: "/dev/hda1", },
98
      ]
99

    
100
    for mode in [constants.INSTANCE_CREATE, constants.INSTANCE_IMPORT]:
101
      for nics in nic_variants:
102
        for disk_template in constants.DISK_TEMPLATES:
103
          for disks in disk_variants:
104
            for beparams in beparam_variants:
105
              for hvparams in hvparam_variants:
106
                data = {
107
                  "name": "inst1.example.com",
108
                  "hypervisor": constants.HT_FAKE,
109
                  "disks": disks,
110
                  "nics": nics,
111
                  "mode": mode,
112
                  "disk_template": disk_template,
113
                  "os": "debootstrap",
114
                  }
115

    
116
                if beparams is not None:
117
                  data["beparams"] = beparams
118

    
119
                if hvparams is not None:
120
                  data["hvparams"] = hvparams
121

    
122
                for dry_run in [False, True]:
123
                  op = self.Parse(data, dry_run)
124
                  self.assert_(isinstance(op, opcodes.OpInstanceCreate))
125
                  self.assertEqual(op.mode, mode)
126
                  self.assertEqual(op.disk_template, disk_template)
127
                  self.assertEqual(op.dry_run, dry_run)
128
                  self.assertEqual(len(op.disks), len(disks))
129
                  self.assertEqual(len(op.nics), len(nics))
130

    
131
                  for opdisk, disk in zip(op.disks, disks):
132
                    for key in constants.IDISK_PARAMS:
133
                      self.assertEqual(opdisk.get(key), disk.get(key))
134
                    self.assertFalse("unknown" in opdisk)
135

    
136
                  for opnic, nic in zip(op.nics, nics):
137
                    for key in constants.INIC_PARAMS:
138
                      self.assertEqual(opnic.get(key), nic.get(key))
139
                    self.assertFalse("unknown" in opnic)
140
                    self.assertFalse("foobar" in opnic)
141

    
142
                  if beparams is None:
143
                    self.assertFalse(hasattr(op, "beparams"))
144
                  else:
145
                    self.assertEqualValues(op.beparams, beparams)
146

    
147
                  if hvparams is None:
148
                    self.assertFalse(hasattr(op, "hvparams"))
149
                  else:
150
                    self.assertEqualValues(op.hvparams, hvparams)
151

    
152
  def testLegacyName(self):
153
    name = "inst29128.example.com"
154
    data = {
155
      "name": name,
156
      "disks": [],
157
      "nics": [],
158
      "mode": constants.INSTANCE_CREATE,
159
      "disk_template": constants.DT_PLAIN,
160
      }
161
    op = self.Parse(data, False)
162
    self.assert_(isinstance(op, opcodes.OpInstanceCreate))
163
    self.assertEqual(op.instance_name, name)
164
    self.assertFalse(hasattr(op, "name"))
165

    
166
    # Define both
167
    data = {
168
      "name": name,
169
      "instance_name": "other.example.com",
170
      "disks": [],
171
      "nics": [],
172
      "mode": constants.INSTANCE_CREATE,
173
      "disk_template": constants.DT_PLAIN,
174
      }
175
    self.assertRaises(http.HttpBadRequest, self.Parse, data, False)
176

    
177
  def testLegacyOs(self):
178
    name = "inst4673.example.com"
179
    os = "linux29206"
180
    data = {
181
      "name": name,
182
      "os_type": os,
183
      "disks": [],
184
      "nics": [],
185
      "mode": constants.INSTANCE_CREATE,
186
      "disk_template": constants.DT_PLAIN,
187
      }
188
    op = self.Parse(data, False)
189
    self.assert_(isinstance(op, opcodes.OpInstanceCreate))
190
    self.assertEqual(op.instance_name, name)
191
    self.assertEqual(op.os_type, os)
192
    self.assertFalse(hasattr(op, "os"))
193

    
194
    # Define both
195
    data = {
196
      "instance_name": name,
197
      "os": os,
198
      "os_type": "linux9584",
199
      "disks": [],
200
      "nics": [],
201
      "mode": constants.INSTANCE_CREATE,
202
      "disk_template": constants.DT_PLAIN,
203
      }
204
    self.assertRaises(http.HttpBadRequest, self.Parse, data, False)
205

    
206
  def testErrors(self):
207
    # Test all required fields
208
    reqfields = {
209
      "name": "inst1.example.com",
210
      "disks": [],
211
      "nics": [],
212
      "mode": constants.INSTANCE_CREATE,
213
      "disk_template": constants.DT_PLAIN,
214
      }
215

    
216
    for name in reqfields.keys():
217
      self.assertRaises(http.HttpBadRequest, self.Parse,
218
                        dict(i for i in reqfields.iteritems() if i[0] != name),
219
                        False)
220

    
221
    # Invalid disks and nics
222
    for field in ["disks", "nics"]:
223
      invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"],
224
                        [{"_unknown_": 999, }]]
225

    
226
      for invvalue in invalid_values:
227
        data = reqfields.copy()
228
        data[field] = invvalue
229
        self.assertRaises(http.HttpBadRequest, self.Parse, data, False)
230

    
231

    
232
class TestParseExportInstanceRequest(testutils.GanetiTestCase):
233
  def setUp(self):
234
    testutils.GanetiTestCase.setUp(self)
235

    
236
    self.Parse = rlib2._ParseExportInstanceRequest
237

    
238
  def test(self):
239
    name = "instmoo"
240
    data = {
241
      "mode": constants.EXPORT_MODE_REMOTE,
242
      "destination": [(1, 2, 3), (99, 99, 99)],
243
      "shutdown": True,
244
      "remove_instance": True,
245
      "x509_key_name": ["name", "hash"],
246
      "destination_x509_ca": "---cert---"
247
      }
248
    op = self.Parse(name, data)
249
    self.assert_(isinstance(op, opcodes.OpBackupExport))
250
    self.assertEqual(op.instance_name, name)
251
    self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE)
252
    self.assertEqual(op.shutdown, True)
253
    self.assertEqual(op.remove_instance, True)
254
    self.assertEqualValues(op.x509_key_name, ("name", "hash"))
255
    self.assertEqual(op.destination_x509_ca, "---cert---")
256

    
257
  def testDefaults(self):
258
    name = "inst1"
259
    data = {
260
      "destination": "node2",
261
      "shutdown": False,
262
      }
263
    op = self.Parse(name, data)
264
    self.assert_(isinstance(op, opcodes.OpBackupExport))
265
    self.assertEqual(op.instance_name, name)
266
    self.assertEqual(op.target_node, "node2")
267
    self.assertFalse(hasattr(op, "mode"))
268
    self.assertFalse(hasattr(op, "remove_instance"))
269
    self.assertFalse(hasattr(op, "destination"))
270

    
271
  def testErrors(self):
272
    self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
273
                      { "remove_instance": "True", })
274
    self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
275
                      { "remove_instance": "False", })
276

    
277

    
278
class TestParseMigrateInstanceRequest(testutils.GanetiTestCase):
279
  def setUp(self):
280
    testutils.GanetiTestCase.setUp(self)
281

    
282
    self.Parse = rlib2._ParseMigrateInstanceRequest
283

    
284
  def test(self):
285
    name = "instYooho6ek"
286

    
287
    for cleanup in [False, True]:
288
      for mode in constants.HT_MIGRATION_MODES:
289
        data = {
290
          "cleanup": cleanup,
291
          "mode": mode,
292
          }
293
        op = self.Parse(name, data)
294
        self.assert_(isinstance(op, opcodes.OpInstanceMigrate))
295
        self.assertEqual(op.instance_name, name)
296
        self.assertEqual(op.mode, mode)
297
        self.assertEqual(op.cleanup, cleanup)
298

    
299
  def testDefaults(self):
300
    name = "instnohZeex0"
301

    
302
    op = self.Parse(name, {})
303
    self.assert_(isinstance(op, opcodes.OpInstanceMigrate))
304
    self.assertEqual(op.instance_name, name)
305
    self.assertFalse(hasattr(op, "mode"))
306
    self.assertFalse(hasattr(op, "cleanup"))
307

    
308

    
309
class TestParseRenameInstanceRequest(testutils.GanetiTestCase):
310
  def setUp(self):
311
    testutils.GanetiTestCase.setUp(self)
312

    
313
    self.Parse = rlib2._ParseRenameInstanceRequest
314

    
315
  def test(self):
316
    name = "instij0eeph7"
317

    
318
    for new_name in ["ua0aiyoo", "fai3ongi"]:
319
      for ip_check in [False, True]:
320
        for name_check in [False, True]:
321
          data = {
322
            "new_name": new_name,
323
            "ip_check": ip_check,
324
            "name_check": name_check,
325
            }
326

    
327
          op = self.Parse(name, data)
328
          self.assert_(isinstance(op, opcodes.OpInstanceRename))
329
          self.assertEqual(op.instance_name, name)
330
          self.assertEqual(op.new_name, new_name)
331
          self.assertEqual(op.ip_check, ip_check)
332
          self.assertEqual(op.name_check, name_check)
333

    
334
  def testDefaults(self):
335
    name = "instahchie3t"
336

    
337
    for new_name in ["thag9mek", "quees7oh"]:
338
      data = {
339
        "new_name": new_name,
340
        }
341

    
342
      op = self.Parse(name, data)
343
      self.assert_(isinstance(op, opcodes.OpInstanceRename))
344
      self.assertEqual(op.instance_name, name)
345
      self.assertEqual(op.new_name, new_name)
346
      self.assertFalse(hasattr(op, "ip_check"))
347
      self.assertFalse(hasattr(op, "name_check"))
348

    
349

    
350
class TestParseModifyInstanceRequest(testutils.GanetiTestCase):
351
  def setUp(self):
352
    testutils.GanetiTestCase.setUp(self)
353

    
354
    self.Parse = rlib2._ParseModifyInstanceRequest
355

    
356
  def test(self):
357
    name = "instush8gah"
358

    
359
    test_disks = [
360
      [],
361
      [(1, { constants.IDISK_MODE: constants.DISK_RDWR, })],
362
      ]
363

    
364
    for osparams in [{}, { "some": "value", "other": "Hello World", }]:
365
      for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]:
366
        for beparams in [{}, { constants.BE_MEMORY: 128, }]:
367
          for force in [False, True]:
368
            for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]:
369
              for disks in test_disks:
370
                for disk_template in constants.DISK_TEMPLATES:
371
                  data = {
372
                    "osparams": osparams,
373
                    "hvparams": hvparams,
374
                    "beparams": beparams,
375
                    "nics": nics,
376
                    "disks": disks,
377
                    "force": force,
378
                    "disk_template": disk_template,
379
                    }
380

    
381
                  op = self.Parse(name, data)
382
                  self.assert_(isinstance(op, opcodes.OpInstanceSetParams))
383
                  self.assertEqual(op.instance_name, name)
384
                  self.assertEqual(op.hvparams, hvparams)
385
                  self.assertEqual(op.beparams, beparams)
386
                  self.assertEqual(op.osparams, osparams)
387
                  self.assertEqual(op.force, force)
388
                  self.assertEqual(op.nics, nics)
389
                  self.assertEqual(op.disks, disks)
390
                  self.assertEqual(op.disk_template, disk_template)
391
                  self.assertFalse(hasattr(op, "remote_node"))
392
                  self.assertFalse(hasattr(op, "os_name"))
393
                  self.assertFalse(hasattr(op, "force_variant"))
394

    
395
  def testDefaults(self):
396
    name = "instir8aish31"
397

    
398
    op = self.Parse(name, {})
399
    self.assert_(isinstance(op, opcodes.OpInstanceSetParams))
400
    self.assertEqual(op.instance_name, name)
401
    for i in ["hvparams", "beparams", "osparams", "force", "nics", "disks",
402
              "disk_template", "remote_node", "os_name", "force_variant"]:
403
      self.assertFalse(hasattr(op, i))
404

    
405

    
406
class TestParseInstanceReinstallRequest(testutils.GanetiTestCase):
407
  def setUp(self):
408
    testutils.GanetiTestCase.setUp(self)
409

    
410
    self.Parse = rlib2._ParseInstanceReinstallRequest
411

    
412
  def _Check(self, ops, name):
413
    expcls = [
414
      opcodes.OpInstanceShutdown,
415
      opcodes.OpInstanceReinstall,
416
      opcodes.OpInstanceStartup,
417
      ]
418

    
419
    self.assert_(compat.all(isinstance(op, exp)
420
                            for op, exp in zip(ops, expcls)))
421
    self.assert_(compat.all(op.instance_name == name for op in ops))
422

    
423
  def test(self):
424
    name = "shoo0tihohma"
425

    
426
    ops = self.Parse(name, {"os": "sys1", "start": True,})
427
    self.assertEqual(len(ops), 3)
428
    self._Check(ops, name)
429
    self.assertEqual(ops[1].os_type, "sys1")
430
    self.assertFalse(ops[1].osparams)
431

    
432
    ops = self.Parse(name, {"os": "sys2", "start": False,})
433
    self.assertEqual(len(ops), 2)
434
    self._Check(ops, name)
435
    self.assertEqual(ops[1].os_type, "sys2")
436

    
437
    osparams = {
438
      "reformat": "1",
439
      }
440
    ops = self.Parse(name, {"os": "sys4035", "start": True,
441
                            "osparams": osparams,})
442
    self.assertEqual(len(ops), 3)
443
    self._Check(ops, name)
444
    self.assertEqual(ops[1].os_type, "sys4035")
445
    self.assertEqual(ops[1].osparams, osparams)
446

    
447
  def testDefaults(self):
448
    name = "noolee0g"
449

    
450
    ops = self.Parse(name, {"os": "linux1"})
451
    self.assertEqual(len(ops), 3)
452
    self._Check(ops, name)
453
    self.assertEqual(ops[1].os_type, "linux1")
454
    self.assertFalse(ops[1].osparams)
455

    
456

    
457
class TestParseRenameGroupRequest(testutils.GanetiTestCase):
458
  def setUp(self):
459
    testutils.GanetiTestCase.setUp(self)
460

    
461
    self.Parse = rlib2._ParseRenameGroupRequest
462

    
463
  def test(self):
464
    name = "instij0eeph7"
465
    data = {
466
      "new_name": "ua0aiyoo",
467
      }
468

    
469
    op = self.Parse(name, data, False)
470

    
471
    self.assert_(isinstance(op, opcodes.OpGroupRename))
472
    self.assertEqual(op.group_name, name)
473
    self.assertEqual(op.new_name, "ua0aiyoo")
474
    self.assertFalse(op.dry_run)
475

    
476
  def testDryRun(self):
477
    name = "instij0eeph7"
478
    data = {
479
      "new_name": "ua0aiyoo",
480
      }
481

    
482
    op = self.Parse(name, data, True)
483

    
484
    self.assert_(isinstance(op, opcodes.OpGroupRename))
485
    self.assertEqual(op.group_name, name)
486
    self.assertEqual(op.new_name, "ua0aiyoo")
487
    self.assert_(op.dry_run)
488

    
489

    
490
class TestParseInstanceReplaceDisksRequest(unittest.TestCase):
491
  def setUp(self):
492
    self.Parse = rlib2._ParseInstanceReplaceDisksRequest
493

    
494
  def test(self):
495
    name = "inst22568"
496

    
497
    for disks in [range(1, 4), "1,2,3", "1, 2, 3"]:
498
      data = {
499
        "mode": constants.REPLACE_DISK_SEC,
500
        "disks": disks,
501
        "iallocator": "myalloc",
502
        }
503

    
504
      op = self.Parse(name, data)
505
      self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks))
506
      self.assertEqual(op.mode, constants.REPLACE_DISK_SEC)
507
      self.assertEqual(op.disks, [1, 2, 3])
508
      self.assertEqual(op.iallocator, "myalloc")
509

    
510
  def testDefaults(self):
511
    name = "inst11413"
512
    data = {
513
      "mode": constants.REPLACE_DISK_AUTO,
514
      }
515

    
516
    op = self.Parse(name, data)
517
    self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks))
518
    self.assertEqual(op.mode, constants.REPLACE_DISK_AUTO)
519
    self.assertFalse(hasattr(op, "iallocator"))
520
    self.assertFalse(hasattr(op, "disks"))
521

    
522
  def testWrong(self):
523
    self.assertRaises(http.HttpBadRequest, self.Parse, "inst",
524
                      { "mode": constants.REPLACE_DISK_AUTO,
525
                        "disks": "hello world",
526
                      })
527

    
528

    
529
class TestParseModifyGroupRequest(unittest.TestCase):
530
  def setUp(self):
531
    self.Parse = rlib2._ParseModifyGroupRequest
532

    
533
  def test(self):
534
    name = "group6002"
535

    
536
    for policy in constants.VALID_ALLOC_POLICIES:
537
      data = {
538
        "alloc_policy": policy,
539
        }
540

    
541
      op = self.Parse(name, data)
542
      self.assert_(isinstance(op, opcodes.OpGroupSetParams))
543
      self.assertEqual(op.group_name, name)
544
      self.assertEqual(op.alloc_policy, policy)
545

    
546
  def testUnknownPolicy(self):
547
    data = {
548
      "alloc_policy": "_unknown_policy_",
549
      }
550

    
551
    self.assertRaises(http.HttpBadRequest, self.Parse, "name", data)
552

    
553
  def testDefaults(self):
554
    name = "group6679"
555
    data = {}
556

    
557
    op = self.Parse(name, data)
558
    self.assert_(isinstance(op, opcodes.OpGroupSetParams))
559
    self.assertEqual(op.group_name, name)
560
    self.assertFalse(hasattr(op, "alloc_policy"))
561

    
562

    
563
class TestParseCreateGroupRequest(unittest.TestCase):
564
  def setUp(self):
565
    self.Parse = rlib2._ParseCreateGroupRequest
566

    
567
  def test(self):
568
    name = "group3618"
569

    
570
    for policy in constants.VALID_ALLOC_POLICIES:
571
      data = {
572
        "group_name": name,
573
        "alloc_policy": policy,
574
        }
575

    
576
      op = self.Parse(data, False)
577
      self.assert_(isinstance(op, opcodes.OpGroupAdd))
578
      self.assertEqual(op.group_name, name)
579
      self.assertEqual(op.alloc_policy, policy)
580
      self.assertFalse(op.dry_run)
581

    
582
  def testUnknownPolicy(self):
583
    data = {
584
      "alloc_policy": "_unknown_policy_",
585
      }
586

    
587
    self.assertRaises(http.HttpBadRequest, self.Parse, "name", data)
588

    
589
  def testDefaults(self):
590
    name = "group15395"
591
    data = {
592
      "group_name": name,
593
      }
594

    
595
    op = self.Parse(data, True)
596
    self.assert_(isinstance(op, opcodes.OpGroupAdd))
597
    self.assertEqual(op.group_name, name)
598
    self.assertFalse(hasattr(op, "alloc_policy"))
599
    self.assertTrue(op.dry_run)
600

    
601
  def testLegacyName(self):
602
    name = "group29852"
603
    data = {
604
      "name": name,
605
      }
606

    
607
    op = self.Parse(data, True)
608
    self.assert_(isinstance(op, opcodes.OpGroupAdd))
609
    self.assertEqual(op.group_name, name)
610

    
611

    
612
if __name__ == '__main__':
613
  testutils.GanetiTestProgram()