Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.rapi.rlib2_unittest.py @ b82d4c5e

History | View | Annotate | Download (13.7 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
      # With unknown setting
67
      [{"size": 123, "unknown": 999 }],
68
      ]
69

    
70
    nic_variants = [
71
      # No NIC
72
      [],
73

    
74
      # Three NICs
75
      [{}, {}, {}],
76

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

    
85
      # Unknown settings
86
      [{ "unknown": 999, }, { "foobar": "Hello World", }],
87
      ]
88

    
89
    beparam_variants = [
90
      None,
91
      {},
92
      { constants.BE_VCPUS: 2, },
93
      { constants.BE_MEMORY: 123, },
94
      { constants.BE_VCPUS: 2,
95
        constants.BE_MEMORY: 1024,
96
        constants.BE_AUTO_BALANCE: True, }
97
      ]
98

    
99
    hvparam_variants = [
100
      None,
101
      { constants.HV_BOOT_ORDER: "anc", },
102
      { constants.HV_KERNEL_PATH: "/boot/fookernel",
103
        constants.HV_ROOT_PATH: "/dev/hda1", },
104
      ]
105

    
106
    for mode in [constants.INSTANCE_CREATE, constants.INSTANCE_IMPORT]:
107
      for nics in nic_variants:
108
        for disk_template in constants.DISK_TEMPLATES:
109
          for disks in disk_variants:
110
            for beparams in beparam_variants:
111
              for hvparams in hvparam_variants:
112
                data = {
113
                  "name": "inst1.example.com",
114
                  "hypervisor": constants.HT_FAKE,
115
                  "disks": disks,
116
                  "nics": nics,
117
                  "mode": mode,
118
                  "disk_template": disk_template,
119
                  "os": "debootstrap",
120
                  }
121

    
122
                if beparams is not None:
123
                  data["beparams"] = beparams
124

    
125
                if hvparams is not None:
126
                  data["hvparams"] = hvparams
127

    
128
                for dry_run in [False, True]:
129
                  op = self.Parse(data, dry_run)
130
                  self.assert_(isinstance(op, opcodes.OpInstanceCreate))
131
                  self.assertEqual(op.mode, mode)
132
                  self.assertEqual(op.disk_template, disk_template)
133
                  self.assertEqual(op.dry_run, dry_run)
134
                  self.assertEqual(len(op.disks), len(disks))
135
                  self.assertEqual(len(op.nics), len(nics))
136

    
137
                  for opdisk, disk in zip(op.disks, disks):
138
                    for key in constants.IDISK_PARAMS:
139
                      self.assertEqual(opdisk.get(key), disk.get(key))
140
                    self.assertFalse("unknown" in opdisk)
141

    
142
                  for opnic, nic in zip(op.nics, nics):
143
                    for key in constants.INIC_PARAMS:
144
                      self.assertEqual(opnic.get(key), nic.get(key))
145
                    self.assertFalse("unknown" in opnic)
146
                    self.assertFalse("foobar" in opnic)
147

    
148
                  if beparams is None:
149
                    self.assertEqualValues(op.beparams, {})
150
                  else:
151
                    self.assertEqualValues(op.beparams, beparams)
152

    
153
                  if hvparams is None:
154
                    self.assertEqualValues(op.hvparams, {})
155
                  else:
156
                    self.assertEqualValues(op.hvparams, hvparams)
157

    
158
  def testErrors(self):
159
    # Test all required fields
160
    reqfields = {
161
      "name": "inst1.example.com",
162
      "disks": [],
163
      "nics": [],
164
      "mode": constants.INSTANCE_CREATE,
165
      "disk_template": constants.DT_PLAIN,
166
      "os": "debootstrap",
167
      }
168

    
169
    for name in reqfields.keys():
170
      self.assertRaises(http.HttpBadRequest, self.Parse,
171
                        dict(i for i in reqfields.iteritems() if i[0] != name),
172
                        False)
173

    
174
    # Invalid disks and nics
175
    for field in ["disks", "nics"]:
176
      invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"]]
177

    
178
      if field == "disks":
179
        invalid_values.append([
180
          # Disks without size
181
          {},
182
          { "mode": constants.DISK_RDWR, },
183
          ])
184

    
185
      for invvalue in invalid_values:
186
        data = reqfields.copy()
187
        data[field] = invvalue
188
        self.assertRaises(http.HttpBadRequest, self.Parse, data, False)
189

    
190

    
191
class TestParseExportInstanceRequest(testutils.GanetiTestCase):
192
  def setUp(self):
193
    testutils.GanetiTestCase.setUp(self)
194

    
195
    self.Parse = rlib2._ParseExportInstanceRequest
196

    
197
  def test(self):
198
    name = "instmoo"
199
    data = {
200
      "mode": constants.EXPORT_MODE_REMOTE,
201
      "destination": [(1, 2, 3), (99, 99, 99)],
202
      "shutdown": True,
203
      "remove_instance": True,
204
      "x509_key_name": ("name", "hash"),
205
      "destination_x509_ca": ("x", "y", "z"),
206
      }
