Statistics
| Branch: | Tag: | Revision:

root / test / py / qa.qa_config_unittest.py @ 6a654276

History | View | Annotate | Download (8.4 kB)

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

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

    
21

    
22
"""Script for testing qa.qa_config"""
23

    
24
import unittest
25
import tempfile
26
import shutil
27
import os
28
import operator
29

    
30
from ganeti import utils
31
from ganeti import serializer
32
from ganeti import constants
33
from ganeti import compat
34

    
35
from qa import qa_config
36
from qa import qa_error
37

    
38
import testutils
39

    
40

    
41
class TestTestEnabled(unittest.TestCase):
42
  def testSimple(self):
43
    for name in ["test", ["foobar"], ["a", "b"]]:
44
      self.assertTrue(qa_config.TestEnabled(name, _cfg={}))
45

    
46
    for default in [False, True]:
47
      self.assertFalse(qa_config.TestEnabled("foo", _cfg={
48
        "tests": {
49
          "default": default,
50
          "foo": False,
51
          },
52
        }))
53

    
54
      self.assertTrue(qa_config.TestEnabled("bar", _cfg={
55
        "tests": {
56
          "default": default,
57
          "bar": True,
58
          },
59
        }))
60

    
61
  def testEitherWithDefault(self):
62
    names = qa_config.Either("one")
63

    
64
    self.assertTrue(qa_config.TestEnabled(names, _cfg={
65
      "tests": {
66
        "default": True,
67
        },
68
      }))
69

    
70
    self.assertFalse(qa_config.TestEnabled(names, _cfg={
71
      "tests": {
72
        "default": False,
73
        },
74
      }))
75

    
76
  def testEither(self):
77
    names = [qa_config.Either(["one", "two"]),
78
             qa_config.Either("foo"),
79
             "hello",
80
             ["bar", "baz"]]
81

    
82
    self.assertTrue(qa_config.TestEnabled(names, _cfg={
83
      "tests": {
84
        "default": True,
85
        },
86
      }))
87

    
88
    self.assertFalse(qa_config.TestEnabled(names, _cfg={
89
      "tests": {
90
        "default": False,
91
        },
92
      }))
93

    
94
    for name in ["foo", "bar", "baz", "hello"]:
95
      self.assertFalse(qa_config.TestEnabled(names, _cfg={
96
        "tests": {
97
          "default": True,
98
          name: False,
99
          },
100
        }))
101

    
102
    self.assertFalse(qa_config.TestEnabled(names, _cfg={
103
      "tests": {
104
        "default": True,
105
        "one": False,
106
        "two": False,
107
        },
108
      }))
109

    
110
    self.assertTrue(qa_config.TestEnabled(names, _cfg={
111
      "tests": {
112
        "default": True,
113
        "one": False,
114
        "two": True,
115
        },
116
      }))
117

    
118
    self.assertFalse(qa_config.TestEnabled(names, _cfg={
119
      "tests": {
120
        "default": True,
121
        "one": True,
122
        "two": True,
123
        "foo": False,
124
        },
125
      }))
126

    
127
  def testEitherNestedWithAnd(self):
128
    names = qa_config.Either([["one", "two"], "foo"])
129

    
130
    self.assertTrue(qa_config.TestEnabled(names, _cfg={
131
      "tests": {
132
        "default": True,
133
        },
134
      }))
135

    
136
    for name in ["one", "two"]:
137
      self.assertFalse(qa_config.TestEnabled(names, _cfg={
138
        "tests": {
139
          "default": True,
140
          "foo": False,
141
          name: False,
142
          },
143
        }))
144

    
145

    
146
class TestQaConfigLoad(unittest.TestCase):
147
  def setUp(self):
148
    self.tmpdir = tempfile.mkdtemp()
149

    
150
  def tearDown(self):
151
    shutil.rmtree(self.tmpdir)
152

    
153
  def testLoadNonExistent(self):
154
    filename = utils.PathJoin(self.tmpdir, "does.not.exist")
155
    self.assertRaises(EnvironmentError, qa_config._QaConfig.Load, filename)
156

    
157
  @staticmethod
158
  def _WriteConfig(filename, data):
159
    utils.WriteFile(filename, data=serializer.DumpJson(data))
160

    
161
  def _CheckLoadError(self, filename, data, expected):
162
    self._WriteConfig(filename, data)
163

    
164
    try:
165
      qa_config._QaConfig.Load(filename)
166
    except qa_error.Error, err:
167
      self.assertTrue(str(err).startswith(expected))
168
    else:
169
      self.fail("Exception was not raised")
170

    
171
  def testFailsValidation(self):
172
    filename = utils.PathJoin(self.tmpdir, "qa.json")
173
    testconfig = {}
174

    
175
    check_fn = compat.partial(self._CheckLoadError, filename, testconfig)
176

    
177
    # No nodes
178
    check_fn("Need at least one node")
179

    
180
    testconfig["nodes"] = [
181
      {
182
        "primary": "xen-test-0",
183
        "secondary": "192.0.2.1",
184
        },
185
      ]
186

    
187
    # No instances
