Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.objects_unittest.py @ 8e8cf324

History | View | Annotate | Download (30 kB)

1 4c14965f Guido Trotter
#!/usr/bin/python
2 4c14965f Guido Trotter
#
3 4c14965f Guido Trotter
4 da5f09ef Bernardo Dal Seno
# Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Google Inc.
5 4c14965f Guido Trotter
#
6 4c14965f Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 4c14965f Guido Trotter
# it under the terms of the GNU General Public License as published by
8 4c14965f Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 4c14965f Guido Trotter
# (at your option) any later version.
10 4c14965f Guido Trotter
#
11 4c14965f Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 4c14965f Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 4c14965f Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4c14965f Guido Trotter
# General Public License for more details.
15 4c14965f Guido Trotter
#
16 4c14965f Guido Trotter
# You should have received a copy of the GNU General Public License
17 4c14965f Guido Trotter
# along with this program; if not, write to the Free Software
18 4c14965f Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 fd7b69c0 Michael Hanselmann
# 02110-1301, USA.
20 4c14965f Guido Trotter
21 4c14965f Guido Trotter
22 4c14965f Guido Trotter
"""Script for unittesting the objects module"""
23 4c14965f Guido Trotter
24 4c14965f Guido Trotter
25 41044e04 Bernardo Dal Seno
import copy
26 285ece5b Santi Raffa
import pprint
27 4c14965f Guido Trotter
import unittest
28 4c14965f Guido Trotter
29 7b64b9ea René Nussbaumer
from ganeti import constants
30 4c14965f Guido Trotter
from ganeti import objects
31 6a050007 Michael Hanselmann
from ganeti import errors
32 285ece5b Santi Raffa
from ganeti import serializer
33 4c14965f Guido Trotter
34 25231ec5 Michael Hanselmann
import testutils
35 25231ec5 Michael Hanselmann
36 25231ec5 Michael Hanselmann
37 4c14965f Guido Trotter
class SimpleObject(objects.ConfigObject):
38 8c114acd Michael Hanselmann
  __slots__ = ["a", "b"]
39 4c14965f Guido Trotter
40 25231ec5 Michael Hanselmann
41 4c14965f Guido Trotter
class TestDictState(unittest.TestCase):
42 4c14965f Guido Trotter
  """Simple dict tansformation tests"""
43 4c14965f Guido Trotter
44 4c14965f Guido Trotter
  def testSimpleObjectToDict(self):
45 8c114acd Michael Hanselmann
    o1 = SimpleObject(a="1")
46 8c114acd Michael Hanselmann
    self.assertEquals(o1.ToDict(), {"a": "1"})
47 8c114acd Michael Hanselmann
    self.assertEquals(o1.__getstate__(), {"a": "1"})
48 4c14965f Guido Trotter
    self.assertEquals(o1.__getstate__(), o1.ToDict())
49 4c14965f Guido Trotter
    o1.a = 2
50 4c14965f Guido Trotter
    o1.b = 5
51 8c114acd Michael Hanselmann
    self.assertEquals(o1.ToDict(), {"a": 2, "b": 5})
52 4c14965f Guido Trotter
    o2 = SimpleObject.FromDict(o1.ToDict())
53 8c114acd Michael Hanselmann
    self.assertEquals(o1.ToDict(), {"a": 2, "b": 5})
54 4c14965f Guido Trotter
55 4c14965f Guido Trotter
56 7b64b9ea René Nussbaumer
class TestClusterObject(unittest.TestCase):
57 7b64b9ea René Nussbaumer
  """Tests done on a L{objects.Cluster}"""
58 7b64b9ea René Nussbaumer
59 7b64b9ea René Nussbaumer
  def setUp(self):
60 7b64b9ea René Nussbaumer
    hvparams = {
61 7b64b9ea René Nussbaumer
      constants.HT_FAKE: {
62 7b64b9ea René Nussbaumer
        "foo": "bar",
63 7b64b9ea René Nussbaumer
        "bar": "foo",
64 7b64b9ea René Nussbaumer
        "foobar": "barfoo",
65 7b64b9ea René Nussbaumer
        },
66 7b64b9ea René Nussbaumer
      }
67 7b64b9ea René Nussbaumer
    os_hvp = {
68 7b64b9ea René Nussbaumer
      "lenny-image": {
69 7b64b9ea René Nussbaumer
        constants.HT_FAKE: {
70 7b64b9ea René Nussbaumer
          "foo": "baz",
71 7b64b9ea René Nussbaumer
          "foobar": "foobar",
72 7b64b9ea René Nussbaumer
          "blah": "blibb",
73 7b64b9ea René Nussbaumer
          "blubb": "blah",
74 7b64b9ea René Nussbaumer
          },
75 7b64b9ea René Nussbaumer
        constants.HT_XEN_PVM: {
76 7b64b9ea René Nussbaumer
          "root_path": "/dev/sda5",
77 7b64b9ea René Nussbaumer
          "foo": "foobar",
78 7b64b9ea René Nussbaumer
          },
79 7b64b9ea René Nussbaumer
        },
80 7b64b9ea René Nussbaumer
      "ubuntu-hardy": {
81 7b64b9ea René Nussbaumer
        },
82 7b64b9ea René Nussbaumer
      }
83 095e71aa René Nussbaumer
    ndparams = {
84 432e8e2f Iustin Pop
        constants.ND_OOB_PROGRAM: "/bin/cluster-oob",
85 0ea11dcb Bernardo Dal Seno
        constants.ND_SPINDLE_COUNT: 1,
86 0ea11dcb Bernardo Dal Seno
        constants.ND_EXCLUSIVE_STORAGE: False,
87 095e71aa René Nussbaumer
        }
88 095e71aa René Nussbaumer
89 095e71aa René Nussbaumer
    self.fake_cl = objects.Cluster(hvparams=hvparams, os_hvp=os_hvp,
90 095e71aa René Nussbaumer
                                   ndparams=ndparams)
91 7b64b9ea René Nussbaumer
    self.fake_cl.UpgradeConfig()
92 7b64b9ea René Nussbaumer
93 d63479b5 Iustin Pop
  def testGetHVDefaults(self):
94 d63479b5 Iustin Pop
    cl = self.fake_cl
95 d63479b5 Iustin Pop
    self.failUnlessEqual(cl.GetHVDefaults(constants.HT_FAKE),
96 d63479b5 Iustin Pop
                         cl.hvparams[constants.HT_FAKE])
97 d63479b5 Iustin Pop
    self.failUnlessEqual(cl.GetHVDefaults(None), {})
98 6ee8fdd3 Michele Tartara
    defaults = cl.GetHVDefaults(constants.HT_XEN_PVM,
99 6ee8fdd3 Michele Tartara
                                          os_name="lenny-image")
100 6ee8fdd3 Michele Tartara
    for param, value in cl.os_hvp["lenny-image"][constants.HT_XEN_PVM].items():
101 6ee8fdd3 Michele Tartara
      self.assertEqual(value, defaults[param])
102 d63479b5 Iustin Pop
103 7b64b9ea René Nussbaumer
  def testFillHvFullMerge(self):
104 7b64b9ea René Nussbaumer
    inst_hvparams = {
105 7b64b9ea René Nussbaumer
      "blah": "blubb",
106 7b64b9ea René Nussbaumer
      }
107 7b64b9ea René Nussbaumer
108 1f3096c2 Thomas Thrainer
    fake_dict = constants.HVC_DEFAULTS[constants.HT_FAKE].copy()
109 1f3096c2 Thomas Thrainer
    fake_dict.update({
110 7b64b9ea René Nussbaumer
      "foo": "baz",
111 7b64b9ea René Nussbaumer
      "bar": "foo",
112 7b64b9ea René Nussbaumer
      "foobar": "foobar",
113 7b64b9ea René Nussbaumer
      "blah": "blubb",
114 7b64b9ea René Nussbaumer
      "blubb": "blah",
115 1f3096c2 Thomas Thrainer
      })
116 7b64b9ea René Nussbaumer
    fake_inst = objects.Instance(name="foobar",
117 7b64b9ea René Nussbaumer
                                 os="lenny-image",
118 7b64b9ea René Nussbaumer
                                 hypervisor=constants.HT_FAKE,
119 7b64b9ea René Nussbaumer
                                 hvparams=inst_hvparams)
120 7b64b9ea René Nussbaumer
    self.assertEqual(fake_dict, self.fake_cl.FillHV(fake_inst))
121 7b64b9ea René Nussbaumer
122 7b64b9ea René Nussbaumer
  def testFillHvGlobalParams(self):