207
    op = self.Parse(name, data)
208
    self.assert_(isinstance(op, opcodes.OpBackupExport))
209
    self.assertEqual(op.instance_name, name)
210
    self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE)
211
    self.assertEqual(op.shutdown, True)
212
    self.assertEqual(op.remove_instance, True)
213
    self.assertEqualValues(op.x509_key_name, ("name", "hash"))
214
    self.assertEqualValues(op.destination_x509_ca, ("x", "y", "z"))
215

    
216
  def testDefaults(self):
217
    name = "inst1"
218
    data = {
219
      "destination": "node2",
220
      "shutdown": False,
221
      }
222
    op = self.Parse(name, data)
223
    self.assert_(isinstance(op, opcodes.OpBackupExport))
224
    self.assertEqual(op.instance_name, name)
225
    self.assertEqual(op.mode, constants.EXPORT_MODE_LOCAL)
226
    self.assertEqual(op.remove_instance, False)
227

    
228
  def testErrors(self):
229
    self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
230
                      { "remove_instance": "True", })
231
    self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
232
                      { "remove_instance": "False", })
233

    
234

    
235
class TestParseMigrateInstanceRequest(testutils.GanetiTestCase):
236
  def setUp(self):
237
    testutils.GanetiTestCase.setUp(self)
238

    
239
    self.Parse = rlib2._ParseMigrateInstanceRequest
240

    
241
  def test(self):
242
    name = "instYooho6ek"
243

    
244
    for cleanup in [False, True]:
245
      for mode in constants.HT_MIGRATION_MODES:
246
        data = {
247
          "cleanup": cleanup,
248
          "mode": mode,
249
          }
250
        op = self.Parse(name, data)
251
        self.assert_(isinstance(op, opcodes.OpInstanceMigrate))
252
        self.assertEqual(op.instance_name, name)
253
        self.assertEqual(op.mode, mode)
254
        self.assertEqual(op.cleanup, cleanup)
255

    
256
  def testDefaults(self):
257
    name = "instnohZeex0"
258

    
259
    op = self.Parse(name, {})
260
    self.assert_(isinstance(op, opcodes.OpInstanceMigrate))
261
    self.assertEqual(op.instance_name, name)
262
    self.assertEqual(op.mode, None)
263
    self.assertFalse(op.cleanup)
264

    
265

    
266
class TestParseRenameInstanceRequest(testutils.GanetiTestCase):
267
  def setUp(self):
268
    testutils.GanetiTestCase.setUp(self)
269

    
270
    self.Parse = rlib2._ParseRenameInstanceRequest
271

    
272
  def test(self):
273
    name = "instij0eeph7"
274

    
275
    for new_name in ["ua0aiyoo", "fai3ongi"]:
276
      for ip_check in [False, True]:
277
        for name_check in [False, True]:
278
          data = {
279
            "new_name": new_name,
280
            "ip_check": ip_check,
281
            "name_check": name_check,
282
            }
283

    
284
          op = self.Parse(name, data)
285
          self.assert_(isinstance(op, opcodes.OpInstanceRename))
286
          self.assertEqual(op.instance_name, name)
287
          self.assertEqual(op.new_name, new_name)
288
          self.assertEqual(op.ip_check, ip_check)
289
          self.assertEqual(op.name_check, name_check)
290

    
291
  def testDefaults(self):
292
    name = "instahchie3t"
293

    
294
    for new_name in ["thag9mek", "quees7oh"]:
295
      data = {
296
        "new_name": new_name,
297
        }
298

    
299
      op = self.Parse(name, data)
300
      self.assert_(isinstance(op, opcodes.OpInstanceRename))
301
      self.assertEqual(op.instance_name, name)
302
      self.assertEqual(op.new_name, new_name)
303
      self.assert_(op.ip_check)
304
      self.assert_(op.name_check)
305

    
306

    
307
class TestParseModifyInstanceRequest(testutils.GanetiTestCase):
308
  def setUp(self):
309
    testutils.GanetiTestCase.setUp(self)
310

    
311
    self.Parse = rlib2._ParseModifyInstanceRequest
312

    
313
  def test(self):
314
    name = "instush8gah"
315

    
316
    test_disks = [
317
      [],
318
      [(1, { constants.IDISK_MODE: constants.DISK_RDWR, })],
319
      ]
320

    
321
    for osparams in [{}, { "some": "value", "other": "Hello World", }]:
322
      for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]:
323
        for beparams in [{}, { constants.BE_MEMORY: 128, }]:
324
          for force in [False, True]:
325
            for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]:
326
              for disks in test_disks:
327
                for disk_template in constants.DISK_TEMPLATES:
328
                  data = {
329
                    "osparams": osparams,
330
                    "hvparams": hvparams,
331
                    "beparams": beparams,
332
                    "nics": nics,
333
                    "disks": disks,
334
                    "force": force,
335
                    "disk_template": disk_template,
336
                    }
