Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.masterd.iallocator_unittest.py @ 6d11529e

History | View | Annotate | Download (6.8 kB)

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

    
4
# Copyright (C) 2012 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 ganeti.masterd.iallocator"""
23

    
24
import unittest
25

    
26
from ganeti import compat
27
from ganeti import constants
28
from ganeti import errors
29
from ganeti import objects
30
from ganeti import ht
31
from ganeti.masterd import iallocator
32

    
33
import testutils
34

    
35

    
36
class _StubIAllocator(object):
37
  def __init__(self, success):
38
    self.success = success
39

    
40

    
41
class TestIAReqMultiInstanceAlloc(unittest.TestCase):
42
  def testResult(self):
43
    good_results = [
44
      # First result (all instances "allocate")
45
      [
46
        [["foo", ["a", "b"]],
47
         ["bar", ["c"]],
48
         ["baz", []]],
49
        []
50
      ],
51
      # Second result (partial "allocate", partial "fail")
52
      [
53
        [["bar", ["c", "b"]],
54
         ["baz", ["a"]]],
55
        ["foo"]
56
      ],
57
      # Third result (all instances "fail")
58
      [
59
        [],
60
        ["foo", "bar", "baz"]
61
      ],
62
      ]
63
    bad_results = [
64
      "foobar",
65
      1234,
66
      [],
67
      [[]],
68
      [[], [], []],
69
      ]
70

    
71
    result_fn = iallocator.IAReqMultiInstanceAlloc.REQ_RESULT
72

    
73
    self.assertTrue(compat.all(map(result_fn, good_results)))
74
    self.assertFalse(compat.any(map(result_fn, bad_results)))
75

    
76

    
77
class TestIARequestBase(unittest.TestCase):
78
  def testValidateResult(self):
79
    class _StubReqBase(iallocator.IARequestBase):
80
      MODE = constants.IALLOCATOR_MODE_ALLOC
81
      REQ_RESULT = ht.TBool
82

    
83
    stub = _StubReqBase()
84
    stub.ValidateResult(_StubIAllocator(True), True)
85
    self.assertRaises(errors.ResultValidationError, stub.ValidateResult,
86
                      _StubIAllocator(True), "foo")
87
    stub.ValidateResult(_StubIAllocator(False), True)
88
    # We don't validate the result if the iallocation request was not successful
89
    stub.ValidateResult(_StubIAllocator(False), "foo")
90

    
91

    
92
class _FakeConfigWithNdParams:
93
  def GetNdParams(self, _):
94
    return None
95

    
96

    
97
class TestComputeBasicNodeData(unittest.TestCase):
98
  def setUp(self):
99
    self.fn = compat.partial(iallocator.IAllocator._ComputeBasicNodeData,
100
                             _FakeConfigWithNdParams())
101

    
102
  def testEmpty(self):
103
    self.assertEqual(self.fn({}, None), {})
104

    
105
  def testSimple(self):
106
    node1 = objects.Node(name="node1",
107
                         primary_ip="192.0.2.1",
108
                         secondary_ip="192.0.2.2",
109
                         offline=False,
110
                         drained=False,
111
                         master_candidate=True,
112
                         master_capable=True,
113
                         group="11112222",
114
                         vm_capable=False)
115

    
116
    node2 = objects.Node(name="node2",
117
                         primary_ip="192.0.2.3",
118
                         secondary_ip="192.0.2.4",
119
                         offline=True,
120
                         drained=False,
121
                         master_candidate=False,
122
                         master_capable=False,
123
                         group="11112222",
124
                         vm_capable=True)
125

    
126
    assert node1 != node2
127

    
128
    ninfo = {
129
      "#unused-1#": node1,
130
      "#unused-2#": node2,
131
      }
132

    
133
    self.assertEqual(self.fn(ninfo, None), {
134
      "node1": {
135
        "tags": [],
136
        "primary_ip": "192.0.2.1",
137
        "secondary_ip": "192.0.2.2",
138
        "offline": False,
139
        "drained": False,
140
        "master_candidate": True,
141
        "group": "11112222",
142
        "master_capable": True,
143
        "vm_capable": False,
144
        "ndparams": None,
145
        },
146
      "node2": {
147
        "tags": [],
148
        "primary_ip": "192.0.2.3",
149
        "secondary_ip": "192.0.2.4",
150
        "offline": True,
151
        "drained": False,
152
        "master_candidate": False,
153
        "group": "11112222",
154
        "master_capable": False,
155
        "vm_capable": True,
156
        "ndparams": None,
157
        },
158
      })
159

    
160
  def testOfflineNode(self):
161
    for whitelist in [None, [], set(), ["node1"], ["node2"]]:
162
      result = self.fn({
163
        "node1": objects.Node(name="node1", offline=True)
164
        }, whitelist)
165
      self.assertEqual(len(result), 1)
166
      self.assertTrue(result["node1"]["offline"])
167

    
168
  def testWhitelist(self):
169
    for whitelist in [None, [], set(), ["node1"], ["node2"]]:
170
      result = self.fn({
171
        "node1": objects.Node(name="node1", offline=False)
172
        }, whitelist)
173
      self.assertEqual(len(result), 1)
174

    
175
      if whitelist is None or "node1" in whitelist:
176
        self.assertFalse(result["node1"]["offline"])
177
      else:
178
        self.assertTrue(result["node1"]["offline"])
179

    
180
class TestProcessStorageInfo(unittest.TestCase):
181

    
182
  def setUp(self):
183
    self.free_storage_file = 23
184
    self.total_storage_file = 42
185
    self.free_storage_lvm = 69
186
    self.total_storage_lvm = 666
187
    self.space_info = [{"name": "mynode",
188
                       "type": constants.ST_FILE,
189
                       "storage_free": self.free_storage_file,
190
                       "storage_size": self.total_storage_file},
191
                      {"name": "mynode",
192
                       "type": constants.ST_LVM_VG,
193
                       "storage_free": self.free_storage_lvm,
194
                       "storage_size": self.total_storage_lvm},
195
                      {"name": "mynode",
196
                       "type": constants.ST_LVM_PV,
197
                       "storage_free": 33,
198
                       "storage_size": 44}]
199

    
200
  def testComputeStorageDataFromNodeInfoDefault(self):
201
    has_lvm = False
202
    node_name = "mynode"
203
    (total_disk, free_disk, total_spindles, free_spindles) = \
204
        iallocator.IAllocator._ComputeStorageDataFromSpaceInfo(
205
            self.space_info, node_name, has_lvm)
206
    # FIXME: right now, iallocator ignores anything else than LVM, adjust
207
    # this test once that arbitrary storage is supported
208
    self.assertEqual(0, free_disk)
209
    self.assertEqual(0, total_disk)
210

    
211
  def testComputeStorageDataFromNodeInfoLvm(self):
212
    has_lvm = True
213
    node_name = "mynode"
214
    (total_disk, free_disk, total_spindles, free_spindles) = \
215
        iallocator.IAllocator._ComputeStorageDataFromSpaceInfo(
216
            self.space_info, node_name, has_lvm)
217
    self.assertEqual(self.free_storage_lvm, free_disk)
218
    self.assertEqual(self.total_storage_lvm, total_disk)
219

    
220

    
221
if __name__ == "__main__":
222
  testutils.GanetiTestProgram()