123 7b64b9ea René Nussbaumer
    fake_inst = objects.Instance(name="foobar",
124 7b64b9ea René Nussbaumer
                                 os="ubuntu-hardy",
125 7b64b9ea René Nussbaumer
                                 hypervisor=constants.HT_FAKE,
126 7b64b9ea René Nussbaumer
                                 hvparams={})
127 7b64b9ea René Nussbaumer
    self.assertEqual(self.fake_cl.hvparams[constants.HT_FAKE],
128 7b64b9ea René Nussbaumer
                     self.fake_cl.FillHV(fake_inst))
129 7b64b9ea René Nussbaumer
130 7b64b9ea René Nussbaumer
  def testFillHvInstParams(self):
131 7b64b9ea René Nussbaumer
    inst_hvparams = {
132 7b64b9ea René Nussbaumer
      "blah": "blubb",
133 7b64b9ea René Nussbaumer
      }
134 7b64b9ea René Nussbaumer
    fake_inst = objects.Instance(name="foobar",
135 7b64b9ea René Nussbaumer
                                 os="ubuntu-hardy",
136 7b64b9ea René Nussbaumer
                                 hypervisor=constants.HT_XEN_PVM,
137 7b64b9ea René Nussbaumer
                                 hvparams=inst_hvparams)
138 6ee8fdd3 Michele Tartara
    filled_conf = self.fake_cl.FillHV(fake_inst)
139 6ee8fdd3 Michele Tartara
    for param, value in constants.HVC_DEFAULTS[constants.HT_XEN_PVM].items():
140 6ee8fdd3 Michele Tartara
      if param == "blah":
141 6ee8fdd3 Michele Tartara
        value = "blubb"
142 6ee8fdd3 Michele Tartara
      self.assertEqual(value, filled_conf[param])
143 7b64b9ea René Nussbaumer
144 6ee8fdd3 Michele Tartara
  def testFillHvDefaultParams(self):
145 7b64b9ea René Nussbaumer
    fake_inst = objects.Instance(name="foobar",
146 7b64b9ea René Nussbaumer
                                 os="ubuntu-hardy",
147 7b64b9ea René Nussbaumer
                                 hypervisor=constants.HT_XEN_PVM,
148 7b64b9ea René Nussbaumer
                                 hvparams={})
149 6ee8fdd3 Michele Tartara
    self.assertEqual(constants.HVC_DEFAULTS[constants.HT_XEN_PVM],
150 6ee8fdd3 Michele Tartara
                     self.fake_cl.FillHV(fake_inst))
151 7b64b9ea René Nussbaumer
152 7b64b9ea René Nussbaumer
  def testFillHvPartialParams(self):
153 7b64b9ea René Nussbaumer
    os = "lenny-image"
154 7b64b9ea René Nussbaumer
    fake_inst = objects.Instance(name="foobar",
155 7b64b9ea René Nussbaumer
                                 os=os,
156 7b64b9ea René Nussbaumer
                                 hypervisor=constants.HT_XEN_PVM,
157 7b64b9ea René Nussbaumer
                                 hvparams={})
158 6ee8fdd3 Michele Tartara
    filled_conf = self.fake_cl.FillHV(fake_inst)
159 6ee8fdd3 Michele Tartara
    for param, value in self.fake_cl.os_hvp[os][constants.HT_XEN_PVM].items():
160 6ee8fdd3 Michele Tartara
      self.assertEqual(value, filled_conf[param])
161 7b64b9ea René Nussbaumer
162 095e71aa René Nussbaumer
  def testFillNdParamsCluster(self):
163 095e71aa René Nussbaumer
    fake_node = objects.Node(name="test",
164 095e71aa René Nussbaumer
                             ndparams={},
165 095e71aa René Nussbaumer
                             group="testgroup")
166 095e71aa René Nussbaumer
    fake_group = objects.NodeGroup(name="testgroup",
167 095e71aa René Nussbaumer
                                   ndparams={})
168 095e71aa René Nussbaumer
    self.assertEqual(self.fake_cl.ndparams,
169 095e71aa René Nussbaumer
                     self.fake_cl.FillND(fake_node, fake_group))
170 095e71aa René Nussbaumer
171 095e71aa René Nussbaumer
  def testFillNdParamsNodeGroup(self):
172 095e71aa René Nussbaumer
    fake_node = objects.Node(name="test",
173 095e71aa René Nussbaumer
                             ndparams={},
174 095e71aa René Nussbaumer
                             group="testgroup")
175 095e71aa René Nussbaumer
    group_ndparams = {
176 432e8e2f Iustin Pop
        constants.ND_OOB_PROGRAM: "/bin/group-oob",
177 432e8e2f Iustin Pop
        constants.ND_SPINDLE_COUNT: 10,
178 0ea11dcb Bernardo Dal Seno
        constants.ND_EXCLUSIVE_STORAGE: True,
179 807d8853 Sebastian Gebhard
        constants.ND_OVS: True,
180 807d8853 Sebastian Gebhard
        constants.ND_OVS_LINK: "eth2",
181 807d8853 Sebastian Gebhard
        constants.ND_OVS_NAME: "openvswitch",
182 33ffda6c Petr Pudlak
        constants.ND_SSH_PORT: 122,
183 095e71aa René Nussbaumer
        }
184 095e71aa René Nussbaumer
    fake_group = objects.NodeGroup(name="testgroup",
185 095e71aa René Nussbaumer
                                   ndparams=group_ndparams)
186 095e71aa René Nussbaumer
    self.assertEqual(group_ndparams,
187 095e71aa René Nussbaumer
                     self.fake_cl.FillND(fake_node, fake_group))
188 095e71aa René Nussbaumer
189 095e71aa René Nussbaumer
  def testFillNdParamsNode(self):
190 095e71aa René Nussbaumer
    node_ndparams = {
191 432e8e2f Iustin Pop
        constants.ND_OOB_PROGRAM: "/bin/node-oob",
192 432e8e2f Iustin Pop
        constants.ND_SPINDLE_COUNT: 2,
193 0ea11dcb Bernardo Dal Seno
        constants.ND_EXCLUSIVE_STORAGE: True,
194 807d8853 Sebastian Gebhard
        constants.ND_OVS: True,
195 807d8853 Sebastian Gebhard
        constants.ND_OVS_LINK: "eth2",
196 807d8853 Sebastian Gebhard
        constants.ND_OVS_NAME: "openvswitch",
197 33ffda6c Petr Pudlak
        constants.ND_SSH_PORT: 222,
198 095e71aa René Nussbaumer
        }
199 095e71aa René Nussbaumer
    fake_node = objects.Node(name="test",
200 095e71aa René Nussbaumer
                             ndparams=node_ndparams,
201 095e71aa René Nussbaumer
                             group="testgroup")
202 095e71aa René Nussbaumer
    fake_group = objects.NodeGroup(name="testgroup",
203 095e71aa René Nussbaumer
                                   ndparams={})
204 095e71aa René Nussbaumer
    self.assertEqual(node_ndparams,
205 095e71aa René Nussbaumer
                     self.fake_cl.FillND(fake_node, fake_group))
206 095e71aa René Nussbaumer
207 095e71aa René Nussbaumer
  def testFillNdParamsAll(self):
208 095e71aa René Nussbaumer
    node_ndparams = {
209 432e8e2f Iustin Pop
        constants.ND_OOB_PROGRAM: "/bin/node-oob",
210 432e8e2f Iustin Pop
        constants.ND_SPINDLE_COUNT: 5,
211 0ea11dcb Bernardo Dal Seno
        constants.ND_EXCLUSIVE_STORAGE: True,
212 807d8853 Sebastian Gebhard
        constants.ND_OVS: True,
213 807d8853 Sebastian Gebhard
        constants.ND_OVS_LINK: "eth2",
214 807d8853 Sebastian Gebhard
        constants.ND_OVS_NAME: "openvswitch",
215 33ffda6c Petr Pudlak
        constants.ND_SSH_PORT: 322,
216 095e71aa René Nussbaumer
        }
217 095e71aa René Nussbaumer
    fake_node = objects.Node(name="test",
218 095e71aa René Nussbaumer
                             ndparams=node_ndparams,
219 095e71aa René Nussbaumer
                             group="testgroup")
220 095e71aa René Nussbaumer
    group_ndparams = {
221 432e8e2f Iustin Pop
        constants.ND_OOB_PROGRAM: "/bin/group-oob",
222 432e8e2f Iustin Pop
        constants.ND_SPINDLE_COUNT: 4,
223 33ffda6c Petr Pudlak
        constants.ND_SSH_PORT: 422,
224 095e71aa René Nussbaumer
        }
