Change the meaning of call_node_start_master
[ganeti-local] / test / ganeti.rapi.rlib2_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2010 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Script for unittesting the RAPI rlib2 module
23
24 """
25
26
27 import unittest
28 import tempfile
29
30 from ganeti import constants
31 from ganeti import opcodes
32 from ganeti import compat
33 from ganeti import http
34
35 from ganeti.rapi import rlib2
36
37 import testutils
38
39
40 class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase):
41   def setUp(self):
42     testutils.GanetiTestCase.setUp(self)
43
44     self.Parse = rlib2._ParseInstanceCreateRequestVersion1
45
46   def test(self):
47     disk_variants = [
48       # No disks
49       [],
50
51       # Two disks
52       [{"size": 5, }, {"size": 100, }],
53
54       # Disk with mode
55       [{"size": 123, "mode": constants.DISK_RDWR, }],
56
57       # With unknown setting
58       [{"size": 123, "unknown": 999 }],
59       ]
60
61     nic_variants = [
62       # No NIC
63       [],
64
65       # Three NICs
66       [{}, {}, {}],
67
68       # Two NICs
69       [
70         { "ip": "192.0.2.6", "mode": constants.NIC_MODE_ROUTED,
71           "mac": "01:23:45:67:68:9A",
72         },
73         { "mode": constants.NIC_MODE_BRIDGED, "link": "n0", "bridge": "br1", },
74       ],
75
76       # Unknown settings
77       [{ "unknown": 999, }, { "foobar": "Hello World", }],
78       ]
79
80     beparam_variants = [
81       None,
82       {},
83       { constants.BE_VCPUS: 2, },
84       { constants.BE_MEMORY: 123, },
85       { constants.BE_VCPUS: 2,
86         constants.BE_MEMORY: 1024,
87         constants.BE_AUTO_BALANCE: True, }
88       ]
89
90     hvparam_variants = [
91       None,
92       { constants.HV_BOOT_ORDER: "anc", },
93       { constants.HV_KERNEL_PATH: "/boot/fookernel",
94         constants.HV_ROOT_PATH: "/dev/hda1", },
95       ]
96
97     for mode in [constants.INSTANCE_CREATE, constants.INSTANCE_IMPORT]:
98       for nics in nic_variants:
99         for disk_template in constants.DISK_TEMPLATES:
100           for disks in disk_variants:
101             for beparams in beparam_variants:
102               for hvparams in hvparam_variants:
103                 data = {
104                   "name": "inst1.example.com",
105                   "hypervisor": constants.HT_FAKE,
106                   "disks": disks,
107                   "nics": nics,
108                   "mode": mode,
109                   "disk_template": disk_template,
110                   }
111
112                 if beparams is not None:
113                   data["beparams"] = beparams
114
115                 if hvparams is not None:
116                   data["hvparams"] = hvparams
117
118                 for dry_run in [False, True]:
119                   op = self.Parse(data, dry_run)
120                   self.assert_(isinstance(op, opcodes.OpCreateInstance))
121                   self.assertEqual(op.mode, mode)
122                   self.assertEqual(op.disk_template, disk_template)
123                   self.assertEqual(op.dry_run, dry_run)
124                   self.assertEqual(len(op.disks), len(disks))
125                   self.assertEqual(len(op.nics), len(nics))
126
127                   for opdisk, disk in zip(op.disks, disks):
128                     for key in constants.IDISK_PARAMS:
129                       self.assertEqual(opdisk.get(key), disk.get(key))
130                     self.assertFalse("unknown" in opdisk)
131
132                   for opnic, nic in zip(op.nics, nics):
133                     for key in constants.INIC_PARAMS:
134                       self.assertEqual(opnic.get(key), nic.get(key))
135                     self.assertFalse("unknown" in opnic)
136                     self.assertFalse("foobar" in opnic)
137
138                   if beparams is None:
139                     self.assertEqualValues(op.beparams, {})
140                   else:
141                     self.assertEqualValues(op.beparams, beparams)
142
143                   if hvparams is None:
144                     self.assertEqualValues(op.hvparams, {})
145                   else:
146                     self.assertEqualValues(op.hvparams, hvparams)
147
148   def testErrors(self):
149     # Test all required fields
150     reqfields = {
151       "name": "inst1.example.com",
152       "disks": [],
153       "nics": [],
154       "mode": constants.INSTANCE_CREATE,
155       "disk_template": constants.DT_PLAIN
156       }
157
158     for name in reqfields.keys():
159       self.assertRaises(http.HttpBadRequest, self.Parse,
160                         dict(i for i in reqfields.iteritems() if i[0] != name),
161                         False)
162
163     # Invalid disks and nics
164     for field in ["disks", "nics"]:
165       invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"]]
166
167       if field == "disks":
168         invalid_values.append([
169           # Disks without size
170           {},
171           { "mode": constants.DISK_RDWR, },
172           ])
173
174       for invvalue in invalid_values:
175         data = reqfields.copy()
176         data[field] = invvalue
177         self.assertRaises(http.HttpBadRequest, self.Parse, data, False)
178
179
180 class TestParseExportInstanceRequest(testutils.GanetiTestCase):
181   def setUp(self):
182     testutils.GanetiTestCase.setUp(self)
183
184     self.Parse = rlib2._ParseExportInstanceRequest
185
186   def test(self):
187     name = "instmoo"
188     data = {
189       "mode": constants.EXPORT_MODE_REMOTE,
190       "destination": [(1, 2, 3), (99, 99, 99)],
191       "shutdown": True,
192       "remove_instance": True,
193       "x509_key_name": ("name", "hash"),
194       "destination_x509_ca": ("x", "y", "z"),
195       }
196     op = self.Parse(name, data)
197     self.assert_(isinstance(op, opcodes.OpExportInstance))
198     self.assertEqual(op.instance_name, name)
199     self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE)
200     self.assertEqual(op.shutdown, True)
201     self.assertEqual(op.remove_instance, True)
202     self.assertEqualValues(op.x509_key_name, ("name", "hash"))
203     self.assertEqualValues(op.destination_x509_ca, ("x", "y", "z"))
204
205   def testDefaults(self):
206     name = "inst1"
207     data = {
208       "destination": "node2",
209       "shutdown": False,
210       }
211     op = self.Parse(name, data)
212     self.assert_(isinstance(op, opcodes.OpExportInstance))
213     self.assertEqual(op.instance_name, name)
214     self.assertEqual(op.mode, constants.EXPORT_MODE_LOCAL)
215     self.assertEqual(op.remove_instance, False)
216
217   def testErrors(self):
218     self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
219                       { "remove_instance": "True", })
220     self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
221                       { "remove_instance": "False", })
222
223
224 if __name__ == '__main__':
225   testutils.GanetiTestProgram()