Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.masterd.iallocator_unittest.py @ 20529708

History | View | Annotate | Download (7 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
import mock
26

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

    
35
import testutils
36

    
37

    
38
class _StubIAllocator(object):
39
  def __init__(self, success):
40
    self.success = success
41

    
42

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

    
73
    result_fn = iallocator.IAReqMultiInstanceAlloc.REQ_RESULT
74

    
75
    self.assertTrue(compat.all(map(result_fn, good_results)))
76
    self.assertFalse(compat.any(map(result_fn, bad_results)))
77

    
78

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

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

    
93

    
94
class _FakeConfigWithNdParams:
95
  def GetNdParams(self, _):
96
    return None
97

    
98

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

    
104
  def testEmpty(self):
105
    self.assertEqual(self.fn({}, None), {})
106

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

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

    
128
    assert node1 != node2
129

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

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

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

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

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

    
182
class TestProcessStorageInfo(unittest.TestCase):
183

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

    
203
  def testComputeStorageDataLvm(self):
204
    has_lvm = True
205
    node_name = "mynode"
206
    remote_info = rpc.MakeLegacyNodeInfo(self.node_info,
207
                                         require_vg_info=has_lvm)
208
    (total_disk, free_disk, total_spindles, free_spindles) = \
209
      iallocator.IAllocator._ComputeStorageData(remote_info, node_name, has_lvm)
210
    self.assertEqual(self.free_storage_lvm, free_disk)
211
    self.assertEqual(self.total_storage_lvm, total_disk)
212

    
213
  def testComputeStorageDataDefault(self):
214
    has_lvm = False
215
    node_name = "mynode"
216
    remote_info = rpc.MakeLegacyNodeInfo(self.node_info,
217
                                         require_vg_info=has_lvm)
218
    (total_disk, free_disk, total_spindles, free_spindles) = \
219
      iallocator.IAllocator._ComputeStorageData(remote_info, node_name, has_lvm)
220
    # FIXME: right now, iallocator ignores anything else than LVM, adjust
221
    # this test once that arbitrary storage is supported
222
    self.assertEqual(0, free_disk)
223
    self.assertEqual(0, total_disk)
224

    
225

    
226
if __name__ == "__main__":
227
  testutils.GanetiTestProgram()