225 095e71aa René Nussbaumer
    fake_group = objects.NodeGroup(name="testgroup",
226 095e71aa René Nussbaumer
                                   ndparams=group_ndparams)
227 095e71aa René Nussbaumer
    self.assertEqual(node_ndparams,
228 095e71aa René Nussbaumer
                     self.fake_cl.FillND(fake_node, fake_group))
229 095e71aa René Nussbaumer
230 0fbedb7a Michael Hanselmann
  def testPrimaryHypervisor(self):
231 0fbedb7a Michael Hanselmann
    assert self.fake_cl.enabled_hypervisors is None
232 0fbedb7a Michael Hanselmann
    self.fake_cl.enabled_hypervisors = [constants.HT_XEN_HVM]
233 0fbedb7a Michael Hanselmann
    self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_XEN_HVM)
234 0fbedb7a Michael Hanselmann
235 0fbedb7a Michael Hanselmann
    self.fake_cl.enabled_hypervisors = [constants.HT_XEN_PVM, constants.HT_KVM]
236 0fbedb7a Michael Hanselmann
    self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_XEN_PVM)
237 0fbedb7a Michael Hanselmann
238 0fbedb7a Michael Hanselmann
    self.fake_cl.enabled_hypervisors = sorted(constants.HYPER_TYPES)
239 0fbedb7a Michael Hanselmann
    self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_CHROOT)
240 0fbedb7a Michael Hanselmann
241 4f7e5a1d Bernardo Dal Seno
  def testUpgradeConfig(self):
242 4f7e5a1d Bernardo Dal Seno
    # FIXME: This test is incomplete
243 4f7e5a1d Bernardo Dal Seno
    cluster = objects.Cluster()
244 4f7e5a1d Bernardo Dal Seno
    cluster.UpgradeConfig()
245 4f7e5a1d Bernardo Dal Seno
    cluster = objects.Cluster(ipolicy={"unknown_key": None})
246 4f7e5a1d Bernardo Dal Seno
    self.assertRaises(errors.ConfigurationError, cluster.UpgradeConfig)
247 4f7e5a1d Bernardo Dal Seno
248 a2112db5 Helga Velroyen
  def testUpgradeEnabledDiskTemplates(self):
249 a2112db5 Helga Velroyen
    cfg = objects.ConfigData()
250 a2112db5 Helga Velroyen
    cfg.cluster = objects.Cluster()
251 a2112db5 Helga Velroyen
    cfg.cluster.volume_group_name = "myvg"
252 a2112db5 Helga Velroyen
    instance1 = objects.Instance()
253 a2112db5 Helga Velroyen
    instance1.disk_template = constants.DT_DISKLESS
254 a2112db5 Helga Velroyen
    instance2 = objects.Instance()
255 a2112db5 Helga Velroyen
    instance2.disk_template = constants.DT_RBD
256 a2112db5 Helga Velroyen
    cfg.instances = { "myinstance1": instance1, "myinstance2": instance2 }
257 a2112db5 Helga Velroyen
    nodegroup = objects.NodeGroup()
258 a2112db5 Helga Velroyen
    nodegroup.ipolicy = {}
259 a2112db5 Helga Velroyen
    nodegroup.ipolicy[constants.IPOLICY_DTS] = [instance1.disk_template, \
260 a2112db5 Helga Velroyen
      constants.DT_BLOCK]
261 a2112db5 Helga Velroyen
    cfg.cluster.ipolicy = {}
262 a2112db5 Helga Velroyen
    cfg.cluster.ipolicy[constants.IPOLICY_DTS] = \
263 a2112db5 Helga Velroyen
      [constants.DT_EXT, constants.DT_DISKLESS]
264 a2112db5 Helga Velroyen
    cfg.nodegroups = { "mynodegroup": nodegroup }
265 a2112db5 Helga Velroyen
    cfg._UpgradeEnabledDiskTemplates()
266 a2112db5 Helga Velroyen
    expected_disk_templates = [constants.DT_DRBD8,
267 a2112db5 Helga Velroyen
                               constants.DT_PLAIN,
268 a2112db5 Helga Velroyen
                               instance1.disk_template,
269 a2112db5 Helga Velroyen
                               instance2.disk_template]
270 a2112db5 Helga Velroyen
    self.assertEqual(set(expected_disk_templates),
271 a2112db5 Helga Velroyen
                     set(cfg.cluster.enabled_disk_templates))
272 a2112db5 Helga Velroyen
    self.assertEqual(set([instance1.disk_template]),
273 a2112db5 Helga Velroyen
                     set(cfg.cluster.ipolicy[constants.IPOLICY_DTS]))
274 a2112db5 Helga Velroyen
275 7b64b9ea René Nussbaumer
276 4d36fbf4 Michael Hanselmann
class TestClusterObjectTcpUdpPortPool(unittest.TestCase):
277 4d36fbf4 Michael Hanselmann
  def testNewCluster(self):
278 4d36fbf4 Michael Hanselmann
    self.assertTrue(objects.Cluster().tcpudp_port_pool is None)
279 4d36fbf4 Michael Hanselmann
280 4d36fbf4 Michael Hanselmann
  def testSerializingEmpty(self):
281 4d36fbf4 Michael Hanselmann
    self.assertEqual(objects.Cluster().ToDict(), {
282 4d36fbf4 Michael Hanselmann
      "tcpudp_port_pool": [],
283 4d36fbf4 Michael Hanselmann
      })
284 4d36fbf4 Michael Hanselmann
285 4d36fbf4 Michael Hanselmann
  def testSerializing(self):
286 4d36fbf4 Michael Hanselmann
    cluster = objects.Cluster.FromDict({})
287 4d36fbf4 Michael Hanselmann
    self.assertEqual(cluster.tcpudp_port_pool, set())
288 4d36fbf4 Michael Hanselmann
289 4d36fbf4 Michael Hanselmann
    cluster.tcpudp_port_pool.add(3546)
290 4d36fbf4 Michael Hanselmann
    cluster.tcpudp_port_pool.add(62511)
291 4d36fbf4 Michael Hanselmann
292 4d36fbf4 Michael Hanselmann
    data = cluster.ToDict()
293 4d36fbf4 Michael Hanselmann
    self.assertEqual(data.keys(), ["tcpudp_port_pool"])
294 4d36fbf4 Michael Hanselmann
    self.assertEqual(sorted(data["tcpudp_port_pool"]), sorted([3546, 62511]))
295 4d36fbf4 Michael Hanselmann
296 4d36fbf4 Michael Hanselmann
  def testDeserializingEmpty(self):
297 4d36fbf4 Michael Hanselmann
    cluster = objects.Cluster.FromDict({})
298 4d36fbf4 Michael Hanselmann
    self.assertEqual(cluster.tcpudp_port_pool, set())
299 4d36fbf4 Michael Hanselmann
300 4d36fbf4 Michael Hanselmann
  def testDeserialize(self):
301 4d36fbf4 Michael Hanselmann
    cluster = objects.Cluster.FromDict({
302 4d36fbf4 Michael Hanselmann
      "tcpudp_port_pool": [26214, 10039, 267],
303 4d36fbf4 Michael Hanselmann
      })
304 4d36fbf4 Michael Hanselmann
    self.assertEqual(cluster.tcpudp_port_pool, set([26214, 10039, 267]))
305 4d36fbf4 Michael Hanselmann
306 4d36fbf4 Michael Hanselmann
307 870dc44c Iustin Pop
class TestOS(unittest.TestCase):
308 870dc44c Iustin Pop
  ALL_DATA = [
309 870dc44c Iustin Pop
    "debootstrap",
310 870dc44c Iustin Pop
    "debootstrap+default",
311 870dc44c Iustin Pop
    "debootstrap++default",
312 870dc44c Iustin Pop
    ]
313 870dc44c Iustin Pop
314 870dc44c Iustin Pop
  def testSplitNameVariant(self):
315 870dc44c Iustin Pop
    for name in self.ALL_DATA:
316 870dc44c Iustin Pop
      self.assertEqual(len(objects.OS.SplitNameVariant(name)), 2)
317 870dc44c Iustin Pop
318 870dc44c Iustin Pop
  def testVariant(self):
319 870dc44c Iustin Pop
    self.assertEqual(objects.OS.GetVariant("debootstrap"), "")
320 870dc44c Iustin Pop
    self.assertEqual(objects.OS.GetVariant("debootstrap+default"), "default")
321 870dc44c Iustin Pop
322 870dc44c Iustin Pop
323 6a050007 Michael Hanselmann
class TestInstance(unittest.TestCase):
324 5b798711 Ilias Tsitsimpis
  def testFindDisk(self):