188
    check_fn("Need at least one instance")
189

    
190
    testconfig["instances"] = [
191
      {
192
        "name": "xen-test-inst1",
193
        },
194
      ]
195

    
196
    # Missing "disk" and "disk-growth"
197
    check_fn("Config options 'disk' and 'disk-growth' ")
198

    
199
    testconfig["disk"] = []
200
    testconfig["disk-growth"] = testconfig["disk"]
201

    
202
    # Minimal accepted configuration
203
    self._WriteConfig(filename, testconfig)
204
    result = qa_config._QaConfig.Load(filename)
205
    self.assertTrue(result.get("nodes"))
206

    
207
    # Non-existent instance check script
208
    testconfig[qa_config._INSTANCE_CHECK_KEY] = \
209
      utils.PathJoin(self.tmpdir, "instcheck")
210
    check_fn("Can't find instance check script")
211
    del testconfig[qa_config._INSTANCE_CHECK_KEY]
212

    
213
    # No enabled hypervisor
214
    testconfig[qa_config._ENABLED_HV_KEY] = None
215
    check_fn("No hypervisor is enabled")
216

    
217
    # Unknown hypervisor
218
    testconfig[qa_config._ENABLED_HV_KEY] = ["#unknownhv#"]
219
    check_fn("Unknown hypervisor(s) enabled:")
220

    
221

    
222
class TestQaConfigWithSampleConfig(unittest.TestCase):
223
  """Tests using C{qa-sample.json}.
224

225
  This test case serves two purposes:
226

227
    - Ensure shipped C{qa-sample.json} file is considered a valid QA
228
      configuration
229
    - Test some functions of L{qa_config._QaConfig} without having to
230
      mock a whole configuration file
231

232
  """
233
  def setUp(self):
234
    filename = "%s/qa/qa-sample.json" % testutils.GetSourceDir()
235

    
236
    self.config = qa_config._QaConfig.Load(filename)
237

    
238
  def testGetEnabledHypervisors(self):
239
    self.assertEqual(self.config.GetEnabledHypervisors(),
240
                     [constants.DEFAULT_ENABLED_HYPERVISOR])
241

    
242
  def testGetDefaultHypervisor(self):
243
    self.assertEqual(self.config.GetDefaultHypervisor(),
244
                     constants.DEFAULT_ENABLED_HYPERVISOR)
245

    
246
  def testGetInstanceCheckScript(self):
247
    self.assertTrue(self.config.GetInstanceCheckScript() is None)
248

    
249
  def testGetAndGetItem(self):
250
    self.assertEqual(self.config["nodes"], self.config.get("nodes"))
251

    
252
  def testGetMasterNode(self):
253
    self.assertEqual(self.config.GetMasterNode(), self.config["nodes"][0])
254

    
255

    
256
class TestQaConfig(unittest.TestCase):
257
  def setUp(self):
258
    filename = \
259
      testutils.TestDataFilename("qa-minimal-nodes-instances-only.json")
260

    
261
    self.config = qa_config._QaConfig.Load(filename)
262

    
263
  def testExclusiveStorage(self):
264
    self.assertRaises(AssertionError, self.config.GetExclusiveStorage)
265

    
266
    for value in [False, True, 0, 1, 30804, ""]:
267
      self.config.SetExclusiveStorage(value)
268
      self.assertEqual(self.config.GetExclusiveStorage(), bool(value))
269

    
270
      for template in constants.DISK_TEMPLATES:
271
        if value and template not in constants.DTS_EXCL_STORAGE:
272
          self.assertFalse(self.config.IsTemplateSupported(template))
273
        else:
274
          self.assertTrue(self.config.IsTemplateSupported(template))
275

    
276
  def testInstanceConversion(self):
277
    self.assertTrue(isinstance(self.config["instances"][0],
278
                               qa_config._QaInstance))
279

    
280
  def testAcquireAndReleaseInstance(self):
281
    self.assertFalse(compat.any(map(operator.attrgetter("used"),
282
                                    self.config["instances"])))
283

    
284
    inst = qa_config.AcquireInstance(_cfg=self.config)
285
    self.assertTrue(inst.used)
286
    self.assertTrue(inst.disk_template is None)
287

    
288
    qa_config.ReleaseInstance(inst)
289

    
290
    self.assertFalse(inst.used)
291
    self.assertTrue(inst.disk_template is None)
292

    
293
    self.assertFalse(compat.any(map(operator.attrgetter("used"),
294
                                    self.config["instances"])))
295

    
296
  def testAcquireInstanceTooMany(self):
297
    # Acquire all instances
298
    for _ in range(len(self.config["instances"])):
299
      inst = qa_config.AcquireInstance(_cfg=self.config)
300
      self.assertTrue(inst.used)
301
      self.assertTrue(inst.disk_template is None)
302

    
303
    # The next acquisition must fail
304
    self.assertRaises(qa_error.OutOfInstancesError,
305
                      qa_config.AcquireInstance, _cfg=self.config)
306

    
307

    
308
if __name__ == "__main__":
309
  testutils.GanetiTestProgram()