337

    
338
                  op = self.Parse(name, data)
339
                  self.assert_(isinstance(op, opcodes.OpInstanceSetParams))
340
                  self.assertEqual(op.instance_name, name)
341
                  self.assertEqual(op.hvparams, hvparams)
342
                  self.assertEqual(op.beparams, beparams)
343
                  self.assertEqual(op.osparams, osparams)
344
                  self.assertEqual(op.force, force)
345
                  self.assertEqual(op.nics, nics)
346
                  self.assertEqual(op.disks, disks)
347
                  self.assertEqual(op.disk_template, disk_template)
348
                  self.assert_(op.remote_node is None)
349
                  self.assert_(op.os_name is None)
350
                  self.assertFalse(op.force_variant)
351

    
352
  def testDefaults(self):
353
    name = "instir8aish31"
354

    
355
    op = self.Parse(name, {})
356
    self.assert_(isinstance(op, opcodes.OpInstanceSetParams))
357
    self.assertEqual(op.instance_name, name)
358
    self.assertEqual(op.hvparams, {})
359
    self.assertEqual(op.beparams, {})
360
    self.assertEqual(op.osparams, {})
361
    self.assertFalse(op.force)
362
    self.assertEqual(op.nics, [])
363
    self.assertEqual(op.disks, [])
364
    self.assert_(op.disk_template is None)
365
    self.assert_(op.remote_node is None)
366
    self.assert_(op.os_name is None)
367
    self.assertFalse(op.force_variant)
368

    
369

    
370
class TestParseInstanceReinstallRequest(testutils.GanetiTestCase):
371
  def setUp(self):
372
    testutils.GanetiTestCase.setUp(self)
373

    
374
    self.Parse = rlib2._ParseInstanceReinstallRequest
375

    
376
  def _Check(self, ops, name):
377
    expcls = [
378
      opcodes.OpInstanceShutdown,
379
      opcodes.OpInstanceReinstall,
380
      opcodes.OpInstanceStartup,
381
      ]
382

    
383
    self.assert_(compat.all(isinstance(op, exp)
384
                            for op, exp in zip(ops, expcls)))
385
    self.assert_(compat.all(op.instance_name == name for op in ops))
386

    
387
  def test(self):
388
    name = "shoo0tihohma"
389

    
390
    ops = self.Parse(name, {"os": "sys1", "start": True,})
391
    self.assertEqual(len(ops), 3)
392
    self._Check(ops, name)
393
    self.assertEqual(ops[1].os_type, "sys1")
394
    self.assertFalse(ops[1].osparams)
395

    
396
    ops = self.Parse(name, {"os": "sys2", "start": False,})
397
    self.assertEqual(len(ops), 2)
398
    self._Check(ops, name)
399
    self.assertEqual(ops[1].os_type, "sys2")
400

    
401
    osparams = {
402
      "reformat": "1",
403
      }
404
    ops = self.Parse(name, {"os": "sys4035", "start": True,
405
                            "osparams": osparams,})
406
    self.assertEqual(len(ops), 3)
407
    self._Check(ops, name)
408
    self.assertEqual(ops[1].os_type, "sys4035")
409
    self.assertEqual(ops[1].osparams, osparams)
410

    
411
  def testDefaults(self):
412
    name = "noolee0g"
413

    
414
    ops = self.Parse(name, {"os": "linux1"})
415
    self.assertEqual(len(ops), 3)
416
    self._Check(ops, name)
417
    self.assertEqual(ops[1].os_type, "linux1")
418
    self.assertFalse(ops[1].osparams)
419

    
420

    
421
class TestParseRenameGroupRequest(testutils.GanetiTestCase):
422
  def setUp(self):
423
    testutils.GanetiTestCase.setUp(self)
424

    
425
    self.Parse = rlib2._ParseRenameGroupRequest
426

    
427
  def test(self):
428
    name = "instij0eeph7"
429
    data = {
430
      "new_name": "ua0aiyoo",
431
      }
432

    
433
    op = self.Parse(name, data, False)
434

    
435
    self.assert_(isinstance(op, opcodes.OpGroupRename))
436
    self.assertEqual(op.old_name, name)
437
    self.assertEqual(op.new_name, "ua0aiyoo")
438
    self.assertFalse(op.dry_run)
439

    
440
  def testDryRun(self):
441
    name = "instij0eeph7"
442
    data = {
443
      "new_name": "ua0aiyoo",
444
      }
445

    
446
    op = self.Parse(name, data, True)
447

    
448
    self.assert_(isinstance(op, opcodes.OpGroupRename))
449
    self.assertEqual(op.old_name, name)
450
    self.assertEqual(op.new_name, "ua0aiyoo")
451
    self.assert_(op.dry_run)
452

    
453

    
454
if __name__ == '__main__':
455
  testutils.GanetiTestProgram()