325 6a050007 Michael Hanselmann
    inst = objects.Instance(name="fakeinstdrbd.example.com",
326 6a050007 Michael Hanselmann
      primary_node="node10.example.com",
327 6a050007 Michael Hanselmann
      disks=[
328 cd3b4ff4 Helga Velroyen
        objects.Disk(dev_type=constants.DT_DRBD8, size=786432,
329 6a050007 Michael Hanselmann
          logical_id=("node10.example.com", "node15.example.com",
330 6a050007 Michael Hanselmann
                      12300, 0, 0, "secret"),
331 6a050007 Michael Hanselmann
          children=[
332 cd3b4ff4 Helga Velroyen
            objects.Disk(dev_type=constants.DT_PLAIN, size=786432,
333 6a050007 Michael Hanselmann
                         logical_id=("myxenvg", "disk0")),
334 cd3b4ff4 Helga Velroyen
            objects.Disk(dev_type=constants.DT_PLAIN, size=128,
335 6a050007 Michael Hanselmann
                         logical_id=("myxenvg", "meta0"))
336 6a050007 Michael Hanselmann
          ],
337 6a050007 Michael Hanselmann
          iv_name="disk/0")
338 6a050007 Michael Hanselmann
        ])
339 6a050007 Michael Hanselmann
340 6a050007 Michael Hanselmann
    self.assertEqual(inst.FindDisk(0), inst.disks[0])
341 6a050007 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, inst.FindDisk, "hello")
342 6a050007 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, inst.FindDisk, 100)
343 6a050007 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, inst.FindDisk, 1)
344 6a050007 Michael Hanselmann
345 6a050007 Michael Hanselmann
346 5f06ce5e Michael Hanselmann
class TestNode(unittest.TestCase):
347 5f06ce5e Michael Hanselmann
  def testEmpty(self):
348 5f06ce5e Michael Hanselmann
    self.assertEqual(objects.Node().ToDict(), {})
349 5f06ce5e Michael Hanselmann
    self.assertTrue(isinstance(objects.Node.FromDict({}), objects.Node))
350 5f06ce5e Michael Hanselmann
351 5f06ce5e Michael Hanselmann
  def testHvState(self):
352 5f06ce5e Michael Hanselmann
    node = objects.Node(name="node18157.example.com", hv_state={
353 5f06ce5e Michael Hanselmann
      constants.HT_XEN_HVM: objects.NodeHvState(cpu_total=64),
354 5f06ce5e Michael Hanselmann
      constants.HT_KVM: objects.NodeHvState(cpu_node=1),
355 5f06ce5e Michael Hanselmann
      })
356 5f06ce5e Michael Hanselmann
357 5f06ce5e Michael Hanselmann
    node2 = objects.Node.FromDict(node.ToDict())
358 5f06ce5e Michael Hanselmann
359 5f06ce5e Michael Hanselmann
    # Make sure nothing can reference it anymore
360 5f06ce5e Michael Hanselmann
    del node
361 5f06ce5e Michael Hanselmann
362 5f06ce5e Michael Hanselmann
    self.assertEqual(node2.name, "node18157.example.com")
363 5f06ce5e Michael Hanselmann
    self.assertEqual(frozenset(node2.hv_state), frozenset([
364 5f06ce5e Michael Hanselmann
      constants.HT_XEN_HVM,
365 5f06ce5e Michael Hanselmann
      constants.HT_KVM,
366 5f06ce5e Michael Hanselmann
      ]))
367 5f06ce5e Michael Hanselmann
    self.assertEqual(node2.hv_state[constants.HT_KVM].cpu_node, 1)
368 5f06ce5e Michael Hanselmann
    self.assertEqual(node2.hv_state[constants.HT_XEN_HVM].cpu_total, 64)
369 5f06ce5e Michael Hanselmann
370 5f06ce5e Michael Hanselmann
  def testDiskState(self):
371 5f06ce5e Michael Hanselmann
    node = objects.Node(name="node32087.example.com", disk_state={
372 cd3b4ff4 Helga Velroyen
      constants.DT_PLAIN: {
373 5f06ce5e Michael Hanselmann
        "lv32352": objects.NodeDiskState(total=128),
374 5f06ce5e Michael Hanselmann
        "lv2082": objects.NodeDiskState(total=512),
375 5f06ce5e Michael Hanselmann
        },
376 5f06ce5e Michael Hanselmann
      })
377 5f06ce5e Michael Hanselmann
378 5f06ce5e Michael Hanselmann
    node2 = objects.Node.FromDict(node.ToDict())
379 5f06ce5e Michael Hanselmann
380 5f06ce5e Michael Hanselmann
    # Make sure nothing can reference it anymore
381 5f06ce5e Michael Hanselmann
    del node
382 5f06ce5e Michael Hanselmann
383 5f06ce5e Michael Hanselmann
    self.assertEqual(node2.name, "node32087.example.com")
384 5f06ce5e Michael Hanselmann
    self.assertEqual(frozenset(node2.disk_state), frozenset([
385 cd3b4ff4 Helga Velroyen
      constants.DT_PLAIN,
386 5f06ce5e Michael Hanselmann
      ]))
387 cd3b4ff4 Helga Velroyen
    self.assertEqual(frozenset(node2.disk_state[constants.DT_PLAIN]),
388 cd3b4ff4 Helga Velroyen
                     frozenset(["lv32352", "lv2082"]))
389 cd3b4ff4 Helga Velroyen
    self.assertEqual(node2.disk_state[constants.DT_PLAIN]["lv2082"].total, 512)
390 cd3b4ff4 Helga Velroyen
    self.assertEqual(node2.disk_state[constants.DT_PLAIN]["lv32352"].total, 128)
391 5f06ce5e Michael Hanselmann
392 250a9404 Bernardo Dal Seno
  def testFilterEsNdp(self):
393 250a9404 Bernardo Dal Seno
    node1 = objects.Node(name="node11673.example.com", ndparams={
394 250a9404 Bernardo Dal Seno
      constants.ND_EXCLUSIVE_STORAGE: True,
395 250a9404 Bernardo Dal Seno
      })
396 250a9404 Bernardo Dal Seno
    node2 = objects.Node(name="node11674.example.com", ndparams={
397 250a9404 Bernardo Dal Seno
      constants.ND_SPINDLE_COUNT: 3,
398 250a9404 Bernardo Dal Seno
      constants.ND_EXCLUSIVE_STORAGE: False,
399 250a9404 Bernardo Dal Seno
      })
400 250a9404 Bernardo Dal Seno
    self.assertTrue(constants.ND_EXCLUSIVE_STORAGE in node1.ndparams)
401 250a9404 Bernardo Dal Seno
    node1.UpgradeConfig()
402 250a9404 Bernardo Dal Seno
    self.assertFalse(constants.ND_EXCLUSIVE_STORAGE in node1.ndparams)
403 250a9404 Bernardo Dal Seno
    self.assertTrue(constants.ND_EXCLUSIVE_STORAGE in node2.ndparams)
404 250a9404 Bernardo Dal Seno
    self.assertTrue(constants.ND_SPINDLE_COUNT in node2.ndparams)
405 250a9404 Bernardo Dal Seno
    node2.UpgradeConfig()
406 250a9404 Bernardo Dal Seno
    self.assertFalse(constants.ND_EXCLUSIVE_STORAGE in node2.ndparams)
407 250a9404 Bernardo Dal Seno
    self.assertTrue(constants.ND_SPINDLE_COUNT in node2.ndparams)
408 250a9404 Bernardo Dal Seno
409 5f06ce5e Michael Hanselmann
410 e38bc4eb Bernardo Dal Seno
class TestInstancePolicy(unittest.TestCase):
411 e38bc4eb Bernardo Dal Seno
  def setUp(self):
412 e38bc4eb Bernardo Dal Seno
    # Policies are big, and we want to see the difference in case of an error
413 e38bc4eb Bernardo Dal Seno
    self.maxDiff = None
414 e38bc4eb Bernardo Dal Seno
415 e38bc4eb Bernardo Dal Seno
  def _AssertIPolicyIsFull(self, policy):
416 e38bc4eb Bernardo Dal Seno
    self.assertEqual(frozenset(policy.keys()), constants.IPOLICY_ALL_KEYS)
417 41044e04 Bernardo Dal Seno
    self.assertTrue(len(policy[constants.ISPECS_MINMAX]) > 0)
418 41044e04 Bernardo Dal Seno
    for minmax in policy[constants.ISPECS_MINMAX]:
419 41044e04 Bernardo Dal Seno
      self.assertEqual(frozenset(minmax.keys()), constants.ISPECS_MINMAX_KEYS)
420 41044e04 Bernardo Dal Seno
      for key in constants.ISPECS_MINMAX_KEYS:
421 41044e04 Bernardo Dal Seno
        self.assertEqual(frozenset(minmax[key].keys()),
422 41044e04 Bernardo Dal Seno
                         constants.ISPECS_PARAMETERS)
423 da5f09ef Bernardo Dal Seno
    self.assertEqual(frozenset(policy[constants.ISPECS_STD].keys()),
424 da5f09ef Bernardo Dal Seno
                     constants.ISPECS_PARAMETERS)
425 e38bc4eb Bernardo Dal Seno
426 e38bc4eb Bernardo Dal Seno
  def testDefaultIPolicy(self):
427 e38bc4eb Bernardo Dal Seno
    objects.InstancePolicy.CheckParameterSyntax(constants.IPOLICY_DEFAULTS,
428 e38bc4eb Bernardo Dal Seno
                                                True)
429 e38bc4eb Bernardo Dal Seno
    self._AssertIPolicyIsFull(constants.IPOLICY_DEFAULTS)
430 e38bc4eb Bernardo Dal Seno
431 41044e04 Bernardo Dal Seno
  def _AssertPolicyIsBad(self, ipolicy, do_check_std=None):
432 41044e04 Bernardo Dal Seno
    if do_check_std is None:
433 41044e04 Bernardo Dal Seno
      check_std_vals = [False, True]
434 41044e04 Bernardo Dal Seno
    else:
435 41044e04 Bernardo Dal Seno
      check_std_vals = [do_check_std]
436 41044e04 Bernardo Dal Seno
    for check_std in check_std_vals:
437 41044e04 Bernardo Dal Seno
      self.assertRaises(errors.ConfigurationError,
438 41044e04 Bernardo Dal Seno
                        objects.InstancePolicy.CheckISpecSyntax,
439 41044e04 Bernardo Dal Seno
                        ipolicy, check_std)
440 41044e04 Bernardo Dal Seno
441 ba5c6c6b Bernardo Dal Seno
  def testCheckISpecSyntax(self):
442 b342c9dd Bernardo Dal Seno
    default_stdspec = constants.IPOLICY_DEFAULTS[constants.ISPECS_STD]
443 62fed51b Bernardo Dal Seno
    incomplete_ipolicies = [
444 62fed51b Bernardo Dal Seno
      {
445 41044e04 Bernardo Dal Seno
         constants.ISPECS_MINMAX: [],
446 b342c9dd Bernardo Dal Seno
         constants.ISPECS_STD: default_stdspec,
447 62fed51b Bernardo Dal Seno
         },
448 62fed51b Bernardo Dal Seno
      {
449 41044e04 Bernardo Dal Seno
         constants.ISPECS_MINMAX: [{}],
450 41044e04 Bernardo Dal Seno
         constants.ISPECS_STD: default_stdspec,
451 41044e04 Bernardo Dal Seno
         },
452 41044e04 Bernardo Dal Seno
      {
453 41044e04 Bernardo Dal Seno
        constants.ISPECS_MINMAX: [{
454 62fed51b Bernardo Dal Seno
          constants.ISPECS_MIN: NotImplemented,
455 41044e04 Bernardo Dal Seno
          }],
456 b342c9dd Bernardo Dal Seno
        constants.ISPECS_STD: default_stdspec,
457 62fed51b Bernardo Dal Seno
        },
458 62fed51b Bernardo Dal Seno
      {
459 41044e04 Bernardo Dal Seno
        constants.ISPECS_MINMAX: [{
460 62fed51b Bernardo Dal Seno
          constants.ISPECS_MAX: NotImplemented,
461 41044e04 Bernardo Dal Seno
          }],
462 b342c9dd Bernardo Dal Seno
        constants.ISPECS_STD: default_stdspec,
463 62fed51b Bernardo Dal Seno
        },
464 62fed51b Bernardo Dal Seno
      {
465 41044e04 Bernardo Dal Seno
        constants.ISPECS_MINMAX: [{
466 62fed51b Bernardo Dal Seno
          constants.ISPECS_MIN: NotImplemented,
467 62fed51b Bernardo Dal Seno
          constants.ISPECS_MAX: NotImplemented,
468 41044e04 Bernardo Dal Seno
          }],
469 62fed51b Bernardo Dal Seno
        },
470 62fed51b Bernardo Dal Seno
      ]
471 62fed51b Bernardo Dal Seno
    for ipol in incomplete_ipolicies:
472 62fed51b Bernardo Dal Seno
      self.assertRaises(errors.ConfigurationError,
473 62fed51b Bernardo Dal Seno
                        objects.InstancePolicy.CheckISpecSyntax,
474 62fed51b Bernardo Dal Seno
                        ipol, True)
475 41044e04 Bernardo Dal Seno
      oldminmax = ipol[constants.ISPECS_MINMAX]
476 41044e04 Bernardo Dal Seno
      if oldminmax:
477 41044e04 Bernardo Dal Seno
        # Prepending valid specs shouldn't change the error
478 41044e04 Bernardo Dal Seno
        ipol[constants.ISPECS_MINMAX] = ([constants.ISPECS_MINMAX_DEFAULTS] +
479 41044e04 Bernardo Dal Seno
                                         oldminmax)
480 41044e04 Bernardo Dal Seno
        self.assertRaises(errors.ConfigurationError,
481 41044e04 Bernardo Dal Seno
                          objects.InstancePolicy.CheckISpecSyntax,
482 41044e04 Bernardo Dal Seno
                          ipol, True)
483 41044e04 Bernardo Dal Seno
484 41044e04 Bernardo Dal Seno
    good_ipolicy = {
485 41044e04 Bernardo Dal Seno
      constants.ISPECS_MINMAX: [
486 41044e04 Bernardo Dal Seno
        {
487 41044e04 Bernardo Dal Seno
          constants.ISPECS_MIN: {
488 41044e04 Bernardo Dal Seno
            constants.ISPEC_MEM_SIZE: 64,
489 41044e04 Bernardo Dal Seno
            constants.ISPEC_CPU_COUNT: 1,
490 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_COUNT: 2,
491 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_SIZE: 64,
492 41044e04 Bernardo Dal Seno
            constants.ISPEC_NIC_COUNT: 1,
493 41044e04 Bernardo Dal Seno
            constants.ISPEC_SPINDLE_USE: 1,
494 41044e04 Bernardo Dal Seno
            },
495 41044e04 Bernardo Dal Seno
          constants.ISPECS_MAX: {
496 41044e04 Bernardo Dal Seno
            constants.ISPEC_MEM_SIZE: 16384,
497 41044e04 Bernardo Dal Seno
            constants.ISPEC_CPU_COUNT: 5,
498 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_COUNT: 12,
499 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_SIZE: 1024,
500 41044e04 Bernardo Dal Seno
            constants.ISPEC_NIC_COUNT: 9,
501 41044e04 Bernardo Dal Seno
            constants.ISPEC_SPINDLE_USE: 18,
502 41044e04 Bernardo Dal Seno
            },
503 41044e04 Bernardo Dal Seno
          },
504 41044e04 Bernardo Dal Seno
        {
505 41044e04 Bernardo Dal Seno
          constants.ISPECS_MIN: {
506 41044e04 Bernardo Dal Seno
            constants.ISPEC_MEM_SIZE: 32768,
507 41044e04 Bernardo Dal Seno
            constants.ISPEC_CPU_COUNT: 8,
508 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_COUNT: 1,
509 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_SIZE: 1024,
510 41044e04 Bernardo Dal Seno
            constants.ISPEC_NIC_COUNT: 1,
511 41044e04 Bernardo Dal Seno
            constants.ISPEC_SPINDLE_USE: 1,
512 41044e04 Bernardo Dal Seno
            },
513 41044e04 Bernardo Dal Seno
          constants.ISPECS_MAX: {
514 41044e04 Bernardo Dal Seno
            constants.ISPEC_MEM_SIZE: 65536,
515 41044e04 Bernardo Dal Seno
            constants.ISPEC_CPU_COUNT: 10,
516 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_COUNT: 5,
517 41044e04 Bernardo Dal Seno
            constants.ISPEC_DISK_SIZE: 1024 * 1024,
518 41044e04 Bernardo Dal Seno
            constants.ISPEC_NIC_COUNT: 3,
519 41044e04 Bernardo Dal Seno
            constants.ISPEC_SPINDLE_USE: 12,
520 41044e04 Bernardo Dal Seno
            },
521 41044e04 Bernardo Dal Seno
          },
522 41044e04 Bernardo Dal Seno
        ],
523 41044e04 Bernardo Dal Seno
      }
524 41044e04 Bernardo Dal Seno
    good_ipolicy[constants.ISPECS_STD] = copy.deepcopy(
525 41044e04 Bernardo Dal Seno
      good_ipolicy[constants.ISPECS_MINMAX][0][constants.ISPECS_MAX])
526 41044e04 Bernardo Dal Seno
    # Check that it's really good before making it bad
527 41044e04 Bernardo Dal Seno
    objects.InstancePolicy.CheckISpecSyntax(good_ipolicy, True)
528 41044e04 Bernardo Dal Seno
529 41044e04 Bernardo Dal Seno
    bad_ipolicy = copy.deepcopy(good_ipolicy)
530 41044e04 Bernardo Dal Seno
    for minmax in bad_ipolicy[constants.ISPECS_MINMAX]:
531 41044e04 Bernardo Dal Seno
      for (key, spec) in minmax.items():
532 41044e04 Bernardo Dal Seno
        for param in spec:
533 41044e04 Bernardo Dal Seno
          oldv = spec[param]
534 41044e04 Bernardo Dal Seno
          del spec[param]
535 41044e04 Bernardo Dal Seno
          self._AssertPolicyIsBad(bad_ipolicy)
536 41044e04 Bernardo Dal Seno
          if key == constants.ISPECS_MIN:
537 41044e04 Bernardo Dal Seno
            spec[param] = minmax[constants.ISPECS_MAX][param] + 1
538 41044e04 Bernardo Dal Seno
          self._AssertPolicyIsBad(bad_ipolicy)
539 41044e04 Bernardo Dal Seno
          spec[param] = oldv
540 41044e04 Bernardo Dal Seno
    assert bad_ipolicy == good_ipolicy
541 41044e04 Bernardo Dal Seno
542 41044e04 Bernardo Dal Seno
    stdspec = bad_ipolicy[constants.ISPECS_STD]
543 41044e04 Bernardo Dal Seno
    for param in stdspec:
544 41044e04 Bernardo Dal Seno
      oldv = stdspec[param]
545 41044e04 Bernardo Dal Seno
      del stdspec[param]
546 41044e04 Bernardo Dal Seno
      self._AssertPolicyIsBad(bad_ipolicy, True)
547 41044e04 Bernardo Dal Seno
      # Note that std spec is the same as a max spec
548 41044e04 Bernardo Dal Seno
      stdspec[param] = oldv + 1
549 41044e04 Bernardo Dal Seno
      self._AssertPolicyIsBad(bad_ipolicy, True)
550 41044e04 Bernardo Dal Seno
      stdspec[param] = oldv
551 41044e04 Bernardo Dal Seno
    assert bad_ipolicy == good_ipolicy
552 41044e04 Bernardo Dal Seno
553 41044e04 Bernardo Dal Seno
    for minmax in good_ipolicy[constants.ISPECS_MINMAX]:
554 41044e04 Bernardo Dal Seno
      for spec in minmax.values():
555 41044e04 Bernardo Dal Seno
        good_ipolicy[constants.ISPECS_STD] = spec
556 41044e04 Bernardo Dal Seno
        objects.InstancePolicy.CheckISpecSyntax(good_ipolicy, True)
557 62fed51b Bernardo Dal Seno
558 62fed51b Bernardo Dal Seno
  def testCheckISpecParamSyntax(self):
559 ba5c6c6b Bernardo Dal Seno
    par = "my_parameter"
560 ba5c6c6b Bernardo Dal Seno
    for check_std in [True, False]:
561 ba5c6c6b Bernardo Dal Seno
      # Min and max only
562 ba5c6c6b Bernardo Dal Seno
      good_values = [(11, 11), (11, 40), (0, 0)]
563 ba5c6c6b Bernardo Dal Seno
      for (mn, mx) in good_values:
564 da5f09ef Bernardo Dal Seno
        minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
565 da5f09ef Bernardo Dal Seno
        minmax[constants.ISPECS_MIN][par] = mn
566 da5f09ef Bernardo Dal Seno
        minmax[constants.ISPECS_MAX][par] = mx
567 62fed51b Bernardo Dal Seno
        objects.InstancePolicy._CheckISpecParamSyntax(minmax, {}, par,
568 62fed51b Bernardo Dal Seno
                                                     check_std)
569 da5f09ef Bernardo Dal Seno
      minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
570 da5f09ef Bernardo Dal Seno
      minmax[constants.ISPECS_MIN][par] = 11
571 da5f09ef Bernardo Dal Seno
      minmax[constants.ISPECS_MAX][par] = 5
572 ba5c6c6b Bernardo Dal Seno
      self.assertRaises(errors.ConfigurationError,
573 62fed51b Bernardo Dal Seno
                        objects.InstancePolicy._CheckISpecParamSyntax,
574 da5f09ef Bernardo Dal Seno
                        minmax, {}, par, check_std)
575 ba5c6c6b Bernardo Dal Seno
    # Min, std, max
576 ba5c6c6b Bernardo Dal Seno
    good_values = [
577 ba5c6c6b Bernardo Dal Seno
      (11, 11, 11),
578 ba5c6c6b Bernardo Dal Seno
      (11, 11, 40),
579 ba5c6c6b Bernardo Dal Seno
      (11, 40, 40),
580 ba5c6c6b Bernardo Dal Seno
      ]
581 ba5c6c6b Bernardo Dal Seno
    for (mn, st, mx) in good_values:
582 da5f09ef Bernardo Dal Seno
      minmax = {
583 ba5c6c6b Bernardo Dal Seno
        constants.ISPECS_MIN: {par: mn},
584 ba5c6c6b Bernardo Dal Seno
        constants.ISPECS_MAX: {par: mx},
585 ba5c6c6b Bernardo Dal Seno
        }
586 da5f09ef Bernardo Dal Seno
      stdspec = {par: st}
587 62fed51b Bernardo Dal Seno
      objects.InstancePolicy._CheckISpecParamSyntax(minmax, stdspec, par, True)
588 ba5c6c6b Bernardo Dal Seno
    bad_values = [
589 b342c9dd Bernardo Dal Seno
      (11, 11,  5, True),
590 b342c9dd Bernardo Dal Seno
      (40, 11, 11, True),
591 b342c9dd Bernardo Dal Seno
      (11, 80, 40, False),
592 b342c9dd Bernardo Dal Seno
      (11,  5, 40, False,),
593 b342c9dd Bernardo Dal Seno
      (11,  5,  5, True),
594 b342c9dd Bernardo Dal Seno
      (40, 40, 11, True),
595 ba5c6c6b Bernardo Dal Seno
      ]
596 b342c9dd Bernardo Dal Seno
    for (mn, st, mx, excp) in bad_values:
597 da5f09ef Bernardo Dal Seno
      minmax = {
598 ba5c6c6b Bernardo Dal Seno
        constants.ISPECS_MIN: {par: mn},
599 ba5c6c6b Bernardo Dal Seno
        constants.ISPECS_MAX: {par: mx},
600 ba5c6c6b Bernardo Dal Seno
        }
601 da5f09ef Bernardo Dal Seno
      stdspec = {par: st}
602 b342c9dd Bernardo Dal Seno
      if excp:
603 b342c9dd Bernardo Dal Seno
        self.assertRaises(errors.ConfigurationError,
604 b342c9dd Bernardo Dal Seno
                          objects.InstancePolicy._CheckISpecParamSyntax,
605 b342c9dd Bernardo Dal Seno
                          minmax, stdspec, par, True)
606 b342c9dd Bernardo Dal Seno
      else:
607 b342c9dd Bernardo Dal Seno
        ret = objects.InstancePolicy._CheckISpecParamSyntax(minmax, stdspec,
608 b342c9dd Bernardo Dal Seno
                                                            par, True)
609 b342c9dd Bernardo Dal Seno
        self.assertFalse(ret)
610 ba5c6c6b Bernardo Dal Seno
611 ba5c6c6b Bernardo Dal Seno
  def testCheckDiskTemplates(self):
612 ba5c6c6b Bernardo Dal Seno
    invalid = "this_is_not_a_good_template"
613 ba5c6c6b Bernardo Dal Seno
    for dt in constants.DISK_TEMPLATES:
614 ba5c6c6b Bernardo Dal Seno
      objects.InstancePolicy.CheckDiskTemplates([dt])
615 ba5c6c6b Bernardo Dal Seno
    objects.InstancePolicy.CheckDiskTemplates(list(constants.DISK_TEMPLATES))
616 ba5c6c6b Bernardo Dal Seno
    bad_examples = [
617 ba5c6c6b Bernardo Dal Seno
      [invalid],
618 ba5c6c6b Bernardo Dal Seno
      [constants.DT_DRBD8, invalid],
619 ba5c6c6b Bernardo Dal Seno
      list(constants.DISK_TEMPLATES) + [invalid],
620 ba5c6c6b Bernardo Dal Seno
      [],
621 ba5c6c6b Bernardo Dal Seno
      None,
622 ba5c6c6b Bernardo Dal Seno
      ]
623 ba5c6c6b Bernardo Dal Seno
    for dtl in bad_examples:
624 ba5c6c6b Bernardo Dal Seno
      self.assertRaises(errors.ConfigurationError,
625 ba5c6c6b Bernardo Dal Seno
                        objects.InstancePolicy.CheckDiskTemplates,
626 ba5c6c6b Bernardo Dal Seno
                        dtl)
627 ba5c6c6b Bernardo Dal Seno
628 ba5c6c6b Bernardo Dal Seno
  def testCheckParameterSyntax(self):
629 ba5c6c6b Bernardo Dal Seno
    invalid = "this_key_shouldnt_be_here"
630 ba5c6c6b Bernardo Dal Seno
    for check_std in [True, False]:
631 da5f09ef Bernardo Dal Seno
      objects.InstancePolicy.CheckParameterSyntax({}, check_std)
632 da5f09ef Bernardo Dal Seno
      policy = {invalid: None}
633 ba5c6c6b Bernardo Dal Seno
      self.assertRaises(errors.ConfigurationError,
634 ba5c6c6b Bernardo Dal Seno
                        objects.InstancePolicy.CheckParameterSyntax,
635 ba5c6c6b Bernardo Dal Seno
                        policy, check_std)
636 ba5c6c6b Bernardo Dal Seno
      for par in constants.IPOLICY_PARAMETERS:
637 ba5c6c6b Bernardo Dal Seno
        for val in ("blah", None, {}, [42]):
638 da5f09ef Bernardo Dal Seno
          policy = {par: val}
639 ba5c6c6b Bernardo Dal Seno
          self.assertRaises(errors.ConfigurationError,
640 ba5c6c6b Bernardo Dal Seno
                            objects.InstancePolicy.CheckParameterSyntax,
641 ba5c6c6b Bernardo Dal Seno
                            policy, check_std)
642 ba5c6c6b Bernardo Dal Seno
643 e38bc4eb Bernardo Dal Seno
  def testFillIPolicyEmpty(self):
644 e38bc4eb Bernardo Dal Seno
    policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, {})
645 e38bc4eb Bernardo Dal Seno
    objects.InstancePolicy.CheckParameterSyntax(policy, True)
646 e38bc4eb Bernardo Dal Seno
    self.assertEqual(policy, constants.IPOLICY_DEFAULTS)
647 e38bc4eb Bernardo Dal Seno
648 e38bc4eb Bernardo Dal Seno
  def _AssertISpecsMerged(self, default_spec, diff_spec, merged_spec):
649 e38bc4eb Bernardo Dal Seno
    for (param, value) in merged_spec.items():
650 e38bc4eb Bernardo Dal Seno
      if param in diff_spec:
651 e38bc4eb Bernardo Dal Seno
        self.assertEqual(value, diff_spec[param])
652 e38bc4eb Bernardo Dal Seno
      else:
653 e38bc4eb Bernardo Dal Seno
        self.assertEqual(value, default_spec[param])
654 e38bc4eb Bernardo Dal Seno
655 e38bc4eb Bernardo Dal Seno
  def _AssertIPolicyMerged(self, default_pol, diff_pol, merged_pol):
656 e38bc4eb Bernardo Dal Seno
    for (key, value) in merged_pol.items():
657 e38bc4eb Bernardo Dal Seno
      if key in diff_pol:
658 41044e04 Bernardo Dal Seno
        if key == constants.ISPECS_STD:
659 e38bc4eb Bernardo Dal Seno
          self._AssertISpecsMerged(default_pol[key], diff_pol[key], value)
660 e38bc4eb Bernardo Dal Seno
        else:
661 e38bc4eb Bernardo Dal Seno
          self.assertEqual(value, diff_pol[key])
662 e38bc4eb Bernardo Dal Seno
      else:
663 e38bc4eb Bernardo Dal Seno
        self.assertEqual(value, default_pol[key])
664 e38bc4eb Bernardo Dal Seno
665 e38bc4eb Bernardo Dal Seno
  def testFillIPolicy(self):
666 e38bc4eb Bernardo Dal Seno
    partial_policies = [
667 e38bc4eb Bernardo Dal Seno
      {constants.IPOLICY_VCPU_RATIO: 3.14},
668 e38bc4eb Bernardo Dal Seno
      {constants.IPOLICY_SPINDLE_RATIO: 2.72},
669 e38bc4eb Bernardo Dal Seno
      {constants.IPOLICY_DTS: [constants.DT_FILE]},
670 41044e04 Bernardo Dal Seno
      {constants.ISPECS_STD: {constants.ISPEC_DISK_COUNT: 3}},
671 41044e04 Bernardo Dal Seno
      {constants.ISPECS_MINMAX: [constants.ISPECS_MINMAX_DEFAULTS,
672 41044e04 Bernardo Dal Seno
                                 constants.ISPECS_MINMAX_DEFAULTS]}
673 e38bc4eb Bernardo Dal Seno
      ]
674 e38bc4eb Bernardo Dal Seno
    for diff_pol in partial_policies:
675 e38bc4eb Bernardo Dal Seno
      policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol)
676 e38bc4eb Bernardo Dal Seno
      objects.InstancePolicy.CheckParameterSyntax(policy, True)
677 e38bc4eb Bernardo Dal Seno
      self._AssertIPolicyIsFull(policy)
678 e38bc4eb Bernardo Dal Seno
      self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy)
679 e38bc4eb Bernardo Dal Seno
680 f73f3567 Bernardo Dal Seno
  def testFillIPolicyKeepsUnknown(self):
681 f73f3567 Bernardo Dal Seno
    INVALID_KEY = "invalid_ipolicy_key"
682 f73f3567 Bernardo Dal Seno
    diff_pol = {
683 f73f3567 Bernardo Dal Seno
      INVALID_KEY: None,
684 f73f3567 Bernardo Dal Seno
      }
685 f73f3567 Bernardo Dal Seno
    policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol)
686 f73f3567 Bernardo Dal Seno
    self.assertTrue(INVALID_KEY in policy)
687 f73f3567 Bernardo Dal Seno
688 e38bc4eb Bernardo Dal Seno
689 73d6b4a7 Helga Velroyen
class TestDisk(unittest.TestCase):
690 73d6b4a7 Helga Velroyen
  def addChild(self, disk):
691 73d6b4a7 Helga Velroyen
    """Adds a child of the same device type as the parent."""
692 73d6b4a7 Helga Velroyen
    disk.children = []
693 73d6b4a7 Helga Velroyen
    child = objects.Disk()
694 73d6b4a7 Helga Velroyen
    child.dev_type = disk.dev_type
695 73d6b4a7 Helga Velroyen
    disk.children.append(child)
696 73d6b4a7 Helga Velroyen
697 73d6b4a7 Helga Velroyen
  def testUpgradeConfigDevTypeLegacy(self):
698 73d6b4a7 Helga Velroyen
    for old, new in [("drbd8", constants.DT_DRBD8),
699 73d6b4a7 Helga Velroyen
                     ("lvm", constants.DT_PLAIN)]:
700 73d6b4a7 Helga Velroyen
      disk = objects.Disk()
701 73d6b4a7 Helga Velroyen
      disk.dev_type = old
702 73d6b4a7 Helga Velroyen
      self.addChild(disk)
703 73d6b4a7 Helga Velroyen
      disk.UpgradeConfig()
704 73d6b4a7 Helga Velroyen
      self.assertEqual(new, disk.dev_type)
705 73d6b4a7 Helga Velroyen
      self.assertEqual(new, disk.children[0].dev_type)
706 73d6b4a7 Helga Velroyen
707 73d6b4a7 Helga Velroyen
  def testUpgradeConfigDevTypeLegacyUnchanged(self):
708 73d6b4a7 Helga Velroyen
    dev_types = [constants.DT_FILE, constants.DT_SHARED_FILE,
709 73d6b4a7 Helga Velroyen
                 constants.DT_BLOCK, constants.DT_EXT,
710 8106dd64 Santi Raffa
                 constants.DT_RBD, constants.DT_GLUSTER]
711 73d6b4a7 Helga Velroyen
    for dev_type in dev_types:
712 73d6b4a7 Helga Velroyen
      disk = objects.Disk()
713 73d6b4a7 Helga Velroyen
      disk.dev_type = dev_type
714 73d6b4a7 Helga Velroyen
      self.addChild(disk)
715 73d6b4a7 Helga Velroyen
      disk.UpgradeConfig()
716 73d6b4a7 Helga Velroyen
      self.assertEqual(dev_type, disk.dev_type)
717 73d6b4a7 Helga Velroyen
      self.assertEqual(dev_type, disk.children[0].dev_type)
718 73d6b4a7 Helga Velroyen
719 73d6b4a7 Helga Velroyen
720 285ece5b Santi Raffa
class TestSimpleFillOS(unittest.TestCase):
721 285ece5b Santi Raffa
    # We have to make sure that:
722 285ece5b Santi Raffa
    #  * From within the configuration, variants override defaults
723 285ece5b Santi Raffa
    #  * Temporary values override configuration
724 285ece5b Santi Raffa
    #  * No overlap between public, private and secret dicts is allowed
725 285ece5b Santi Raffa
    #
726 285ece5b Santi Raffa
    # As a result, here are the actors in this test:
727 285ece5b Santi Raffa
    #
728 285ece5b Santi Raffa
    # A:  temporary                 public
729 285ece5b Santi Raffa
    # B:  temporary                        private
730 285ece5b Santi Raffa
    # C:  temporary                                secret
731 285ece5b Santi Raffa
    # X:  temporary                 public private secret
732 285ece5b Santi Raffa
    # D:            configuration   public                       variant
733 285ece5b Santi Raffa
    # E:            configuration   public                  base
734 285ece5b Santi Raffa
    # F:            configuration          private               variant
735 285ece5b Santi Raffa
    # G:            configuration          private          base
736 285ece5b Santi Raffa
    #
737 285ece5b Santi Raffa
    # Every time a param is assigned "ERROR", we expect FillOSParams to override
738 285ece5b Santi Raffa
    # it. If it doesn't, it's an error.
739 285ece5b Santi Raffa
    #
740 285ece5b Santi Raffa
    # Every time a param is assigned itself as a value, it's the value we expect
741 285ece5b Santi Raffa
    # FillOSParams to give us back.
742 285ece5b Santi Raffa
743 285ece5b Santi Raffa
    def setUp(self):
744 285ece5b Santi Raffa
      self.fake_cl = objects.Cluster()
745 285ece5b Santi Raffa
      self.fake_cl.UpgradeConfig()
746 285ece5b Santi Raffa
      self.fake_cl.osparams = {"os": {"A": "ERROR",
747 285ece5b Santi Raffa
                                      "D": "ERROR",
748 285ece5b Santi Raffa
                                      "E": "E"},
749 285ece5b Santi Raffa
                               "os+a": {"D": "D"}}
750 285ece5b Santi Raffa
      self.fake_cl.osparams_private_cluster = {"os": {"B": "ERROR",
751 285ece5b Santi Raffa
                                                      "F": "ERROR",
752 285ece5b Santi Raffa
                                                      "G": "G"},
753 285ece5b Santi Raffa
                                               "os+a": {"F": "F"}}
754 285ece5b Santi Raffa
755 285ece5b Santi Raffa
    def testConflictPublicPrivate(self):
756 285ece5b Santi Raffa
      "Make sure we disallow attempts to override params based on visibility."
757 285ece5b Santi Raffa
      public_dict = {"A": "A", "X": "X"}
758 285ece5b Santi Raffa
      private_dict = {"B": "B", "X": "X"}
759 285ece5b Santi Raffa
      secret_dict = {"C": "C"}
760 285ece5b Santi Raffa
      dicts_pp = (public_dict, private_dict)
761 285ece5b Santi Raffa
      dicts_pps = (public_dict, private_dict, secret_dict)
762 285ece5b Santi Raffa
763 285ece5b Santi Raffa
      # Without secret parameters
764 285ece5b Santi Raffa
      self.assertRaises(errors.OpPrereqError,
765 285ece5b Santi Raffa
                        lambda: self.fake_cl.SimpleFillOS("os+a", *dicts_pp))
766 285ece5b Santi Raffa
767 285ece5b Santi Raffa
      # but also with those.
768 285ece5b Santi Raffa
      self.assertRaises(errors.OpPrereqError,
769 285ece5b Santi Raffa
                        lambda: self.fake_cl.SimpleFillOS("os+a", *dicts_pps))
770 285ece5b Santi Raffa
771 285ece5b Santi Raffa
    def testConflictPublicSecret(self):
772 285ece5b Santi Raffa
      "Make sure we disallow attempts to override params based on visibility."
773 285ece5b Santi Raffa
      public_dict = {"A": "A", "X": "X"}
774 285ece5b Santi Raffa
      private_dict = {"B": "B"}
775 285ece5b Santi Raffa
      secret_dict = {"C": "C", "X": "X"}
776 285ece5b Santi Raffa
      dicts_pps = (public_dict, private_dict, secret_dict)
777 285ece5b Santi Raffa
778 285ece5b Santi Raffa
      self.assertRaises(errors.OpPrereqError,
779 285ece5b Santi Raffa
                        lambda: self.fake_cl.SimpleFillOS("os+a", *dicts_pps))
780 285ece5b Santi Raffa
781 285ece5b Santi Raffa
    def testConflictPrivateSecret(self):
782 285ece5b Santi Raffa
      "Make sure we disallow attempts to override params based on visibility."
783 285ece5b Santi Raffa
      public_dict = {"A": "A"}
784 285ece5b Santi Raffa
      private_dict = {"B": "B", "X": "X"}
785 285ece5b Santi Raffa
      secret_dict = {"C": "C", "X": "X"}
786 285ece5b Santi Raffa
      dicts_pps = (public_dict, private_dict, secret_dict)
787 285ece5b Santi Raffa
788 285ece5b Santi Raffa
      self.assertRaises(errors.OpPrereqError,
789 285ece5b Santi Raffa
                        lambda: self.fake_cl.SimpleFillOS("os+a", *dicts_pps))
790 285ece5b Santi Raffa
791 285ece5b Santi Raffa
    def testValidValues(self):
792 285ece5b Santi Raffa
      "Make sure we handle all overriding we do allow correctly."
793 285ece5b Santi Raffa
      public_dict = {"A": "A"}
794 285ece5b Santi Raffa
      private_dict = {"B": "B"}
795 285ece5b Santi Raffa
      secret_dict = {"C": "C"}
796 285ece5b Santi Raffa
      dicts_p = (public_dict,)
797 285ece5b Santi Raffa
      dicts_pp = (public_dict, private_dict)
798 285ece5b Santi Raffa
      dicts_pps = (public_dict, private_dict, secret_dict)
799 285ece5b Santi Raffa
      expected_keys_p = ("A", "D", "E") # nothing private, secret
800 285ece5b Santi Raffa
      expected_keys_pp = ("A", "B", "D", "E", "F", "G") # nothing secret
801 285ece5b Santi Raffa
      expected_keys_pps = ("A", "B", "C", "D", "E", "F", "G") # all of them
802 285ece5b Santi Raffa
803 285ece5b Santi Raffa
      for (dicts, expected_keys) in [(dicts_p, expected_keys_p),
804 285ece5b Santi Raffa
                                     (dicts_pp, expected_keys_pp),
805 285ece5b Santi Raffa
                                     (dicts_pps, expected_keys_pps)]:
806 285ece5b Santi Raffa
        result = self.fake_cl.SimpleFillOS("os+a", *dicts)
807 285ece5b Santi Raffa
        # Values
808 285ece5b Santi Raffa
        for key in result:
809 285ece5b Santi Raffa
          if not result[key] == key:
810 285ece5b Santi Raffa
            self.fail("Invalid public-private fill with input:\n%s\n%s"
811 285ece5b Santi Raffa
                      % (pprint.pformat(dicts), result))
812 285ece5b Santi Raffa
        # Completeness
813 285ece5b Santi Raffa
        if set(result) != set(expected_keys):
814 285ece5b Santi Raffa
          self.fail("Problem with key %s from merge result of:\n%s\n%s"
815 285ece5b Santi Raffa
                    % (set(expected_keys) ^ set(result), # symmetric difference
816 285ece5b Santi Raffa
                       pprint.pformat(dicts),
817 285ece5b Santi Raffa
                       result))
818 285ece5b Santi Raffa
819 2f96c43c Michael Hanselmann
if __name__ == "__main__":
820 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()