Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.cmdlib_unittest.py @ cd3b4ff4

History | View | Annotate | Download (70.8 kB)

1 6de7c41d Iustin Pop
#!/usr/bin/python
2 6de7c41d Iustin Pop
#
3 6de7c41d Iustin Pop
4 da5f09ef Bernardo Dal Seno
# Copyright (C) 2008, 2011, 2012, 2013 Google Inc.
5 6de7c41d Iustin Pop
#
6 6de7c41d Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 6de7c41d Iustin Pop
# it under the terms of the GNU General Public License as published by
8 6de7c41d Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 6de7c41d Iustin Pop
# (at your option) any later version.
10 6de7c41d Iustin Pop
#
11 6de7c41d Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 6de7c41d Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 6de7c41d Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 6de7c41d Iustin Pop
# General Public License for more details.
15 6de7c41d Iustin Pop
#
16 6de7c41d Iustin Pop
# You should have received a copy of the GNU General Public License
17 6de7c41d Iustin Pop
# along with this program; if not, write to the Free Software
18 6de7c41d Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 fd7b69c0 Michael Hanselmann
# 02110-1301, USA.
20 6de7c41d Iustin Pop
21 6de7c41d Iustin Pop
22 6de7c41d Iustin Pop
"""Script for unittesting the cmdlib module"""
23 6de7c41d Iustin Pop
24 6de7c41d Iustin Pop
25 6de7c41d Iustin Pop
import os
26 6de7c41d Iustin Pop
import unittest
27 b98bf262 Michael Hanselmann
import tempfile
28 b98bf262 Michael Hanselmann
import shutil
29 64c7b383 Michael Hanselmann
import operator
30 d755483c Michael Hanselmann
import itertools
31 99ccf8b9 René Nussbaumer
import copy
32 6de7c41d Iustin Pop
33 83f72637 Michael Hanselmann
from ganeti import constants
34 b8812691 Iustin Pop
from ganeti import mcpu
35 6de7c41d Iustin Pop
from ganeti import cmdlib
36 7352d33b Thomas Thrainer
from ganeti.cmdlib import cluster
37 f380d53c Thomas Thrainer
from ganeti.cmdlib import group
38 22b7f6f8 Thomas Thrainer
from ganeti.cmdlib import instance
39 763ad5be Thomas Thrainer
from ganeti.cmdlib import instance_storage
40 763ad5be Thomas Thrainer
from ganeti.cmdlib import instance_utils
41 7352d33b Thomas Thrainer
from ganeti.cmdlib import common
42 ec3cc4a8 Thomas Thrainer
from ganeti.cmdlib import query
43 b8812691 Iustin Pop
from ganeti import opcodes
44 6de7c41d Iustin Pop
from ganeti import errors
45 b8812691 Iustin Pop
from ganeti import utils
46 e58f87a9 Michael Hanselmann
from ganeti import luxi
47 65e183af Michael Hanselmann
from ganeti import ht
48 8ec505dd Adeodato Simo
from ganeti import objects
49 170b02b7 Michael Hanselmann
from ganeti import compat
50 170b02b7 Michael Hanselmann
from ganeti import rpc
51 ef86bf28 Michael Hanselmann
from ganeti import locking
52 a56625a2 Michael Hanselmann
from ganeti import pathutils
53 0fcd0cad René Nussbaumer
from ganeti.masterd import iallocator
54 0ad1ea40 Guido Trotter
from ganeti.hypervisor import hv_xen
55 6de7c41d Iustin Pop
56 25231ec5 Michael Hanselmann
import testutils
57 bd5f214b Apollon Oikonomopoulos
import mocks
58 25231ec5 Michael Hanselmann
59 6de7c41d Iustin Pop
60 b98bf262 Michael Hanselmann
class TestCertVerification(testutils.GanetiTestCase):
61 b98bf262 Michael Hanselmann
  def setUp(self):
62 b98bf262 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
63 b98bf262 Michael Hanselmann
64 b98bf262 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
65 b98bf262 Michael Hanselmann
66 b98bf262 Michael Hanselmann
  def tearDown(self):
67 b98bf262 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
68 b98bf262 Michael Hanselmann
69 b98bf262 Michael Hanselmann
  def testVerifyCertificate(self):
70 7352d33b Thomas Thrainer
    cluster._VerifyCertificate(testutils.TestDataFilename("cert1.pem"))
71 b98bf262 Michael Hanselmann
72 b98bf262 Michael Hanselmann
    nonexist_filename = os.path.join(self.tmpdir, "does-not-exist")
73 b98bf262 Michael Hanselmann
74 7352d33b Thomas Thrainer
    (errcode, msg) = cluster._VerifyCertificate(nonexist_filename)
75 7352d33b Thomas Thrainer
    self.assertEqual(errcode, cluster.LUClusterVerifyConfig.ETYPE_ERROR)
76 b98bf262 Michael Hanselmann
77 b98bf262 Michael Hanselmann
    # Try to load non-certificate file
78 00ef625c Michael Hanselmann
    invalid_cert = testutils.TestDataFilename("bdev-net.txt")
79 7352d33b Thomas Thrainer
    (errcode, msg) = cluster._VerifyCertificate(invalid_cert)
80 7352d33b Thomas Thrainer
    self.assertEqual(errcode, cluster.LUClusterVerifyConfig.ETYPE_ERROR)
81 b98bf262 Michael Hanselmann
82 b98bf262 Michael Hanselmann
83 b8812691 Iustin Pop
class TestOpcodeParams(testutils.GanetiTestCase):
84 b8812691 Iustin Pop
  def testParamsStructures(self):
85 b8812691 Iustin Pop
    for op in sorted(mcpu.Processor.DISPATCH_TABLE):
86 b8812691 Iustin Pop
      lu = mcpu.Processor.DISPATCH_TABLE[op]
87 b8812691 Iustin Pop
      lu_name = lu.__name__
88 0bff0b12 Michael Hanselmann
      self.failIf(hasattr(lu, "_OP_REQP"),
89 0bff0b12 Michael Hanselmann
                  msg=("LU '%s' has old-style _OP_REQP" % lu_name))
90 0bff0b12 Michael Hanselmann
      self.failIf(hasattr(lu, "_OP_DEFS"),
91 0bff0b12 Michael Hanselmann
                  msg=("LU '%s' has old-style _OP_DEFS" % lu_name))
92 0bff0b12 Michael Hanselmann
      self.failIf(hasattr(lu, "_OP_PARAMS"),
93 0bff0b12 Michael Hanselmann
                  msg=("LU '%s' has old-style _OP_PARAMS" % lu_name))
94 b8812691 Iustin Pop
95 b8812691 Iustin Pop
96 bd5f214b Apollon Oikonomopoulos
class TestIAllocatorChecks(testutils.GanetiTestCase):
97 bd5f214b Apollon Oikonomopoulos
  def testFunction(self):
98 bd5f214b Apollon Oikonomopoulos
    class TestLU(object):
99 bd5f214b Apollon Oikonomopoulos
      def __init__(self, opcode):
100 bd5f214b Apollon Oikonomopoulos
        self.cfg = mocks.FakeConfig()
101 bd5f214b Apollon Oikonomopoulos
        self.op = opcode
102 bd5f214b Apollon Oikonomopoulos
103 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
104 ff0d18e6 Iustin Pop
       OP_PARAMS = [
105 197b323b Michael Hanselmann
        ("iallocator", None, ht.NoType, None),
106 197b323b Michael Hanselmann
        ("node", None, ht.NoType, None),
107 65e183af Michael Hanselmann
        ]
108 bd5f214b Apollon Oikonomopoulos
109 bd5f214b Apollon Oikonomopoulos
    default_iallocator = mocks.FakeConfig().GetDefaultIAllocator()
110 bd5f214b Apollon Oikonomopoulos
    other_iallocator = default_iallocator + "_not"
111 bd5f214b Apollon Oikonomopoulos
112 ff0d18e6 Iustin Pop
    op = OpTest()
113 bd5f214b Apollon Oikonomopoulos
    lu = TestLU(op)
114 bd5f214b Apollon Oikonomopoulos
115 5eacbcae Thomas Thrainer
    c_i = lambda: common.CheckIAllocatorOrNode(lu, "iallocator", "node")
116 bd5f214b Apollon Oikonomopoulos
117 bd5f214b Apollon Oikonomopoulos
    # Neither node nor iallocator given
118 43a8f36a Bernardo Dal Seno
    for n in (None, []):
119 43a8f36a Bernardo Dal Seno
      op.iallocator = None
120 43a8f36a Bernardo Dal Seno
      op.node = n
121 43a8f36a Bernardo Dal Seno
      c_i()
122 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.iallocator, default_iallocator)
123 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.node, n)
124 bd5f214b Apollon Oikonomopoulos
125 bd5f214b Apollon Oikonomopoulos
    # Both, iallocator and node given
126 43a8f36a Bernardo Dal Seno
    for a in ("test", constants.DEFAULT_IALLOCATOR_SHORTCUT):
127 43a8f36a Bernardo Dal Seno
      op.iallocator = a
128 43a8f36a Bernardo Dal Seno
      op.node = "test"
129 43a8f36a Bernardo Dal Seno
      self.assertRaises(errors.OpPrereqError, c_i)
130 bd5f214b Apollon Oikonomopoulos
131 bd5f214b Apollon Oikonomopoulos
    # Only iallocator given
132 43a8f36a Bernardo Dal Seno
    for n in (None, []):
133 43a8f36a Bernardo Dal Seno
      op.iallocator = other_iallocator
134 43a8f36a Bernardo Dal Seno
      op.node = n
135 43a8f36a Bernardo Dal Seno
      c_i()
136 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.iallocator, other_iallocator)
137 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.node, n)
138 bd5f214b Apollon Oikonomopoulos
139 bd5f214b Apollon Oikonomopoulos
    # Only node given
140 bd5f214b Apollon Oikonomopoulos
    op.iallocator = None
141 bd5f214b Apollon Oikonomopoulos
    op.node = "node"
142 bd5f214b Apollon Oikonomopoulos
    c_i()
143 bd5f214b Apollon Oikonomopoulos
    self.assertEqual(lu.op.iallocator, None)
144 bd5f214b Apollon Oikonomopoulos
    self.assertEqual(lu.op.node, "node")
145 bd5f214b Apollon Oikonomopoulos
146 43a8f36a Bernardo Dal Seno
    # Asked for default iallocator, no node given
147 43a8f36a Bernardo Dal Seno
    op.iallocator = constants.DEFAULT_IALLOCATOR_SHORTCUT
148 43a8f36a Bernardo Dal Seno
    op.node = None
149 43a8f36a Bernardo Dal Seno
    c_i()
150 43a8f36a Bernardo Dal Seno
    self.assertEqual(lu.op.iallocator, default_iallocator)
151 43a8f36a Bernardo Dal Seno
    self.assertEqual(lu.op.node, None)
152 43a8f36a Bernardo Dal Seno
153 bd5f214b Apollon Oikonomopoulos
    # No node, iallocator or default iallocator
154 bd5f214b Apollon Oikonomopoulos
    op.iallocator = None
155 bd5f214b Apollon Oikonomopoulos
    op.node = None
156 bd5f214b Apollon Oikonomopoulos
    lu.cfg.GetDefaultIAllocator = lambda: None
157 bd5f214b Apollon Oikonomopoulos
    self.assertRaises(errors.OpPrereqError, c_i)
158 bd5f214b Apollon Oikonomopoulos
159 bd5f214b Apollon Oikonomopoulos
160 b469eb4d Iustin Pop
class TestLUTestJqueue(unittest.TestCase):
161 e58f87a9 Michael Hanselmann
  def test(self):
162 b469eb4d Iustin Pop
    self.assert_(cmdlib.LUTestJqueue._CLIENT_CONNECT_TIMEOUT <
163 e58f87a9 Michael Hanselmann
                 (luxi.WFJC_TIMEOUT * 0.75),
164 e58f87a9 Michael Hanselmann
                 msg=("Client timeout too high, might not notice bugs"
165 e58f87a9 Michael Hanselmann
                      " in WaitForJobChange"))
166 e58f87a9 Michael Hanselmann
167 e58f87a9 Michael Hanselmann
168 83f72637 Michael Hanselmann
class TestLUQuery(unittest.TestCase):
169 83f72637 Michael Hanselmann
  def test(self):
170 ec3cc4a8 Thomas Thrainer
    self.assertEqual(sorted(query._QUERY_IMPL.keys()),
171 abd66bf8 Michael Hanselmann
                     sorted(constants.QR_VIA_OP))
172 83f72637 Michael Hanselmann
173 abd66bf8 Michael Hanselmann
    assert constants.QR_NODE in constants.QR_VIA_OP
174 abd66bf8 Michael Hanselmann
    assert constants.QR_INSTANCE in constants.QR_VIA_OP
175 83f72637 Michael Hanselmann
176 abd66bf8 Michael Hanselmann
    for i in constants.QR_VIA_OP:
177 ec3cc4a8 Thomas Thrainer
      self.assert_(query._GetQueryImplementation(i))
178 83f72637 Michael Hanselmann
179 ec3cc4a8 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, query._GetQueryImplementation,
180 22b7f6f8 Thomas Thrainer
                      "")
181 ec3cc4a8 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, query._GetQueryImplementation,
182 83f72637 Michael Hanselmann
                      "xyz")
183 83f72637 Michael Hanselmann
184 83f72637 Michael Hanselmann
185 934704ae Iustin Pop
class TestLUGroupAssignNodes(unittest.TestCase):
186 8ec505dd Adeodato Simo
187 8ec505dd Adeodato Simo
  def testCheckAssignmentForSplitInstances(self):
188 22b7f6f8 Thomas Thrainer
    node_data = dict((n, objects.Node(name=n, group=g))
189 22b7f6f8 Thomas Thrainer
                     for (n, g) in [("n1a", "g1"), ("n1b", "g1"),
190 22b7f6f8 Thomas Thrainer
                                    ("n2a", "g2"), ("n2b", "g2"),
191 22b7f6f8 Thomas Thrainer
                                    ("n3a", "g3"), ("n3b", "g3"),
192 22b7f6f8 Thomas Thrainer
                                    ("n3c", "g3"),
193 22b7f6f8 Thomas Thrainer
                                    ])
194 8ec505dd Adeodato Simo
195 da4a52a3 Thomas Thrainer
    def Instance(uuid, pnode, snode):
196 8ec505dd Adeodato Simo
      if snode is None:
197 8ec505dd Adeodato Simo
        disks = []
198 8ec505dd Adeodato Simo
        disk_template = constants.DT_DISKLESS
199 8ec505dd Adeodato Simo
      else:
200 cd3b4ff4 Helga Velroyen
        disks = [objects.Disk(dev_type=constants.DT_DRBD8,
201 8ec505dd Adeodato Simo
                              logical_id=[pnode, snode, 1, 17, 17])]
202 8ec505dd Adeodato Simo
        disk_template = constants.DT_DRBD8
203 8ec505dd Adeodato Simo
204 da4a52a3 Thomas Thrainer
      return objects.Instance(name="%s-name" % uuid, uuid="%s" % uuid,
205 da4a52a3 Thomas Thrainer
                              primary_node=pnode, disks=disks,
206 8ec505dd Adeodato Simo
                              disk_template=disk_template)
207 8ec505dd Adeodato Simo
208 da4a52a3 Thomas Thrainer
    instance_data = dict((uuid, Instance(uuid, pnode, snode))
209 da4a52a3 Thomas Thrainer
                         for uuid, pnode, snode in [("inst1a", "n1a", "n1b"),
210 8ec505dd Adeodato Simo
                                                    ("inst1b", "n1b", "n1a"),
211 8ec505dd Adeodato Simo
                                                    ("inst2a", "n2a", "n2b"),
212 8ec505dd Adeodato Simo
                                                    ("inst3a", "n3a", None),
213 8ec505dd Adeodato Simo
                                                    ("inst3b", "n3b", "n1b"),
214 8ec505dd Adeodato Simo
                                                    ("inst3c", "n3b", "n2b"),
215 8ec505dd Adeodato Simo
                                                    ])
216 8ec505dd Adeodato Simo
217 8ec505dd Adeodato Simo
    # Test first with the existing state.
218 8ec505dd Adeodato Simo
    (new, prev) = \
219 f380d53c Thomas Thrainer
      group.LUGroupAssignNodes.CheckAssignmentForSplitInstances([],
220 f380d53c Thomas Thrainer
                                                                node_data,
221 f380d53c Thomas Thrainer
                                                                instance_data)
222 8ec505dd Adeodato Simo
223 8ec505dd Adeodato Simo
    self.assertEqual([], new)
224 8ec505dd Adeodato Simo
    self.assertEqual(set(["inst3b", "inst3c"]), set(prev))
225 8ec505dd Adeodato Simo
226 8ec505dd Adeodato Simo
    # And now some changes.
227 8ec505dd Adeodato Simo
    (new, prev) = \
228 f380d53c Thomas Thrainer
      group.LUGroupAssignNodes.CheckAssignmentForSplitInstances([("n1b",
229 f380d53c Thomas Thrainer
                                                                  "g3")],
230 f380d53c Thomas Thrainer
                                                                node_data,
231 f380d53c Thomas Thrainer
                                                                instance_data)
232 8ec505dd Adeodato Simo
233 8ec505dd Adeodato Simo
    self.assertEqual(set(["inst1a", "inst1b"]), set(new))
234 8ec505dd Adeodato Simo
    self.assertEqual(set(["inst3c"]), set(prev))
235 8ec505dd Adeodato Simo
236 8ec505dd Adeodato Simo
237 64c7b383 Michael Hanselmann
class TestClusterVerifySsh(unittest.TestCase):
238 64c7b383 Michael Hanselmann
  def testMultipleGroups(self):
239 7352d33b Thomas Thrainer
    fn = cluster.LUClusterVerifyGroup._SelectSshCheckNodes
240 64c7b383 Michael Hanselmann
    mygroupnodes = [
241 64c7b383 Michael Hanselmann
      objects.Node(name="node20", group="my", offline=False),
242 64c7b383 Michael Hanselmann
      objects.Node(name="node21", group="my", offline=False),
243 64c7b383 Michael Hanselmann
      objects.Node(name="node22", group="my", offline=False),
244 64c7b383 Michael Hanselmann
      objects.Node(name="node23", group="my", offline=False),
245 64c7b383 Michael Hanselmann
      objects.Node(name="node24", group="my", offline=False),
246 64c7b383 Michael Hanselmann
      objects.Node(name="node25", group="my", offline=False),
247 64c7b383 Michael Hanselmann
      objects.Node(name="node26", group="my", offline=True),
248 64c7b383 Michael Hanselmann
      ]
249 64c7b383 Michael Hanselmann
    nodes = [
250 64c7b383 Michael Hanselmann
      objects.Node(name="node1", group="g1", offline=True),
251 64c7b383 Michael Hanselmann
      objects.Node(name="node2", group="g1", offline=False),
252 64c7b383 Michael Hanselmann
      objects.Node(name="node3", group="g1", offline=False),
253 64c7b383 Michael Hanselmann
      objects.Node(name="node4", group="g1", offline=True),
254 64c7b383 Michael Hanselmann
      objects.Node(name="node5", group="g1", offline=False),
255 64c7b383 Michael Hanselmann
      objects.Node(name="node10", group="xyz", offline=False),
256 64c7b383 Michael Hanselmann
      objects.Node(name="node11", group="xyz", offline=False),
257 64c7b383 Michael Hanselmann
      objects.Node(name="node40", group="alloff", offline=True),
258 64c7b383 Michael Hanselmann
      objects.Node(name="node41", group="alloff", offline=True),
259 64c7b383 Michael Hanselmann
      objects.Node(name="node50", group="aaa", offline=False),
260 64c7b383 Michael Hanselmann
      ] + mygroupnodes
261 64c7b383 Michael Hanselmann
    assert not utils.FindDuplicates(map(operator.attrgetter("name"), nodes))
262 64c7b383 Michael Hanselmann
263 64c7b383 Michael Hanselmann
    (online, perhost) = fn(mygroupnodes, "my", nodes)
264 64c7b383 Michael Hanselmann
    self.assertEqual(online, ["node%s" % i for i in range(20, 26)])
265 64c7b383 Michael Hanselmann
    self.assertEqual(set(perhost.keys()), set(online))
266 64c7b383 Michael Hanselmann
267 64c7b383 Michael Hanselmann
    self.assertEqual(perhost, {
268 64c7b383 Michael Hanselmann
      "node20": ["node10", "node2", "node50"],
269 64c7b383 Michael Hanselmann
      "node21": ["node11", "node3", "node50"],
270 64c7b383 Michael Hanselmann
      "node22": ["node10", "node5", "node50"],
271 64c7b383 Michael Hanselmann
      "node23": ["node11", "node2", "node50"],
272 64c7b383 Michael Hanselmann
      "node24": ["node10", "node3", "node50"],
273 64c7b383 Michael Hanselmann
      "node25": ["node11", "node5", "node50"],
274 64c7b383 Michael Hanselmann
      })
275 64c7b383 Michael Hanselmann
276 64c7b383 Michael Hanselmann
  def testSingleGroup(self):
277 7352d33b Thomas Thrainer
    fn = cluster.LUClusterVerifyGroup._SelectSshCheckNodes
278 64c7b383 Michael Hanselmann
    nodes = [
279 64c7b383 Michael Hanselmann
      objects.Node(name="node1", group="default", offline=True),
280 64c7b383 Michael Hanselmann
      objects.Node(name="node2", group="default", offline=False),
281 64c7b383 Michael Hanselmann
      objects.Node(name="node3", group="default", offline=False),
282 64c7b383 Michael Hanselmann
      objects.Node(name="node4", group="default", offline=True),
283 64c7b383 Michael Hanselmann
      ]
284 64c7b383 Michael Hanselmann
    assert not utils.FindDuplicates(map(operator.attrgetter("name"), nodes))
285 64c7b383 Michael Hanselmann
286 64c7b383 Michael Hanselmann
    (online, perhost) = fn(nodes, "default", nodes)
287 64c7b383 Michael Hanselmann
    self.assertEqual(online, ["node2", "node3"])
288 64c7b383 Michael Hanselmann
    self.assertEqual(set(perhost.keys()), set(online))
289 64c7b383 Michael Hanselmann
290 64c7b383 Michael Hanselmann
    self.assertEqual(perhost, {
291 64c7b383 Michael Hanselmann
      "node2": [],
292 64c7b383 Michael Hanselmann
      "node3": [],
293 64c7b383 Michael Hanselmann
      })
294 64c7b383 Michael Hanselmann
295 64c7b383 Michael Hanselmann
296 170b02b7 Michael Hanselmann
class TestClusterVerifyFiles(unittest.TestCase):
297 170b02b7 Michael Hanselmann
  @staticmethod
298 170b02b7 Michael Hanselmann
  def _FakeErrorIf(errors, cond, ecode, item, msg, *args, **kwargs):
299 eedf99b5 Andrea Spadaccini
    assert ((ecode == constants.CV_ENODEFILECHECK and
300 170b02b7 Michael Hanselmann
             ht.TNonEmptyString(item)) or
301 eedf99b5 Andrea Spadaccini
            (ecode == constants.CV_ECLUSTERFILECHECK and
302 170b02b7 Michael Hanselmann
             item is None))
303 170b02b7 Michael Hanselmann
304 170b02b7 Michael Hanselmann
    if args:
305 170b02b7 Michael Hanselmann
      msg = msg % args
306 170b02b7 Michael Hanselmann
307 170b02b7 Michael Hanselmann
    if cond:
308 170b02b7 Michael Hanselmann
      errors.append((item, msg))
309 170b02b7 Michael Hanselmann
310 170b02b7 Michael Hanselmann
  def test(self):
311 170b02b7 Michael Hanselmann
    errors = []
312 170b02b7 Michael Hanselmann
    nodeinfo = [
313 1c3231aa Thomas Thrainer
      objects.Node(name="master.example.com",
314 1c3231aa Thomas Thrainer
                   uuid="master-uuid",
315 1c3231aa Thomas Thrainer
                   offline=False,
316 1c3231aa Thomas Thrainer
                   vm_capable=True),
317 1c3231aa Thomas Thrainer
      objects.Node(name="node2.example.com",
318 1c3231aa Thomas Thrainer
                   uuid="node2-uuid",
319 1c3231aa Thomas Thrainer
                   offline=False,
320 1c3231aa Thomas Thrainer
                   vm_capable=True),
321 1c3231aa Thomas Thrainer
      objects.Node(name="node3.example.com",
322 1c3231aa Thomas Thrainer
                   uuid="node3-uuid",
323 1c3231aa Thomas Thrainer
                   master_candidate=True,
324 0ad1ea40 Guido Trotter
                   vm_capable=False),
325 1c3231aa Thomas Thrainer
      objects.Node(name="node4.example.com",
326 1c3231aa Thomas Thrainer
                   uuid="node4-uuid",
327 1c3231aa Thomas Thrainer
                   offline=False,
328 1c3231aa Thomas Thrainer
                   vm_capable=True),
329 1c3231aa Thomas Thrainer
      objects.Node(name="nodata.example.com",
330 1c3231aa Thomas Thrainer
                   uuid="nodata-uuid",
331 1c3231aa Thomas Thrainer
                   offline=False,
332 1c3231aa Thomas Thrainer
                   vm_capable=True),
333 1c3231aa Thomas Thrainer
      objects.Node(name="offline.example.com",
334 1c3231aa Thomas Thrainer
                   uuid="offline-uuid",
335 1c3231aa Thomas Thrainer
                   offline=True),
336 170b02b7 Michael Hanselmann
      ]
337 170b02b7 Michael Hanselmann
    files_all = set([
338 a56625a2 Michael Hanselmann
      pathutils.CLUSTER_DOMAIN_SECRET_FILE,
339 a56625a2 Michael Hanselmann
      pathutils.RAPI_CERT_FILE,
340 a56625a2 Michael Hanselmann
      pathutils.RAPI_USERS_FILE,
341 170b02b7 Michael Hanselmann
      ])
342 0ad1ea40 Guido Trotter
    files_opt = set([
343 a56625a2 Michael Hanselmann
      pathutils.RAPI_USERS_FILE,
344 0ad1ea40 Guido Trotter
      hv_xen.XL_CONFIG_FILE,
345 a56625a2 Michael Hanselmann
      pathutils.VNC_PASSWORD_FILE,
346 170b02b7 Michael Hanselmann
      ])
347 170b02b7 Michael Hanselmann
    files_mc = set([
348 a56625a2 Michael Hanselmann
      pathutils.CLUSTER_CONF_FILE,
349 170b02b7 Michael Hanselmann
      ])
350 0ad1ea40 Guido Trotter
    files_vm = set([
351 0ad1ea40 Guido Trotter
      hv_xen.XEND_CONFIG_FILE,
352 0ad1ea40 Guido Trotter
      hv_xen.XL_CONFIG_FILE,
353 a56625a2 Michael Hanselmann
      pathutils.VNC_PASSWORD_FILE,
354 0ad1ea40 Guido Trotter
      ])
355 170b02b7 Michael Hanselmann
    nvinfo = {
356 1c3231aa Thomas Thrainer
      "master-uuid": rpc.RpcResult(data=(True, {
357 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
358 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_CONF_FILE: "82314f897f38b35f9dab2f7c6b1593e0",
359 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "babbce8f387bc082228e544a2146fee4",
360 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
361 0ad1ea40 Guido Trotter
          hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310",
362 0ad1ea40 Guido Trotter
          hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9"
363 170b02b7 Michael Hanselmann
        }})),
364 1c3231aa Thomas Thrainer
      "node2-uuid": rpc.RpcResult(data=(True, {
365 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
366 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
367 0ad1ea40 Guido Trotter
          hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310",
368 170b02b7 Michael Hanselmann
          }
369 170b02b7 Michael Hanselmann
        })),
370 1c3231aa Thomas Thrainer
      "node3-uuid": rpc.RpcResult(data=(True, {
371 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
372 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
373 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
374 170b02b7 Michael Hanselmann
          }
375 170b02b7 Michael Hanselmann
        })),
376 1c3231aa Thomas Thrainer
      "node4-uuid": rpc.RpcResult(data=(True, {
377 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
378 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
379 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_CONF_FILE: "conf-a6d4b13e407867f7a7b4f0f232a8f527",
380 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
381 a56625a2 Michael Hanselmann
          pathutils.RAPI_USERS_FILE: "rapiusers-ea3271e8d810ef3",
382 0ad1ea40 Guido Trotter
          hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9"
383 170b02b7 Michael Hanselmann
          }
384 170b02b7 Michael Hanselmann
        })),
385 1c3231aa Thomas Thrainer
      "nodata-uuid": rpc.RpcResult(data=(True, {})),
386 1c3231aa Thomas Thrainer
      "offline-uuid": rpc.RpcResult(offline=True),
387 170b02b7 Michael Hanselmann
      }
388 1c3231aa Thomas Thrainer
    assert set(nvinfo.keys()) == set(map(operator.attrgetter("uuid"), nodeinfo))
389 1c3231aa Thomas Thrainer
390 1c3231aa Thomas Thrainer
    verify_lu = cluster.LUClusterVerifyGroup(mocks.FakeProc(),
391 1c3231aa Thomas Thrainer
                                             opcodes.OpClusterVerify(),
392 1c3231aa Thomas Thrainer
                                             mocks.FakeContext(),
393 1c3231aa Thomas Thrainer
                                             None)
394 1c3231aa Thomas Thrainer
395 1c3231aa Thomas Thrainer
    verify_lu._ErrorIf = compat.partial(self._FakeErrorIf, errors)
396 1c3231aa Thomas Thrainer
397 1c3231aa Thomas Thrainer
    # TODO: That's a bit hackish to mock only this single method. We should
398 1c3231aa Thomas Thrainer
    # build a better FakeConfig which provides such a feature already.
399 1c3231aa Thomas Thrainer
    def GetNodeName(node_uuid):
400 1c3231aa Thomas Thrainer
      for node in nodeinfo:
401 1c3231aa Thomas Thrainer
        if node.uuid == node_uuid:
402 1c3231aa Thomas Thrainer
          return node.name
403 1c3231aa Thomas Thrainer
      return None
404 1c3231aa Thomas Thrainer
405 1c3231aa Thomas Thrainer
    verify_lu.cfg.GetNodeName = GetNodeName
406 170b02b7 Michael Hanselmann
407 1c3231aa Thomas Thrainer
    verify_lu._VerifyFiles(nodeinfo, "master-uuid", nvinfo,
408 1c3231aa Thomas Thrainer
                           (files_all, files_opt, files_mc, files_vm))
409 170b02b7 Michael Hanselmann
    self.assertEqual(sorted(errors), sorted([
410 170b02b7 Michael Hanselmann
      (None, ("File %s found with 2 different checksums (variant 1 on"
411 170b02b7 Michael Hanselmann
              " node2.example.com, node3.example.com, node4.example.com;"
412 a56625a2 Michael Hanselmann
              " variant 2 on master.example.com)" % pathutils.RAPI_CERT_FILE)),
413 170b02b7 Michael Hanselmann
      (None, ("File %s is missing from node(s) node2.example.com" %
414 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_DOMAIN_SECRET_FILE)),
415 170b02b7 Michael Hanselmann
      (None, ("File %s should not exist on node(s) node4.example.com" %
416 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_CONF_FILE)),
417 0ad1ea40 Guido Trotter
      (None, ("File %s is missing from node(s) node4.example.com" %
418 0ad1ea40 Guido Trotter
              hv_xen.XEND_CONFIG_FILE)),
419 170b02b7 Michael Hanselmann
      (None, ("File %s is missing from node(s) node3.example.com" %
420 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_CONF_FILE)),
421 170b02b7 Michael Hanselmann
      (None, ("File %s found with 2 different checksums (variant 1 on"
422 170b02b7 Michael Hanselmann
              " master.example.com; variant 2 on node4.example.com)" %
423 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_CONF_FILE)),
424 170b02b7 Michael Hanselmann
      (None, ("File %s is optional, but it must exist on all or no nodes (not"
425 170b02b7 Michael Hanselmann
              " found on master.example.com, node2.example.com,"
426 a56625a2 Michael Hanselmann
              " node3.example.com)" % pathutils.RAPI_USERS_FILE)),
427 0ad1ea40 Guido Trotter
      (None, ("File %s is optional, but it must exist on all or no nodes (not"
428 0ad1ea40 Guido Trotter
              " found on node2.example.com)" % hv_xen.XL_CONFIG_FILE)),
429 170b02b7 Michael Hanselmann
      ("nodata.example.com", "Node did not return file checksum data"),
430 170b02b7 Michael Hanselmann
      ]))
431 170b02b7 Michael Hanselmann
432 170b02b7 Michael Hanselmann
433 d755483c Michael Hanselmann
class _FakeLU:
434 129cce69 Michael Hanselmann
  def __init__(self, cfg=NotImplemented, proc=NotImplemented,
435 129cce69 Michael Hanselmann
               rpc=NotImplemented):
436 d755483c Michael Hanselmann
    self.warning_log = []
437 d755483c Michael Hanselmann
    self.info_log = []
438 ff02b60f René Nussbaumer
    self.cfg = cfg
439 a8e3e009 Michael Hanselmann
    self.proc = proc
440 129cce69 Michael Hanselmann
    self.rpc = rpc
441 d755483c Michael Hanselmann
442 d755483c Michael Hanselmann
  def LogWarning(self, text, *args):
443 d755483c Michael Hanselmann
    self.warning_log.append((text, args))
444 d755483c Michael Hanselmann
445 d755483c Michael Hanselmann
  def LogInfo(self, text, *args):
446 d755483c Michael Hanselmann
    self.info_log.append((text, args))
447 d755483c Michael Hanselmann
448 d755483c Michael Hanselmann
449 d755483c Michael Hanselmann
class TestLoadNodeEvacResult(unittest.TestCase):
450 d755483c Michael Hanselmann
  def testSuccess(self):
451 d755483c Michael Hanselmann
    for moved in [[], [
452 d755483c Michael Hanselmann
      ("inst20153.example.com", "grp2", ["nodeA4509", "nodeB2912"]),
453 d755483c Michael Hanselmann
      ]]:
454 d755483c Michael Hanselmann
      for early_release in [False, True]:
455 d755483c Michael Hanselmann
        for use_nodes in [False, True]:
456 d755483c Michael Hanselmann
          jobs = [
457 d755483c Michael Hanselmann
            [opcodes.OpInstanceReplaceDisks().__getstate__()],
458 d755483c Michael Hanselmann
            [opcodes.OpInstanceMigrate().__getstate__()],
459 d755483c Michael Hanselmann
            ]
460 d755483c Michael Hanselmann
461 d755483c Michael Hanselmann
          alloc_result = (moved, [], jobs)
462 0fcd0cad René Nussbaumer
          assert iallocator._NEVAC_RESULT(alloc_result)
463 d755483c Michael Hanselmann
464 d755483c Michael Hanselmann
          lu = _FakeLU()
465 5eacbcae Thomas Thrainer
          result = common.LoadNodeEvacResult(lu, alloc_result,
466 5eacbcae Thomas Thrainer
                                             early_release, use_nodes)
467 d755483c Michael Hanselmann
468 d755483c Michael Hanselmann
          if moved:
469 d755483c Michael Hanselmann
            (_, (info_args, )) = lu.info_log.pop(0)
470 d755483c Michael Hanselmann
            for (instname, instgroup, instnodes) in moved:
471 d755483c Michael Hanselmann
              self.assertTrue(instname in info_args)
472 d755483c Michael Hanselmann
              if use_nodes:
473 d755483c Michael Hanselmann
                for i in instnodes:
474 d755483c Michael Hanselmann
                  self.assertTrue(i in info_args)
475 d755483c Michael Hanselmann
              else:
476 d755483c Michael Hanselmann
                self.assertTrue(instgroup in info_args)
477 d755483c Michael Hanselmann
478 d755483c Michael Hanselmann
          self.assertFalse(lu.info_log)
479 d755483c Michael Hanselmann
          self.assertFalse(lu.warning_log)
480 d755483c Michael Hanselmann
481 d755483c Michael Hanselmann
          for op in itertools.chain(*result):
482 d755483c Michael Hanselmann
            if hasattr(op.__class__, "early_release"):
483 d755483c Michael Hanselmann
              self.assertEqual(op.early_release, early_release)
484 d755483c Michael Hanselmann
            else:
485 d755483c Michael Hanselmann
              self.assertFalse(hasattr(op, "early_release"))
486 d755483c Michael Hanselmann
487 d755483c Michael Hanselmann
  def testFailed(self):
488 d755483c Michael Hanselmann
    alloc_result = ([], [
489 d755483c Michael Hanselmann
      ("inst5191.example.com", "errormsg21178"),
490 d755483c Michael Hanselmann
      ], [])
491 0fcd0cad René Nussbaumer
    assert iallocator._NEVAC_RESULT(alloc_result)
492 d755483c Michael Hanselmann
493 d755483c Michael Hanselmann
    lu = _FakeLU()
494 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpExecError, common.LoadNodeEvacResult,
495 d755483c Michael Hanselmann
                      lu, alloc_result, False, False)
496 d755483c Michael Hanselmann
    self.assertFalse(lu.info_log)
497 d755483c Michael Hanselmann
    (_, (args, )) = lu.warning_log.pop(0)
498 d755483c Michael Hanselmann
    self.assertTrue("inst5191.example.com" in args)
499 d755483c Michael Hanselmann
    self.assertTrue("errormsg21178" in args)
500 d755483c Michael Hanselmann
    self.assertFalse(lu.warning_log)
501 d755483c Michael Hanselmann
502 d755483c Michael Hanselmann
503 784cd737 René Nussbaumer
class TestUpdateAndVerifySubDict(unittest.TestCase):
504 784cd737 René Nussbaumer
  def setUp(self):
505 784cd737 René Nussbaumer
    self.type_check = {
506 784cd737 René Nussbaumer
        "a": constants.VTYPE_INT,
507 784cd737 René Nussbaumer
        "b": constants.VTYPE_STRING,
508 784cd737 René Nussbaumer
        "c": constants.VTYPE_BOOL,
509 784cd737 René Nussbaumer
        "d": constants.VTYPE_STRING,
510 784cd737 René Nussbaumer
        }
511 784cd737 René Nussbaumer
512 784cd737 René Nussbaumer
  def test(self):
513 784cd737 René Nussbaumer
    old_test = {
514 784cd737 René Nussbaumer
      "foo": {
515 784cd737 René Nussbaumer
        "d": "blubb",
516 784cd737 René Nussbaumer
        "a": 321,
517 784cd737 René Nussbaumer
        },
518 784cd737 René Nussbaumer
      "baz": {
519 784cd737 René Nussbaumer
        "a": 678,
520 784cd737 René Nussbaumer
        "b": "678",
521 784cd737 René Nussbaumer
        "c": True,
522 784cd737 René Nussbaumer
        },
523 784cd737 René Nussbaumer
      }
524 784cd737 René Nussbaumer
    test = {
525 784cd737 René Nussbaumer
      "foo": {
526 784cd737 René Nussbaumer
        "a": 123,
527 784cd737 René Nussbaumer
        "b": "123",
528 784cd737 René Nussbaumer
        "c": True,
529 784cd737 René Nussbaumer
        },
530 784cd737 René Nussbaumer
      "bar": {
531 784cd737 René Nussbaumer
        "a": 321,
532 784cd737 René Nussbaumer
        "b": "321",
533 784cd737 René Nussbaumer
        "c": False,
534 784cd737 René Nussbaumer
        },
535 784cd737 René Nussbaumer
      }
536 784cd737 René Nussbaumer
537 784cd737 René Nussbaumer
    mv = {
538 784cd737 René Nussbaumer
      "foo": {
539 784cd737 René Nussbaumer
        "a": 123,
540 784cd737 René Nussbaumer
        "b": "123",
541 784cd737 René Nussbaumer
        "c": True,
542 784cd737 René Nussbaumer
        "d": "blubb"
543 784cd737 René Nussbaumer
        },
544 784cd737 René Nussbaumer
      "bar": {
545 784cd737 René Nussbaumer
        "a": 321,
546 784cd737 René Nussbaumer
        "b": "321",
547 784cd737 René Nussbaumer
        "c": False,
548 784cd737 René Nussbaumer
        },
549 784cd737 René Nussbaumer
      "baz": {
550 784cd737 René Nussbaumer
        "a": 678,
551 784cd737 René Nussbaumer
        "b": "678",
552 784cd737 René Nussbaumer
        "c": True,
553 784cd737 René Nussbaumer
        },
554 784cd737 René Nussbaumer
      }
555 784cd737 René Nussbaumer
556 7352d33b Thomas Thrainer
    verified = common._UpdateAndVerifySubDict(old_test, test, self.type_check)
557 784cd737 René Nussbaumer
    self.assertEqual(verified, mv)
558 784cd737 René Nussbaumer
559 784cd737 René Nussbaumer
  def testWrong(self):
560 784cd737 René Nussbaumer
    test = {
561 784cd737 René Nussbaumer
      "foo": {
562 784cd737 René Nussbaumer
        "a": "blubb",
563 784cd737 René Nussbaumer
        "b": "123",
564 784cd737 René Nussbaumer
        "c": True,
565 784cd737 René Nussbaumer
        },
566 784cd737 René Nussbaumer
      "bar": {
567 784cd737 René Nussbaumer
        "a": 321,
568 784cd737 René Nussbaumer
        "b": "321",
569 784cd737 René Nussbaumer
        "c": False,
570 784cd737 René Nussbaumer
        },
571 784cd737 René Nussbaumer
      }
572 784cd737 René Nussbaumer
573 784cd737 René Nussbaumer
    self.assertRaises(errors.TypeEnforcementError,
574 7352d33b Thomas Thrainer
                      common._UpdateAndVerifySubDict, {}, test,
575 7352d33b Thomas Thrainer
                      self.type_check)
576 784cd737 René Nussbaumer
577 784cd737 René Nussbaumer
578 0ba177e2 René Nussbaumer
class TestHvStateHelper(unittest.TestCase):
579 0ba177e2 René Nussbaumer
  def testWithoutOpData(self):
580 5eacbcae Thomas Thrainer
    self.assertEqual(common.MergeAndVerifyHvState(None, NotImplemented),
581 7352d33b Thomas Thrainer
                     None)
582 0ba177e2 René Nussbaumer
583 0ba177e2 René Nussbaumer
  def testWithoutOldData(self):
584 0ba177e2 René Nussbaumer
    new = {
585 0ba177e2 René Nussbaumer
      constants.HT_XEN_PVM: {
586 0ba177e2 René Nussbaumer
        constants.HVST_MEMORY_TOTAL: 4096,
587 0ba177e2 René Nussbaumer
        },
588 0ba177e2 René Nussbaumer
      }
589 5eacbcae Thomas Thrainer
    self.assertEqual(common.MergeAndVerifyHvState(new, None), new)
590 0ba177e2 René Nussbaumer
591 0ba177e2 René Nussbaumer
  def testWithWrongHv(self):
592 0ba177e2 René Nussbaumer
    new = {
593 0ba177e2 René Nussbaumer
      "i-dont-exist": {
594 0ba177e2 René Nussbaumer
        constants.HVST_MEMORY_TOTAL: 4096,
595 0ba177e2 René Nussbaumer
        },
596 0ba177e2 René Nussbaumer
      }
597 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, common.MergeAndVerifyHvState,
598 7352d33b Thomas Thrainer
                      new, None)
599 0ba177e2 René Nussbaumer
600 0ba177e2 René Nussbaumer
class TestDiskStateHelper(unittest.TestCase):
601 0ba177e2 René Nussbaumer
  def testWithoutOpData(self):
602 5eacbcae Thomas Thrainer
    self.assertEqual(common.MergeAndVerifyDiskState(None, NotImplemented),
603 0ba177e2 René Nussbaumer
                     None)
604 0ba177e2 René Nussbaumer
605 0ba177e2 René Nussbaumer
  def testWithoutOldData(self):
606 0ba177e2 René Nussbaumer
    new = {
607 cd3b4ff4 Helga Velroyen
      constants.DT_PLAIN: {
608 0ba177e2 René Nussbaumer
        "xenvg": {
609 0ba177e2 René Nussbaumer
          constants.DS_DISK_RESERVED: 1024,
610 0ba177e2 René Nussbaumer
          },
611 0ba177e2 René Nussbaumer
        },
612 0ba177e2 René Nussbaumer
      }
613 5eacbcae Thomas Thrainer
    self.assertEqual(common.MergeAndVerifyDiskState(new, None), new)
614 0ba177e2 René Nussbaumer
615 0ba177e2 René Nussbaumer
  def testWithWrongStorageType(self):
616 0ba177e2 René Nussbaumer
    new = {
617 0ba177e2 René Nussbaumer
      "i-dont-exist": {
618 0ba177e2 René Nussbaumer
        "xenvg": {
619 0ba177e2 René Nussbaumer
          constants.DS_DISK_RESERVED: 1024,
620 0ba177e2 René Nussbaumer
          },
621 0ba177e2 René Nussbaumer
        },
622 0ba177e2 René Nussbaumer
      }
623 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, common.MergeAndVerifyDiskState,
624 0ba177e2 René Nussbaumer
                      new, None)
625 0ba177e2 René Nussbaumer
626 0ba177e2 René Nussbaumer
627 2096d068 René Nussbaumer
class TestComputeMinMaxSpec(unittest.TestCase):
628 2096d068 René Nussbaumer
  def setUp(self):
629 da5f09ef Bernardo Dal Seno
    self.ispecs = {
630 2096d068 René Nussbaumer
      constants.ISPECS_MAX: {
631 2096d068 René Nussbaumer
        constants.ISPEC_MEM_SIZE: 512,
632 2096d068 René Nussbaumer
        constants.ISPEC_DISK_SIZE: 1024,
633 2096d068 René Nussbaumer
        },
634 2096d068 René Nussbaumer
      constants.ISPECS_MIN: {
635 2096d068 René Nussbaumer
        constants.ISPEC_MEM_SIZE: 128,
636 2096d068 René Nussbaumer
        constants.ISPEC_DISK_COUNT: 1,
637 2096d068 René Nussbaumer
        },
638 2096d068 René Nussbaumer
      }
639 2096d068 René Nussbaumer
640 2096d068 René Nussbaumer
  def testNoneValue(self):
641 7352d33b Thomas Thrainer
    self.assertTrue(common._ComputeMinMaxSpec(constants.ISPEC_MEM_SIZE, None,
642 da5f09ef Bernardo Dal Seno
                                              self.ispecs, None) is None)
643 2096d068 René Nussbaumer
644 2096d068 René Nussbaumer
  def testAutoValue(self):
645 7352d33b Thomas Thrainer
    self.assertTrue(common._ComputeMinMaxSpec(constants.ISPEC_MEM_SIZE, None,
646 da5f09ef Bernardo Dal Seno
                                              self.ispecs,
647 2096d068 René Nussbaumer
                                              constants.VALUE_AUTO) is None)
648 2096d068 René Nussbaumer
649 2096d068 René Nussbaumer
  def testNotDefined(self):
650 7352d33b Thomas Thrainer
    self.assertTrue(common._ComputeMinMaxSpec(constants.ISPEC_NIC_COUNT, None,
651 da5f09ef Bernardo Dal Seno
                                              self.ispecs, 3) is None)
652 2096d068 René Nussbaumer
653 2096d068 René Nussbaumer
  def testNoMinDefined(self):
654 7352d33b Thomas Thrainer
    self.assertTrue(common._ComputeMinMaxSpec(constants.ISPEC_DISK_SIZE, None,
655 da5f09ef Bernardo Dal Seno
                                              self.ispecs, 128) is None)
656 2096d068 René Nussbaumer
657 2096d068 René Nussbaumer
  def testNoMaxDefined(self):
658 7352d33b Thomas Thrainer
    self.assertTrue(common._ComputeMinMaxSpec(constants.ISPEC_DISK_COUNT,
659 7352d33b Thomas Thrainer
                                              None, self.ispecs, 16) is None)
660 2096d068 René Nussbaumer
661 2096d068 René Nussbaumer
  def testOutOfRange(self):
662 2096d068 René Nussbaumer
    for (name, val) in ((constants.ISPEC_MEM_SIZE, 64),
663 2096d068 René Nussbaumer
                        (constants.ISPEC_MEM_SIZE, 768),
664 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_SIZE, 4096),
665 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_COUNT, 0)):
666 da5f09ef Bernardo Dal Seno
      min_v = self.ispecs[constants.ISPECS_MIN].get(name, val)
667 da5f09ef Bernardo Dal Seno
      max_v = self.ispecs[constants.ISPECS_MAX].get(name, val)
668 7352d33b Thomas Thrainer
      self.assertEqual(common._ComputeMinMaxSpec(name, None,
669 da5f09ef Bernardo Dal Seno
                                                 self.ispecs, val),
670 2096d068 René Nussbaumer
                       "%s value %s is not in range [%s, %s]" %
671 2096d068 René Nussbaumer
                       (name, val,min_v, max_v))
672 7352d33b Thomas Thrainer
      self.assertEqual(common._ComputeMinMaxSpec(name, "1",
673 da5f09ef Bernardo Dal Seno
                                                 self.ispecs, val),
674 0c2e59ac Iustin Pop
                       "%s/1 value %s is not in range [%s, %s]" %
675 0c2e59ac Iustin Pop
                       (name, val,min_v, max_v))
676 2096d068 René Nussbaumer
677 2096d068 René Nussbaumer
  def test(self):
678 2096d068 René Nussbaumer
    for (name, val) in ((constants.ISPEC_MEM_SIZE, 256),
679 2096d068 René Nussbaumer
                        (constants.ISPEC_MEM_SIZE, 128),
680 2096d068 René Nussbaumer
                        (constants.ISPEC_MEM_SIZE, 512),
681 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_SIZE, 1024),
682 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_SIZE, 0),
683 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_COUNT, 1),
684 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_COUNT, 5)):
685 7352d33b Thomas Thrainer
      self.assertTrue(common._ComputeMinMaxSpec(name, None, self.ispecs, val)
686 2096d068 René Nussbaumer
                      is None)
687 2096d068 René Nussbaumer
688 2096d068 René Nussbaumer
689 0e68bf27 René Nussbaumer
def _ValidateComputeMinMaxSpec(name, *_):
690 0fb81174 René Nussbaumer
  assert name in constants.ISPECS_PARAMETERS
691 0fb81174 René Nussbaumer
  return None
692 0fb81174 René Nussbaumer
693 0fb81174 René Nussbaumer
694 cc4b2676 Bernardo Dal Seno
def _NoDiskComputeMinMaxSpec(name, *_):
695 cc4b2676 Bernardo Dal Seno
  if name == constants.ISPEC_DISK_COUNT:
696 cc4b2676 Bernardo Dal Seno
    return name
697 cc4b2676 Bernardo Dal Seno
  else:
698 cc4b2676 Bernardo Dal Seno
    return None
699 cc4b2676 Bernardo Dal Seno
700 cc4b2676 Bernardo Dal Seno
701 0fb81174 René Nussbaumer
class _SpecWrapper:
702 0fb81174 René Nussbaumer
  def __init__(self, spec):
703 0fb81174 René Nussbaumer
    self.spec = spec
704 0fb81174 René Nussbaumer
705 0e68bf27 René Nussbaumer
  def ComputeMinMaxSpec(self, *args):
706 0fb81174 René Nussbaumer
    return self.spec.pop(0)
707 0fb81174 René Nussbaumer
708 0fb81174 René Nussbaumer
709 0fb81174 René Nussbaumer
class TestComputeIPolicySpecViolation(unittest.TestCase):
710 cc4b2676 Bernardo Dal Seno
  # Minimal policy accepted by _ComputeIPolicySpecViolation()
711 cc4b2676 Bernardo Dal Seno
  _MICRO_IPOL = {
712 cc4b2676 Bernardo Dal Seno
    constants.IPOLICY_DTS: [constants.DT_PLAIN, constants.DT_DISKLESS],
713 41044e04 Bernardo Dal Seno
    constants.ISPECS_MINMAX: [NotImplemented],
714 cc4b2676 Bernardo Dal Seno
    }
715 cc4b2676 Bernardo Dal Seno
716 0fb81174 René Nussbaumer
  def test(self):
717 0e68bf27 René Nussbaumer
    compute_fn = _ValidateComputeMinMaxSpec
718 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicySpecViolation(self._MICRO_IPOL, 1024, 1, 1, 1,
719 5eacbcae Thomas Thrainer
                                             [1024], 1, constants.DT_PLAIN,
720 5eacbcae Thomas Thrainer
                                             _compute_fn=compute_fn)
721 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
722 0fb81174 René Nussbaumer
723 cc4b2676 Bernardo Dal Seno
  def testDiskFull(self):
724 cc4b2676 Bernardo Dal Seno
    compute_fn = _NoDiskComputeMinMaxSpec
725 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicySpecViolation(self._MICRO_IPOL, 1024, 1, 1, 1,
726 5eacbcae Thomas Thrainer
                                             [1024], 1, constants.DT_PLAIN,
727 5eacbcae Thomas Thrainer
                                             _compute_fn=compute_fn)
728 cc4b2676 Bernardo Dal Seno
    self.assertEqual(ret, [constants.ISPEC_DISK_COUNT])
729 cc4b2676 Bernardo Dal Seno
730 cc4b2676 Bernardo Dal Seno
  def testDiskLess(self):
731 cc4b2676 Bernardo Dal Seno
    compute_fn = _NoDiskComputeMinMaxSpec
732 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicySpecViolation(self._MICRO_IPOL, 1024, 1, 1, 1,
733 5eacbcae Thomas Thrainer
                                             [1024], 1, constants.DT_DISKLESS,
734 5eacbcae Thomas Thrainer
                                             _compute_fn=compute_fn)
735 cc4b2676 Bernardo Dal Seno
    self.assertEqual(ret, [])
736 cc4b2676 Bernardo Dal Seno
737 cc4b2676 Bernardo Dal Seno
  def testWrongTemplates(self):
738 cc4b2676 Bernardo Dal Seno
    compute_fn = _ValidateComputeMinMaxSpec
739 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicySpecViolation(self._MICRO_IPOL, 1024, 1, 1, 1,
740 5eacbcae Thomas Thrainer
                                             [1024], 1, constants.DT_DRBD8,
741 5eacbcae Thomas Thrainer
                                             _compute_fn=compute_fn)
742 cc4b2676 Bernardo Dal Seno
    self.assertEqual(len(ret), 1)
743 cc4b2676 Bernardo Dal Seno
    self.assertTrue("Disk template" in ret[0])
744 cc4b2676 Bernardo Dal Seno
745 0fb81174 René Nussbaumer
  def testInvalidArguments(self):
746 5eacbcae Thomas Thrainer
    self.assertRaises(AssertionError, common.ComputeIPolicySpecViolation,
747 cc4b2676 Bernardo Dal Seno
                      self._MICRO_IPOL, 1024, 1, 1, 1, [], 1,
748 cc4b2676 Bernardo Dal Seno
                      constants.DT_PLAIN,)
749 0fb81174 René Nussbaumer
750 0fb81174 René Nussbaumer
  def testInvalidSpec(self):
751 553cb5f7 René Nussbaumer
    spec = _SpecWrapper([None, False, "foo", None, "bar", None])
752 0e68bf27 René Nussbaumer
    compute_fn = spec.ComputeMinMaxSpec
753 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicySpecViolation(self._MICRO_IPOL, 1024, 1, 1, 1,
754 5eacbcae Thomas Thrainer
                                             [1024], 1, constants.DT_PLAIN,
755 5eacbcae Thomas Thrainer
                                             _compute_fn=compute_fn)
756 0fb81174 René Nussbaumer
    self.assertEqual(ret, ["foo", "bar"])
757 0fb81174 René Nussbaumer
    self.assertFalse(spec.spec)
758 0fb81174 René Nussbaumer
759 41044e04 Bernardo Dal Seno
  def testWithIPolicy(self):
760 41044e04 Bernardo Dal Seno
    mem_size = 2048
761 41044e04 Bernardo Dal Seno
    cpu_count = 2
762 41044e04 Bernardo Dal Seno
    disk_count = 1
763 41044e04 Bernardo Dal Seno
    disk_sizes = [512]
764 41044e04 Bernardo Dal Seno
    nic_count = 1
765 41044e04 Bernardo Dal Seno
    spindle_use = 4
766 41044e04 Bernardo Dal Seno
    disk_template = "mytemplate"
767 41044e04 Bernardo Dal Seno
    ispec = {
768 41044e04 Bernardo Dal Seno
      constants.ISPEC_MEM_SIZE: mem_size,
769 41044e04 Bernardo Dal Seno
      constants.ISPEC_CPU_COUNT: cpu_count,
770 41044e04 Bernardo Dal Seno
      constants.ISPEC_DISK_COUNT: disk_count,
771 41044e04 Bernardo Dal Seno
      constants.ISPEC_DISK_SIZE: disk_sizes[0],
772 41044e04 Bernardo Dal Seno
      constants.ISPEC_NIC_COUNT: nic_count,
773 41044e04 Bernardo Dal Seno
      constants.ISPEC_SPINDLE_USE: spindle_use,
774 41044e04 Bernardo Dal Seno
      }
775 41044e04 Bernardo Dal Seno
    ipolicy1 = {
776 41044e04 Bernardo Dal Seno
      constants.ISPECS_MINMAX: [{
777 41044e04 Bernardo Dal Seno
        constants.ISPECS_MIN: ispec,
778 41044e04 Bernardo Dal Seno
        constants.ISPECS_MAX: ispec,
779 41044e04 Bernardo Dal Seno
        }],
780 41044e04 Bernardo Dal Seno
      constants.IPOLICY_DTS: [disk_template],
781 41044e04 Bernardo Dal Seno
      }
782 41044e04 Bernardo Dal Seno
    ispec_copy = copy.deepcopy(ispec)
783 41044e04 Bernardo Dal Seno
    ipolicy2 = {
784 41044e04 Bernardo Dal Seno
      constants.ISPECS_MINMAX: [
785 41044e04 Bernardo Dal Seno
        {
786 41044e04 Bernardo Dal Seno
          constants.ISPECS_MIN: ispec_copy,
787 41044e04 Bernardo Dal Seno
          constants.ISPECS_MAX: ispec_copy,
788 41044e04 Bernardo Dal Seno
          },
789 41044e04 Bernardo Dal Seno
        {
790 41044e04 Bernardo Dal Seno
          constants.ISPECS_MIN: ispec,
791 41044e04 Bernardo Dal Seno
          constants.ISPECS_MAX: ispec,
792 41044e04 Bernardo Dal Seno
          },
793 41044e04 Bernardo Dal Seno
        ],
794 41044e04 Bernardo Dal Seno
      constants.IPOLICY_DTS: [disk_template],
795 41044e04 Bernardo Dal Seno
      }
796 41044e04 Bernardo Dal Seno
    ipolicy3 = {
797 41044e04 Bernardo Dal Seno
      constants.ISPECS_MINMAX: [
798 41044e04 Bernardo Dal Seno
        {
799 41044e04 Bernardo Dal Seno
          constants.ISPECS_MIN: ispec,
800 41044e04 Bernardo Dal Seno
          constants.ISPECS_MAX: ispec,
801 41044e04 Bernardo Dal Seno
          },
802 41044e04 Bernardo Dal Seno
        {
803 41044e04 Bernardo Dal Seno
          constants.ISPECS_MIN: ispec_copy,
804 41044e04 Bernardo Dal Seno
          constants.ISPECS_MAX: ispec_copy,
805 41044e04 Bernardo Dal Seno
          },
806 41044e04 Bernardo Dal Seno
        ],
807 41044e04 Bernardo Dal Seno
      constants.IPOLICY_DTS: [disk_template],
808 41044e04 Bernardo Dal Seno
      }
809 41044e04 Bernardo Dal Seno
    def AssertComputeViolation(ipolicy, violations):
810 5eacbcae Thomas Thrainer
      ret = common.ComputeIPolicySpecViolation(ipolicy, mem_size, cpu_count,
811 5eacbcae Thomas Thrainer
                                               disk_count, nic_count,
812 5eacbcae Thomas Thrainer
                                               disk_sizes, spindle_use,
813 5eacbcae Thomas Thrainer
                                               disk_template)
814 41044e04 Bernardo Dal Seno
      self.assertEqual(len(ret), violations)
815 41044e04 Bernardo Dal Seno
816 41044e04 Bernardo Dal Seno
    AssertComputeViolation(ipolicy1, 0)
817 41044e04 Bernardo Dal Seno
    AssertComputeViolation(ipolicy2, 0)
818 41044e04 Bernardo Dal Seno
    AssertComputeViolation(ipolicy3, 0)
819 41044e04 Bernardo Dal Seno
    for par in constants.ISPECS_PARAMETERS:
820 41044e04 Bernardo Dal Seno
      ispec[par] += 1
821 41044e04 Bernardo Dal Seno
      AssertComputeViolation(ipolicy1, 1)
822 41044e04 Bernardo Dal Seno
      AssertComputeViolation(ipolicy2, 0)
823 41044e04 Bernardo Dal Seno
      AssertComputeViolation(ipolicy3, 0)
824 41044e04 Bernardo Dal Seno
      ispec[par] -= 2
825 41044e04 Bernardo Dal Seno
      AssertComputeViolation(ipolicy1, 1)
826 41044e04 Bernardo Dal Seno
      AssertComputeViolation(ipolicy2, 0)
827 41044e04 Bernardo Dal Seno
      AssertComputeViolation(ipolicy3, 0)
828 41044e04 Bernardo Dal Seno
      ispec[par] += 1 # Restore
829 41044e04 Bernardo Dal Seno
    ipolicy1[constants.IPOLICY_DTS] = ["another_template"]
830 41044e04 Bernardo Dal Seno
    AssertComputeViolation(ipolicy1, 1)
831 41044e04 Bernardo Dal Seno
832 0fb81174 René Nussbaumer
833 0fb81174 René Nussbaumer
class _StubComputeIPolicySpecViolation:
834 553cb5f7 René Nussbaumer
  def __init__(self, mem_size, cpu_count, disk_count, nic_count, disk_sizes,
835 cc4b2676 Bernardo Dal Seno
               spindle_use, disk_template):
836 0fb81174 René Nussbaumer
    self.mem_size = mem_size
837 0fb81174 René Nussbaumer
    self.cpu_count = cpu_count
838 0fb81174 René Nussbaumer
    self.disk_count = disk_count
839 0fb81174 René Nussbaumer
    self.nic_count = nic_count
840 0fb81174 René Nussbaumer
    self.disk_sizes = disk_sizes
841 553cb5f7 René Nussbaumer
    self.spindle_use = spindle_use
842 cc4b2676 Bernardo Dal Seno
    self.disk_template = disk_template
843 0fb81174 René Nussbaumer
844 553cb5f7 René Nussbaumer
  def __call__(self, _, mem_size, cpu_count, disk_count, nic_count, disk_sizes,
845 cc4b2676 Bernardo Dal Seno
               spindle_use, disk_template):
846 0fb81174 René Nussbaumer
    assert self.mem_size == mem_size
847 0fb81174 René Nussbaumer
    assert self.cpu_count == cpu_count
848 0fb81174 René Nussbaumer
    assert self.disk_count == disk_count
849 0fb81174 René Nussbaumer
    assert self.nic_count == nic_count
850 0fb81174 René Nussbaumer
    assert self.disk_sizes == disk_sizes
851 553cb5f7 René Nussbaumer
    assert self.spindle_use == spindle_use
852 cc4b2676 Bernardo Dal Seno
    assert self.disk_template == disk_template
853 0fb81174 René Nussbaumer
854 0fb81174 René Nussbaumer
    return []
855 0fb81174 René Nussbaumer
856 0fb81174 René Nussbaumer
857 2477c1c5 Bernardo Dal Seno
class _FakeConfigForComputeIPolicyInstanceViolation:
858 5a13489b Bernardo Dal Seno
  def __init__(self, be, excl_stor):
859 2477c1c5 Bernardo Dal Seno
    self.cluster = objects.Cluster(beparams={"default": be})
860 5a13489b Bernardo Dal Seno
    self.excl_stor = excl_stor
861 2477c1c5 Bernardo Dal Seno
862 2477c1c5 Bernardo Dal Seno
  def GetClusterInfo(self):
863 2477c1c5 Bernardo Dal Seno
    return self.cluster
864 2477c1c5 Bernardo Dal Seno
865 5a13489b Bernardo Dal Seno
  def GetNodeInfo(self, _):
866 5a13489b Bernardo Dal Seno
    return {}
867 5a13489b Bernardo Dal Seno
868 5a13489b Bernardo Dal Seno
  def GetNdParams(self, _):
869 5a13489b Bernardo Dal Seno
    return {
870 5a13489b Bernardo Dal Seno
      constants.ND_EXCLUSIVE_STORAGE: self.excl_stor,
871 5a13489b Bernardo Dal Seno
      }
872 5a13489b Bernardo Dal Seno
873 2477c1c5 Bernardo Dal Seno
874 0fb81174 René Nussbaumer
class TestComputeIPolicyInstanceViolation(unittest.TestCase):
875 0fb81174 René Nussbaumer
  def test(self):
876 0fb81174 René Nussbaumer
    beparams = {
877 0fb81174 René Nussbaumer
      constants.BE_MAXMEM: 2048,
878 0fb81174 René Nussbaumer
      constants.BE_VCPUS: 2,
879 34700f5b René Nussbaumer
      constants.BE_SPINDLE_USE: 4,
880 0fb81174 René Nussbaumer
      }
881 5a13489b Bernardo Dal Seno
    disks = [objects.Disk(size=512, spindles=13)]
882 5a13489b Bernardo Dal Seno
    cfg = _FakeConfigForComputeIPolicyInstanceViolation(beparams, False)
883 cc4b2676 Bernardo Dal Seno
    instance = objects.Instance(beparams=beparams, disks=disks, nics=[],
884 cc4b2676 Bernardo Dal Seno
                                disk_template=constants.DT_PLAIN)
885 cc4b2676 Bernardo Dal Seno
    stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 4,
886 cc4b2676 Bernardo Dal Seno
                                            constants.DT_PLAIN)
887 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance,
888 5eacbcae Thomas Thrainer
                                                 cfg, _compute_fn=stub)
889 2477c1c5 Bernardo Dal Seno
    self.assertEqual(ret, [])
890 2477c1c5 Bernardo Dal Seno
    instance2 = objects.Instance(beparams={}, disks=disks, nics=[],
891 2477c1c5 Bernardo Dal Seno
                                 disk_template=constants.DT_PLAIN)
892 5eacbcae Thomas Thrainer
    ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance2,
893 5eacbcae Thomas Thrainer
                                                 cfg, _compute_fn=stub)
894 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
895 5a13489b Bernardo Dal Seno
    cfg_es = _FakeConfigForComputeIPolicyInstanceViolation(beparams, True)
896 5a13489b Bernardo Dal Seno
    stub_es = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 13,
897 5a13489b Bernardo Dal Seno
                                               constants.DT_PLAIN)
898 5a13489b Bernardo Dal Seno
    ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance,
899 5a13489b Bernardo Dal Seno
                                                 cfg_es, _compute_fn=stub_es)
900 5a13489b Bernardo Dal Seno
    self.assertEqual(ret, [])
901 5a13489b Bernardo Dal Seno
    ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance2,
902 5a13489b Bernardo Dal Seno
                                                 cfg_es, _compute_fn=stub_es)
903 5a13489b Bernardo Dal Seno
    self.assertEqual(ret, [])
904 0fb81174 René Nussbaumer
905 0fb81174 René Nussbaumer
906 0fb81174 René Nussbaumer
class TestComputeIPolicyInstanceSpecViolation(unittest.TestCase):
907 0fb81174 René Nussbaumer
  def test(self):
908 0fb81174 René Nussbaumer
    ispec = {
909 0fb81174 René Nussbaumer
      constants.ISPEC_MEM_SIZE: 2048,
910 0fb81174 René Nussbaumer
      constants.ISPEC_CPU_COUNT: 2,
911 0fb81174 René Nussbaumer
      constants.ISPEC_DISK_COUNT: 1,
912 0fb81174 René Nussbaumer
      constants.ISPEC_DISK_SIZE: [512],
913 0fb81174 René Nussbaumer
      constants.ISPEC_NIC_COUNT: 0,
914 553cb5f7 René Nussbaumer
      constants.ISPEC_SPINDLE_USE: 1,
915 0fb81174 René Nussbaumer
      }
916 cc4b2676 Bernardo Dal Seno
    stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 1,
917 cc4b2676 Bernardo Dal Seno
                                            constants.DT_PLAIN)
918 22b7f6f8 Thomas Thrainer
    ret = instance._ComputeIPolicyInstanceSpecViolation(NotImplemented, ispec,
919 22b7f6f8 Thomas Thrainer
                                                        constants.DT_PLAIN,
920 22b7f6f8 Thomas Thrainer
                                                        _compute_fn=stub)
921 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
922 0fb81174 René Nussbaumer
923 0fb81174 René Nussbaumer
924 0fb81174 René Nussbaumer
class _CallRecorder:
925 0fb81174 René Nussbaumer
  def __init__(self, return_value=None):
926 0fb81174 René Nussbaumer
    self.called = False
927 0fb81174 René Nussbaumer
    self.return_value = return_value
928 0fb81174 René Nussbaumer
929 0fb81174 René Nussbaumer
  def __call__(self, *args):
930 0fb81174 René Nussbaumer
    self.called = True
931 0fb81174 René Nussbaumer
    return self.return_value
932 0fb81174 René Nussbaumer
933 0fb81174 René Nussbaumer
934 0fb81174 René Nussbaumer
class TestComputeIPolicyNodeViolation(unittest.TestCase):
935 0fb81174 René Nussbaumer
  def setUp(self):
936 0fb81174 René Nussbaumer
    self.recorder = _CallRecorder(return_value=[])
937 0fb81174 René Nussbaumer
938 0fb81174 René Nussbaumer
  def testSameGroup(self):
939 763ad5be Thomas Thrainer
    ret = instance_utils._ComputeIPolicyNodeViolation(
940 763ad5be Thomas Thrainer
      NotImplemented,
941 763ad5be Thomas Thrainer
      NotImplemented,
942 763ad5be Thomas Thrainer
      "foo", "foo", NotImplemented,
943 763ad5be Thomas Thrainer
      _compute_fn=self.recorder)
944 0fb81174 René Nussbaumer
    self.assertFalse(self.recorder.called)
945 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
946 0fb81174 René Nussbaumer
947 0fb81174 René Nussbaumer
  def testDifferentGroup(self):
948 763ad5be Thomas Thrainer
    ret = instance_utils._ComputeIPolicyNodeViolation(
949 763ad5be Thomas Thrainer
      NotImplemented,
950 763ad5be Thomas Thrainer
      NotImplemented,
951 763ad5be Thomas Thrainer
      "foo", "bar", NotImplemented,
952 763ad5be Thomas Thrainer
      _compute_fn=self.recorder)
953 0fb81174 René Nussbaumer
    self.assertTrue(self.recorder.called)
954 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
955 0fb81174 René Nussbaumer
956 0fb81174 René Nussbaumer
957 ff02b60f René Nussbaumer
class _FakeConfigForTargetNodeIPolicy:
958 ff02b60f René Nussbaumer
  def __init__(self, node_info=NotImplemented):
959 ff02b60f René Nussbaumer
    self._node_info = node_info
960 ff02b60f René Nussbaumer
961 ff02b60f René Nussbaumer
  def GetNodeInfo(self, _):
962 ff02b60f René Nussbaumer
    return self._node_info
963 ff02b60f René Nussbaumer
964 ff02b60f René Nussbaumer
965 0fb81174 René Nussbaumer
class TestCheckTargetNodeIPolicy(unittest.TestCase):
966 0fb81174 René Nussbaumer
  def setUp(self):
967 ff02b60f René Nussbaumer
    self.instance = objects.Instance(primary_node="blubb")
968 0fb81174 René Nussbaumer
    self.target_node = objects.Node(group="bar")
969 ff02b60f René Nussbaumer
    node_info = objects.Node(group="foo")
970 ff02b60f René Nussbaumer
    fake_cfg = _FakeConfigForTargetNodeIPolicy(node_info=node_info)
971 ff02b60f René Nussbaumer
    self.lu = _FakeLU(cfg=fake_cfg)
972 0fb81174 René Nussbaumer
973 0fb81174 René Nussbaumer
  def testNoViolation(self):
974 0fb81174 René Nussbaumer
    compute_recoder = _CallRecorder(return_value=[])
975 5eacbcae Thomas Thrainer
    instance.CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
976 5eacbcae Thomas Thrainer
                                    self.target_node, NotImplemented,
977 5eacbcae Thomas Thrainer
                                    _compute_fn=compute_recoder)
978 0fb81174 René Nussbaumer
    self.assertTrue(compute_recoder.called)
979 0fb81174 René Nussbaumer
    self.assertEqual(self.lu.warning_log, [])
980 0fb81174 René Nussbaumer
981 0fb81174 René Nussbaumer
  def testNoIgnore(self):
982 0fb81174 René Nussbaumer
    compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
983 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, instance.CheckTargetNodeIPolicy,
984 22b7f6f8 Thomas Thrainer
                      self.lu, NotImplemented, self.instance,
985 22b7f6f8 Thomas Thrainer
                      self.target_node, NotImplemented,
986 22b7f6f8 Thomas Thrainer
                      _compute_fn=compute_recoder)
987 0fb81174 René Nussbaumer
    self.assertTrue(compute_recoder.called)
988 0fb81174 René Nussbaumer
    self.assertEqual(self.lu.warning_log, [])
989 0fb81174 René Nussbaumer
990 0fb81174 René Nussbaumer
  def testIgnoreViolation(self):
991 0fb81174 René Nussbaumer
    compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
992 5eacbcae Thomas Thrainer
    instance.CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
993 22b7f6f8 Thomas Thrainer
                                     self.target_node, NotImplemented,
994 22b7f6f8 Thomas Thrainer
                                     ignore=True, _compute_fn=compute_recoder)
995 0fb81174 René Nussbaumer
    self.assertTrue(compute_recoder.called)
996 0fb81174 René Nussbaumer
    msg = ("Instance does not meet target node group's (bar) instance policy:"
997 0fb81174 René Nussbaumer
           " mem_size not in range")
998 0fb81174 René Nussbaumer
    self.assertEqual(self.lu.warning_log, [(msg, ())])
999 0fb81174 René Nussbaumer
1000 0fb81174 René Nussbaumer
1001 8301885b Michael Hanselmann
class TestApplyContainerMods(unittest.TestCase):
1002 8301885b Michael Hanselmann
  def testEmptyContainer(self):
1003 8301885b Michael Hanselmann
    container = []
1004 8301885b Michael Hanselmann
    chgdesc = []
1005 5eacbcae Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, [], None, None,
1006 22b7f6f8 Thomas Thrainer
                                None)
1007 8301885b Michael Hanselmann
    self.assertEqual(container, [])
1008 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [])
1009 8301885b Michael Hanselmann
1010 8301885b Michael Hanselmann
  def testAdd(self):
1011 8301885b Michael Hanselmann
    container = []
1012 8301885b Michael Hanselmann
    chgdesc = []
1013 5eacbcae Thomas Thrainer
    mods = instance._PrepareContainerMods([
1014 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "Hello"),
1015 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "World"),
1016 8301885b Michael Hanselmann
      (constants.DDM_ADD, 0, "Start"),
1017 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "End"),
1018 8301885b Michael Hanselmann
      ], None)
1019 5eacbcae Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
1020 22b7f6f8 Thomas Thrainer
                                None, None, None)
1021 8301885b Michael Hanselmann
    self.assertEqual(container, ["Start", "Hello", "World", "End"])
1022 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [])
1023 8301885b Michael Hanselmann
1024 5eacbcae Thomas Thrainer
    mods = instance._PrepareContainerMods([
1025 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 0, "zero"),
1026 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 3, "Added"),
1027 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 5, "four"),
1028 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 7, "xyz"),
1029 35554b4f Michael Hanselmann
      ], None)
1030 5eacbcae Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
1031 22b7f6f8 Thomas Thrainer
                                None, None, None)
1032 35554b4f Michael Hanselmann
    self.assertEqual(container,
1033 35554b4f Michael Hanselmann
                     ["zero", "Start", "Hello", "Added", "World", "four",
1034 35554b4f Michael Hanselmann
                      "End", "xyz"])
1035 35554b4f Michael Hanselmann
    self.assertEqual(chgdesc, [])
1036 35554b4f Michael Hanselmann
1037 35554b4f Michael Hanselmann
    for idx in [-2, len(container) + 1]:
1038 5eacbcae Thomas Thrainer
      mods = instance._PrepareContainerMods([
1039 35554b4f Michael Hanselmann
        (constants.DDM_ADD, idx, "error"),
1040 35554b4f Michael Hanselmann
        ], None)
1041 5eacbcae Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
1042 35554b4f Michael Hanselmann
                        "test", container, None, mods, None, None, None)
1043 35554b4f Michael Hanselmann
1044 8301885b Michael Hanselmann
  def testRemoveError(self):
1045 8301885b Michael Hanselmann
    for idx in [0, 1, 2, 100, -1, -4]:
1046 5eacbcae Thomas Thrainer
      mods = instance._PrepareContainerMods([
1047 8301885b Michael Hanselmann
        (constants.DDM_REMOVE, idx, None),
1048 8301885b Michael Hanselmann
        ], None)
1049 5eacbcae Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
1050 8301885b Michael Hanselmann
                        "test", [], None, mods, None, None, None)
1051 8301885b Michael Hanselmann
1052 5eacbcae Thomas Thrainer
    mods = instance._PrepareContainerMods([
1053 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, 0, object()),
1054 8301885b Michael Hanselmann
      ], None)
1055 5eacbcae Thomas Thrainer
    self.assertRaises(AssertionError, instance._ApplyContainerMods,
1056 8301885b Michael Hanselmann
                      "test", [""], None, mods, None, None, None)
1057 8301885b Michael Hanselmann
1058 8301885b Michael Hanselmann
  def testAddError(self):
1059 35554b4f Michael Hanselmann
    for idx in range(-100, -1) + [100]:
1060 5eacbcae Thomas Thrainer
      mods = instance._PrepareContainerMods([
1061 8301885b Michael Hanselmann
        (constants.DDM_ADD, idx, None),
1062 8301885b Michael Hanselmann
        ], None)
1063 5eacbcae Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
1064 8301885b Michael Hanselmann
                        "test", [], None, mods, None, None, None)
1065 8301885b Michael Hanselmann
1066 8301885b Michael Hanselmann
  def testRemove(self):
1067 8301885b Michael Hanselmann
    container = ["item 1", "item 2"]
1068 5eacbcae Thomas Thrainer
    mods = instance._PrepareContainerMods([
1069 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "aaa"),
1070 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, -1, None),
1071 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "bbb"),
1072 8301885b Michael Hanselmann
      ], None)
1073 8301885b Michael Hanselmann
    chgdesc = []
1074 5eacbcae Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
1075 22b7f6f8 Thomas Thrainer
                                None, None, None)
1076 8301885b Michael Hanselmann
    self.assertEqual(container, ["item 1", "item 2", "bbb"])
1077 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [
1078 8301885b Michael Hanselmann
      ("test/2", "remove"),
1079 8301885b Michael Hanselmann
      ])
1080 8301885b Michael Hanselmann
1081 35554b4f Michael Hanselmann
  def testModify(self):
1082 35554b4f Michael Hanselmann
    container = ["item 1", "item 2"]
1083 5eacbcae Thomas Thrainer
    mods = instance._PrepareContainerMods([
1084 35554b4f Michael Hanselmann
      (constants.DDM_MODIFY, -1, "a"),
1085 35554b4f Michael Hanselmann
      (constants.DDM_MODIFY, 0, "b"),
1086 35554b4f Michael Hanselmann
      (constants.DDM_MODIFY, 1, "c"),
1087 35554b4f Michael Hanselmann
      ], None)
1088 35554b4f Michael Hanselmann
    chgdesc = []
1089 5eacbcae Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
1090 22b7f6f8 Thomas Thrainer
                                None, None, None)
1091 35554b4f Michael Hanselmann
    self.assertEqual(container, ["item 1", "item 2"])
1092 35554b4f Michael Hanselmann
    self.assertEqual(chgdesc, [])
1093 35554b4f Michael Hanselmann
1094 35554b4f Michael Hanselmann
    for idx in [-2, len(container) + 1]:
1095 5eacbcae Thomas Thrainer
      mods = instance._PrepareContainerMods([
1096 35554b4f Michael Hanselmann
        (constants.DDM_MODIFY, idx, "error"),
1097 35554b4f Michael Hanselmann
        ], None)
1098 5eacbcae Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
1099 35554b4f Michael Hanselmann
                        "test", container, None, mods, None, None, None)
1100 35554b4f Michael Hanselmann
1101 8301885b Michael Hanselmann
  class _PrivateData:
1102 8301885b Michael Hanselmann
    def __init__(self):
1103 8301885b Michael Hanselmann
      self.data = None
1104 8301885b Michael Hanselmann
1105 8301885b Michael Hanselmann
  @staticmethod
1106 efcfa99d Michael Hanselmann
  def _CreateTestFn(idx, params, private):
1107 8301885b Michael Hanselmann
    private.data = ("add", idx, params)
1108 efcfa99d Michael Hanselmann
    return ((100 * idx, params), [
1109 efcfa99d Michael Hanselmann
      ("test/%s" % idx, hex(idx)),
1110 efcfa99d Michael Hanselmann
      ])
1111 8301885b Michael Hanselmann
1112 8301885b Michael Hanselmann
  @staticmethod
1113 efcfa99d Michael Hanselmann
  def _ModifyTestFn(idx, item, params, private):
1114 8301885b Michael Hanselmann
    private.data = ("modify", idx, params)
1115 efcfa99d Michael Hanselmann
    return [
1116 efcfa99d Michael Hanselmann
      ("test/%s" % idx, "modify %s" % params),
1117 efcfa99d Michael Hanselmann
      ]
1118 8301885b Michael Hanselmann
1119 8301885b Michael Hanselmann
  @staticmethod
1120 efcfa99d Michael Hanselmann
  def _RemoveTestFn(idx, item, private):
1121 8301885b Michael Hanselmann
    private.data = ("remove", idx, item)
1122 8301885b Michael Hanselmann
1123 8301885b Michael Hanselmann
  def testAddWithCreateFunction(self):
1124 8301885b Michael Hanselmann
    container = []
1125 8301885b Michael Hanselmann
    chgdesc = []
1126 5eacbcae Thomas Thrainer
    mods = instance._PrepareContainerMods([
1127 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "Hello"),
1128 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "World"),
1129 8301885b Michael Hanselmann
      (constants.DDM_ADD, 0, "Start"),
1130 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "End"),
1131 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, 2, None),
1132 8301885b Michael Hanselmann
      (constants.DDM_MODIFY, -1, "foobar"),
1133 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, 2, None),
1134 8301885b Michael Hanselmann
      (constants.DDM_ADD, 1, "More"),
1135 8301885b Michael Hanselmann
      ], self._PrivateData)
1136 5eacbcae Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
1137 22b7f6f8 Thomas Thrainer
                                self._CreateTestFn, self._ModifyTestFn,
1138 22b7f6f8 Thomas Thrainer
                                self._RemoveTestFn)
1139 8301885b Michael Hanselmann
    self.assertEqual(container, [
1140 35554b4f Michael Hanselmann
      (000, "Start"),
1141 35554b4f Michael Hanselmann
      (100, "More"),
1142 35554b4f Michael Hanselmann
      (000, "Hello"),
1143 8301885b Michael Hanselmann
      ])
1144 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [
1145 8301885b Michael Hanselmann
      ("test/0", "0x0"),
1146 8301885b Michael Hanselmann
      ("test/1", "0x1"),
1147 35554b4f Michael Hanselmann
      ("test/0", "0x0"),
1148 8301885b Michael Hanselmann
      ("test/3", "0x3"),
1149 8301885b Michael Hanselmann
      ("test/2", "remove"),
1150 8301885b Michael Hanselmann
      ("test/2", "modify foobar"),
1151 8301885b Michael Hanselmann
      ("test/2", "remove"),
1152 35554b4f Michael Hanselmann
      ("test/1", "0x1")
1153 8301885b Michael Hanselmann
      ])
1154 8301885b Michael Hanselmann
    self.assertTrue(compat.all(op == private.data[0]
1155 8301885b Michael Hanselmann
                               for (op, _, _, private) in mods))
1156 8301885b Michael Hanselmann
    self.assertEqual([private.data for (op, _, _, private) in mods], [
1157 8301885b Michael Hanselmann
      ("add", 0, "Hello"),
1158 8301885b Michael Hanselmann
      ("add", 1, "World"),
1159 35554b4f Michael Hanselmann
      ("add", 0, "Start"),
1160 8301885b Michael Hanselmann
      ("add", 3, "End"),
1161 8301885b Michael Hanselmann
      ("remove", 2, (100, "World")),
1162 8301885b Michael Hanselmann
      ("modify", 2, "foobar"),
1163 8301885b Michael Hanselmann
      ("remove", 2, (300, "End")),
1164 35554b4f Michael Hanselmann
      ("add", 1, "More"),
1165 8301885b Michael Hanselmann
      ])
1166 8301885b Michael Hanselmann
1167 8301885b Michael Hanselmann
1168 a8e3e009 Michael Hanselmann
class _FakeConfigForGenDiskTemplate:
1169 850c53f1 Helga Velroyen
  def __init__(self, enabled_disk_templates):
1170 a8e3e009 Michael Hanselmann
    self._unique_id = itertools.count()
1171 a8e3e009 Michael Hanselmann
    self._drbd_minor = itertools.count(20)
1172 a8e3e009 Michael Hanselmann
    self._port = itertools.count(constants.FIRST_DRBD_PORT)
1173 a8e3e009 Michael Hanselmann
    self._secret = itertools.count()
1174 850c53f1 Helga Velroyen
    self._enabled_disk_templates = enabled_disk_templates
1175 a8e3e009 Michael Hanselmann
1176 a8e3e009 Michael Hanselmann
  def GetVGName(self):
1177 a8e3e009 Michael Hanselmann
    return "testvg"
1178 a8e3e009 Michael Hanselmann
1179 a8e3e009 Michael Hanselmann
  def GenerateUniqueID(self, ec_id):
1180 a8e3e009 Michael Hanselmann
    return "ec%s-uq%s" % (ec_id, self._unique_id.next())
1181 a8e3e009 Michael Hanselmann
1182 a8e3e009 Michael Hanselmann
  def AllocateDRBDMinor(self, nodes, instance):
1183 a8e3e009 Michael Hanselmann
    return [self._drbd_minor.next()
1184 a8e3e009 Michael Hanselmann
            for _ in nodes]
1185 a8e3e009 Michael Hanselmann
1186 a8e3e009 Michael Hanselmann
  def AllocatePort(self):
1187 a8e3e009 Michael Hanselmann
    return self._port.next()
1188 a8e3e009 Michael Hanselmann
1189 a8e3e009 Michael Hanselmann
  def GenerateDRBDSecret(self, ec_id):
1190 a8e3e009 Michael Hanselmann
    return "ec%s-secret%s" % (ec_id, self._secret.next())
1191 a8e3e009 Michael Hanselmann
1192 99ccf8b9 René Nussbaumer
  def GetInstanceInfo(self, _):
1193 99ccf8b9 René Nussbaumer
    return "foobar"
1194 99ccf8b9 René Nussbaumer
1195 850c53f1 Helga Velroyen
  def GetClusterInfo(self):
1196 850c53f1 Helga Velroyen
    cluster = objects.Cluster()
1197 850c53f1 Helga Velroyen
    cluster.enabled_disk_templates = self._enabled_disk_templates
1198 850c53f1 Helga Velroyen
    return cluster
1199 850c53f1 Helga Velroyen
1200 a8e3e009 Michael Hanselmann
1201 a8e3e009 Michael Hanselmann
class _FakeProcForGenDiskTemplate:
1202 a8e3e009 Michael Hanselmann
  def GetECId(self):
1203 a8e3e009 Michael Hanselmann
    return 0
1204 a8e3e009 Michael Hanselmann
1205 a8e3e009 Michael Hanselmann
1206 a8e3e009 Michael Hanselmann
class TestGenerateDiskTemplate(unittest.TestCase):
1207 a8e3e009 Michael Hanselmann
1208 850c53f1 Helga Velroyen
  def _SetUpLUWithTemplates(self, enabled_disk_templates):
1209 850c53f1 Helga Velroyen
    self._enabled_disk_templates = enabled_disk_templates
1210 850c53f1 Helga Velroyen
    cfg = _FakeConfigForGenDiskTemplate(self._enabled_disk_templates)
1211 a8e3e009 Michael Hanselmann
    proc = _FakeProcForGenDiskTemplate()
1212 a8e3e009 Michael Hanselmann
1213 a8e3e009 Michael Hanselmann
    self.lu = _FakeLU(cfg=cfg, proc=proc)
1214 850c53f1 Helga Velroyen
1215 850c53f1 Helga Velroyen
  def setUp(self):
1216 850c53f1 Helga Velroyen
    nodegroup = objects.NodeGroup(name="ng")
1217 850c53f1 Helga Velroyen
    nodegroup.UpgradeConfig()
1218 850c53f1 Helga Velroyen
1219 850c53f1 Helga Velroyen
    self._enabled_disk_templates = list(constants.DISK_TEMPLATES)
1220 850c53f1 Helga Velroyen
    self._SetUpLUWithTemplates(self._enabled_disk_templates)
1221 a8e3e009 Michael Hanselmann
    self.nodegroup = nodegroup
1222 a8e3e009 Michael Hanselmann
1223 99ccf8b9 René Nussbaumer
  @staticmethod
1224 99ccf8b9 René Nussbaumer
  def GetDiskParams():
1225 99ccf8b9 René Nussbaumer
    return copy.deepcopy(constants.DISK_DT_DEFAULTS)
1226 99ccf8b9 René Nussbaumer
1227 a8e3e009 Michael Hanselmann
  def testWrongDiskTemplate(self):
1228 5eacbcae Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1229 a8e3e009 Michael Hanselmann
    disk_template = "##unknown##"
1230 a8e3e009 Michael Hanselmann
1231 a8e3e009 Michael Hanselmann
    assert disk_template not in constants.DISK_TEMPLATES
1232 a8e3e009 Michael Hanselmann
1233 850c53f1 Helga Velroyen
    self.assertRaises(errors.OpPrereqError, gdt, self.lu, disk_template,
1234 a8e3e009 Michael Hanselmann
                      "inst26831.example.com", "node30113.example.com", [], [],
1235 a8e3e009 Michael Hanselmann
                      NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1236 99ccf8b9 René Nussbaumer
                      self.GetDiskParams())
1237 a8e3e009 Michael Hanselmann
1238 a8e3e009 Michael Hanselmann
  def testDiskless(self):
1239 5eacbcae Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1240 a8e3e009 Michael Hanselmann
1241 a8e3e009 Michael Hanselmann
    result = gdt(self.lu, constants.DT_DISKLESS, "inst27734.example.com",
1242 a8e3e009 Michael Hanselmann
                 "node30113.example.com", [], [],
1243 a8e3e009 Michael Hanselmann
                 NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1244 99ccf8b9 René Nussbaumer
                 self.GetDiskParams())
1245 a8e3e009 Michael Hanselmann
    self.assertEqual(result, [])
1246 a8e3e009 Michael Hanselmann
1247 a8e3e009 Michael Hanselmann
  def _TestTrivialDisk(self, template, disk_info, base_index, exp_dev_type,
1248 a8e3e009 Michael Hanselmann
                       file_storage_dir=NotImplemented,
1249 850c53f1 Helga Velroyen
                       file_driver=NotImplemented):
1250 5eacbcae Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1251 a8e3e009 Michael Hanselmann
1252 a8e3e009 Michael Hanselmann
    map(lambda params: utils.ForceDictType(params,
1253 a8e3e009 Michael Hanselmann
                                           constants.IDISK_PARAMS_TYPES),
1254 a8e3e009 Michael Hanselmann
        disk_info)
1255 a8e3e009 Michael Hanselmann
1256 a8e3e009 Michael Hanselmann
    # Check if non-empty list of secondaries is rejected
1257 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, gdt, self.lu,
1258 a8e3e009 Michael Hanselmann
                      template, "inst25088.example.com",
1259 a8e3e009 Michael Hanselmann
                      "node185.example.com", ["node323.example.com"], [],
1260 a8e3e009 Michael Hanselmann
                      NotImplemented, NotImplemented, base_index,
1261 850c53f1 Helga Velroyen
                      self.lu.LogInfo, self.GetDiskParams())
1262 a8e3e009 Michael Hanselmann
1263 a8e3e009 Michael Hanselmann
    result = gdt(self.lu, template, "inst21662.example.com",
1264 a8e3e009 Michael Hanselmann
                 "node21741.example.com", [],
1265 a8e3e009 Michael Hanselmann
                 disk_info, file_storage_dir, file_driver, base_index,
1266 850c53f1 Helga Velroyen
                 self.lu.LogInfo, self.GetDiskParams())
1267 a8e3e009 Michael Hanselmann
1268 a8e3e009 Michael Hanselmann
    for (idx, disk) in enumerate(result):
1269 a8e3e009 Michael Hanselmann
      self.assertTrue(isinstance(disk, objects.Disk))
1270 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.dev_type, exp_dev_type)
1271 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.size, disk_info[idx][constants.IDISK_SIZE])
1272 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.mode, disk_info[idx][constants.IDISK_MODE])
1273 a8e3e009 Michael Hanselmann
      self.assertTrue(disk.children is None)
1274 a8e3e009 Michael Hanselmann
1275 0356a13d Michael Hanselmann
    self._CheckIvNames(result, base_index, base_index + len(disk_info))
1276 22b7f6f8 Thomas Thrainer
    instance._UpdateIvNames(base_index, result)
1277 0356a13d Michael Hanselmann
    self._CheckIvNames(result, base_index, base_index + len(disk_info))
1278 a8e3e009 Michael Hanselmann
1279 a8e3e009 Michael Hanselmann
    return result
1280 a8e3e009 Michael Hanselmann
1281 0356a13d Michael Hanselmann
  def _CheckIvNames(self, disks, base_index, end_index):
1282 0356a13d Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("iv_name"), disks),
1283 0356a13d Michael Hanselmann
                     ["disk/%s" % i for i in range(base_index, end_index)])
1284 0356a13d Michael Hanselmann
1285 a8e3e009 Michael Hanselmann
  def testPlain(self):
1286 a8e3e009 Michael Hanselmann
    disk_info = [{
1287 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 1024,
1288 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1289 a8e3e009 Michael Hanselmann
      }, {
1290 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 4096,
1291 a8e3e009 Michael Hanselmann
      constants.IDISK_VG: "othervg",
1292 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1293 a8e3e009 Michael Hanselmann
      }]
1294 a8e3e009 Michael Hanselmann
1295 a8e3e009 Michael Hanselmann
    result = self._TestTrivialDisk(constants.DT_PLAIN, disk_info, 3,
1296 cd3b4ff4 Helga Velroyen
                                   constants.DT_PLAIN)
1297 a8e3e009 Michael Hanselmann
1298 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1299 a8e3e009 Michael Hanselmann
      ("testvg", "ec0-uq0.disk3"),
1300 a8e3e009 Michael Hanselmann
      ("othervg", "ec0-uq1.disk4"),
1301 a8e3e009 Michael Hanselmann
      ])
1302 a8e3e009 Michael Hanselmann
1303 a8e3e009 Michael Hanselmann
  def testFile(self):
1304 850c53f1 Helga Velroyen
    # anything != DT_FILE would do here
1305 850c53f1 Helga Velroyen
    self._SetUpLUWithTemplates([constants.DT_PLAIN])
1306 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, self._TestTrivialDisk,
1307 850c53f1 Helga Velroyen
                      constants.DT_FILE, [], 0, NotImplemented)
1308 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, self._TestTrivialDisk,
1309 850c53f1 Helga Velroyen
                      constants.DT_SHARED_FILE, [], 0, NotImplemented)
1310 a8e3e009 Michael Hanselmann
1311 a8e3e009 Michael Hanselmann
    for disk_template in [constants.DT_FILE, constants.DT_SHARED_FILE]:
1312 a8e3e009 Michael Hanselmann
      disk_info = [{
1313 a8e3e009 Michael Hanselmann
        constants.IDISK_SIZE: 80 * 1024,
1314 a8e3e009 Michael Hanselmann
        constants.IDISK_MODE: constants.DISK_RDONLY,
1315 a8e3e009 Michael Hanselmann
        }, {
1316 a8e3e009 Michael Hanselmann
        constants.IDISK_SIZE: 4096,
1317 a8e3e009 Michael Hanselmann
        constants.IDISK_MODE: constants.DISK_RDWR,
1318 a8e3e009 Michael Hanselmann
        }, {
1319 a8e3e009 Michael Hanselmann
        constants.IDISK_SIZE: 6 * 1024,
1320 a8e3e009 Michael Hanselmann
        constants.IDISK_MODE: constants.DISK_RDWR,
1321 a8e3e009 Michael Hanselmann
        }]
1322 a8e3e009 Michael Hanselmann
1323 850c53f1 Helga Velroyen
      self._SetUpLUWithTemplates([disk_template])
1324 a8e3e009 Michael Hanselmann
      result = self._TestTrivialDisk(disk_template, disk_info, 2,
1325 cd3b4ff4 Helga Velroyen
        constants.DT_FILE, file_storage_dir="/tmp",
1326 850c53f1 Helga Velroyen
        file_driver=constants.FD_BLKTAP)
1327 a8e3e009 Michael Hanselmann
1328 a8e3e009 Michael Hanselmann
      self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1329 a8e3e009 Michael Hanselmann
        (constants.FD_BLKTAP, "/tmp/disk2"),
1330 a8e3e009 Michael Hanselmann
        (constants.FD_BLKTAP, "/tmp/disk3"),
1331 a8e3e009 Michael Hanselmann
        (constants.FD_BLKTAP, "/tmp/disk4"),
1332 a8e3e009 Michael Hanselmann
        ])
1333 a8e3e009 Michael Hanselmann
1334 a8e3e009 Michael Hanselmann
  def testBlock(self):
1335 a8e3e009 Michael Hanselmann
    disk_info = [{
1336 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 8 * 1024,
1337 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1338 a8e3e009 Michael Hanselmann
      constants.IDISK_ADOPT: "/tmp/some/block/dev",
1339 a8e3e009 Michael Hanselmann
      }]
1340 a8e3e009 Michael Hanselmann
1341 a8e3e009 Michael Hanselmann
    result = self._TestTrivialDisk(constants.DT_BLOCK, disk_info, 10,
1342 cd3b4ff4 Helga Velroyen
                                   constants.DT_BLOCK)
1343 a8e3e009 Michael Hanselmann
1344 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1345 a8e3e009 Michael Hanselmann
      (constants.BLOCKDEV_DRIVER_MANUAL, "/tmp/some/block/dev"),
1346 a8e3e009 Michael Hanselmann
      ])
1347 a8e3e009 Michael Hanselmann
1348 a8e3e009 Michael Hanselmann
  def testRbd(self):
1349 a8e3e009 Michael Hanselmann
    disk_info = [{
1350 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 8 * 1024,
1351 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDONLY,
1352 a8e3e009 Michael Hanselmann
      }, {
1353 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 100 * 1024,
1354 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1355 a8e3e009 Michael Hanselmann
      }]
1356 a8e3e009 Michael Hanselmann
1357 a8e3e009 Michael Hanselmann
    result = self._TestTrivialDisk(constants.DT_RBD, disk_info, 0,
1358 cd3b4ff4 Helga Velroyen
                                   constants.DT_RBD)
1359 a8e3e009 Michael Hanselmann
1360 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1361 a8e3e009 Michael Hanselmann
      ("rbd", "ec0-uq0.rbd.disk0"),
1362 a8e3e009 Michael Hanselmann
      ("rbd", "ec0-uq1.rbd.disk1"),
1363 a8e3e009 Michael Hanselmann
      ])
1364 a8e3e009 Michael Hanselmann
1365 a8e3e009 Michael Hanselmann
  def testDrbd8(self):
1366 5eacbcae Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1367 cd3b4ff4 Helga Velroyen
    drbd8_defaults = constants.DISK_DT_DEFAULTS[constants.DT_DRBD8]
1368 a8e3e009 Michael Hanselmann
    drbd8_default_metavg = drbd8_defaults[constants.LDP_DEFAULT_METAVG]
1369 a8e3e009 Michael Hanselmann
1370 a8e3e009 Michael Hanselmann
    disk_info = [{
1371 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 1024,
1372 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1373 a8e3e009 Michael Hanselmann
      }, {
1374 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 100 * 1024,
1375 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDONLY,
1376 a8e3e009 Michael Hanselmann
      constants.IDISK_METAVG: "metavg",
1377 a8e3e009 Michael Hanselmann
      }, {
1378 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 4096,
1379 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1380 a8e3e009 Michael Hanselmann
      constants.IDISK_VG: "vgxyz",
1381 a8e3e009 Michael Hanselmann
      },
1382 a8e3e009 Michael Hanselmann
      ]
1383 a8e3e009 Michael Hanselmann
1384 a8e3e009 Michael Hanselmann
    exp_logical_ids = [[
1385 a8e3e009 Michael Hanselmann
      (self.lu.cfg.GetVGName(), "ec0-uq0.disk0_data"),
1386 a8e3e009 Michael Hanselmann
      (drbd8_default_metavg, "ec0-uq0.disk0_meta"),
1387 a8e3e009 Michael Hanselmann
      ], [
1388 a8e3e009 Michael Hanselmann
      (self.lu.cfg.GetVGName(), "ec0-uq1.disk1_data"),
1389 a8e3e009 Michael Hanselmann
      ("metavg", "ec0-uq1.disk1_meta"),
1390 a8e3e009 Michael Hanselmann
      ], [
1391 a8e3e009 Michael Hanselmann
      ("vgxyz", "ec0-uq2.disk2_data"),
1392 a8e3e009 Michael Hanselmann
      (drbd8_default_metavg, "ec0-uq2.disk2_meta"),
1393 a8e3e009 Michael Hanselmann
      ]]
1394 a8e3e009 Michael Hanselmann
1395 a8e3e009 Michael Hanselmann
    assert len(exp_logical_ids) == len(disk_info)
1396 a8e3e009 Michael Hanselmann
1397 a8e3e009 Michael Hanselmann
    map(lambda params: utils.ForceDictType(params,
1398 a8e3e009 Michael Hanselmann
                                           constants.IDISK_PARAMS_TYPES),
1399 a8e3e009 Michael Hanselmann
        disk_info)
1400 a8e3e009 Michael Hanselmann
1401 a8e3e009 Michael Hanselmann
    # Check if empty list of secondaries is rejected
1402 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, gdt, self.lu, constants.DT_DRBD8,
1403 a8e3e009 Michael Hanselmann
                      "inst827.example.com", "node1334.example.com", [],
1404 a8e3e009 Michael Hanselmann
                      disk_info, NotImplemented, NotImplemented, 0,
1405 99ccf8b9 René Nussbaumer
                      self.lu.LogInfo, self.GetDiskParams())
1406 a8e3e009 Michael Hanselmann
1407 a8e3e009 Michael Hanselmann
    result = gdt(self.lu, constants.DT_DRBD8, "inst827.example.com",
1408 a8e3e009 Michael Hanselmann
                 "node1334.example.com", ["node12272.example.com"],
1409 a8e3e009 Michael Hanselmann
                 disk_info, NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1410 99ccf8b9 René Nussbaumer
                 self.GetDiskParams())
1411 a8e3e009 Michael Hanselmann
1412 a8e3e009 Michael Hanselmann
    for (idx, disk) in enumerate(result):
1413 a8e3e009 Michael Hanselmann
      self.assertTrue(isinstance(disk, objects.Disk))
1414 cd3b4ff4 Helga Velroyen
      self.assertEqual(disk.dev_type, constants.DT_DRBD8)
1415 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.size, disk_info[idx][constants.IDISK_SIZE])
1416 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.mode, disk_info[idx][constants.IDISK_MODE])
1417 a8e3e009 Michael Hanselmann
1418 a8e3e009 Michael Hanselmann
      for child in disk.children:
1419 a8e3e009 Michael Hanselmann
        self.assertTrue(isinstance(disk, objects.Disk))
1420 cd3b4ff4 Helga Velroyen
        self.assertEqual(child.dev_type, constants.DT_PLAIN)
1421 a8e3e009 Michael Hanselmann
        self.assertTrue(child.children is None)
1422 a8e3e009 Michael Hanselmann
1423 a8e3e009 Michael Hanselmann
      self.assertEqual(map(operator.attrgetter("logical_id"), disk.children),
1424 a8e3e009 Michael Hanselmann
                       exp_logical_ids[idx])
1425 a8e3e009 Michael Hanselmann
1426 a8e3e009 Michael Hanselmann
      self.assertEqual(len(disk.children), 2)
1427 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.children[0].size, disk.size)
1428 0c77c331 René Nussbaumer
      self.assertEqual(disk.children[1].size, constants.DRBD_META_SIZE)
1429 a8e3e009 Michael Hanselmann
1430 0356a13d Michael Hanselmann
    self._CheckIvNames(result, 0, len(disk_info))
1431 22b7f6f8 Thomas Thrainer
    instance._UpdateIvNames(0, result)
1432 0356a13d Michael Hanselmann
    self._CheckIvNames(result, 0, len(disk_info))
1433 a8e3e009 Michael Hanselmann
1434 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1435 a8e3e009 Michael Hanselmann
      ("node1334.example.com", "node12272.example.com",
1436 a8e3e009 Michael Hanselmann
       constants.FIRST_DRBD_PORT, 20, 21, "ec0-secret0"),
1437 a8e3e009 Michael Hanselmann
      ("node1334.example.com", "node12272.example.com",
1438 a8e3e009 Michael Hanselmann
       constants.FIRST_DRBD_PORT + 1, 22, 23, "ec0-secret1"),
1439 a8e3e009 Michael Hanselmann
      ("node1334.example.com", "node12272.example.com",
1440 a8e3e009 Michael Hanselmann
       constants.FIRST_DRBD_PORT + 2, 24, 25, "ec0-secret2"),
1441 a8e3e009 Michael Hanselmann
      ])
1442 a8e3e009 Michael Hanselmann
1443 a8e3e009 Michael Hanselmann
1444 129cce69 Michael Hanselmann
class _ConfigForDiskWipe:
1445 1c3231aa Thomas Thrainer
  def __init__(self, exp_node_uuid):
1446 1c3231aa Thomas Thrainer
    self._exp_node_uuid = exp_node_uuid
1447 555b6cb1 Michael Hanselmann
1448 1c3231aa Thomas Thrainer
  def SetDiskID(self, device, node_uuid):
1449 129cce69 Michael Hanselmann
    assert isinstance(device, objects.Disk)
1450 1c3231aa Thomas Thrainer
    assert node_uuid == self._exp_node_uuid
1451 1c3231aa Thomas Thrainer
1452 1c3231aa Thomas Thrainer
  def GetNodeName(self, node_uuid):
1453 1c3231aa Thomas Thrainer
    assert node_uuid == self._exp_node_uuid
1454 1c3231aa Thomas Thrainer
    return "name.of.expected.node"
1455 129cce69 Michael Hanselmann
1456 129cce69 Michael Hanselmann
1457 129cce69 Michael Hanselmann
class _RpcForDiskWipe:
1458 555b6cb1 Michael Hanselmann
  def __init__(self, exp_node, pause_cb, wipe_cb):
1459 555b6cb1 Michael Hanselmann
    self._exp_node = exp_node
1460 129cce69 Michael Hanselmann
    self._pause_cb = pause_cb
1461 129cce69 Michael Hanselmann
    self._wipe_cb = wipe_cb
1462 129cce69 Michael Hanselmann
1463 129cce69 Michael Hanselmann
  def call_blockdev_pause_resume_sync(self, node, disks, pause):
1464 555b6cb1 Michael Hanselmann
    assert node == self._exp_node
1465 129cce69 Michael Hanselmann
    return rpc.RpcResult(data=self._pause_cb(disks, pause))
1466 129cce69 Michael Hanselmann
1467 129cce69 Michael Hanselmann
  def call_blockdev_wipe(self, node, bdev, offset, size):
1468 555b6cb1 Michael Hanselmann
    assert node == self._exp_node
1469 129cce69 Michael Hanselmann
    return rpc.RpcResult(data=self._wipe_cb(bdev, offset, size))
1470 129cce69 Michael Hanselmann
1471 129cce69 Michael Hanselmann
1472 129cce69 Michael Hanselmann
class _DiskPauseTracker:
1473 129cce69 Michael Hanselmann
  def __init__(self):
1474 129cce69 Michael Hanselmann
    self.history = []
1475 129cce69 Michael Hanselmann
1476 129cce69 Michael Hanselmann
  def __call__(self, (disks, instance), pause):
1477 fa8ef9d6 Michael Hanselmann
    assert not (set(disks) - set(instance.disks))
1478 129cce69 Michael Hanselmann
1479 129cce69 Michael Hanselmann
    self.history.extend((i.logical_id, i.size, pause)
1480 129cce69 Michael Hanselmann
                        for i in disks)
1481 129cce69 Michael Hanselmann
1482 129cce69 Michael Hanselmann
    return (True, [True] * len(disks))
1483 129cce69 Michael Hanselmann
1484 129cce69 Michael Hanselmann
1485 555b6cb1 Michael Hanselmann
class _DiskWipeProgressTracker:
1486 555b6cb1 Michael Hanselmann
  def __init__(self, start_offset):
1487 555b6cb1 Michael Hanselmann
    self._start_offset = start_offset
1488 555b6cb1 Michael Hanselmann
    self.progress = {}
1489 555b6cb1 Michael Hanselmann
1490 555b6cb1 Michael Hanselmann
  def __call__(self, (disk, _), offset, size):
1491 555b6cb1 Michael Hanselmann
    assert isinstance(offset, (long, int))
1492 555b6cb1 Michael Hanselmann
    assert isinstance(size, (long, int))
1493 555b6cb1 Michael Hanselmann
1494 555b6cb1 Michael Hanselmann
    max_chunk_size = (disk.size / 100.0 * constants.MIN_WIPE_CHUNK_PERCENT)
1495 555b6cb1 Michael Hanselmann
1496 555b6cb1 Michael Hanselmann
    assert offset >= self._start_offset
1497 555b6cb1 Michael Hanselmann
    assert (offset + size) <= disk.size
1498 555b6cb1 Michael Hanselmann
1499 555b6cb1 Michael Hanselmann
    assert size > 0
1500 555b6cb1 Michael Hanselmann
    assert size <= constants.MAX_WIPE_CHUNK
1501 555b6cb1 Michael Hanselmann
    assert size <= max_chunk_size
1502 555b6cb1 Michael Hanselmann
1503 555b6cb1 Michael Hanselmann
    assert offset == self._start_offset or disk.logical_id in self.progress
1504 555b6cb1 Michael Hanselmann
1505 555b6cb1 Michael Hanselmann
    # Keep track of progress
1506 555b6cb1 Michael Hanselmann
    cur_progress = self.progress.setdefault(disk.logical_id, self._start_offset)
1507 555b6cb1 Michael Hanselmann
1508 555b6cb1 Michael Hanselmann
    assert cur_progress == offset
1509 555b6cb1 Michael Hanselmann
1510 555b6cb1 Michael Hanselmann
    # Record progress
1511 555b6cb1 Michael Hanselmann
    self.progress[disk.logical_id] += size
1512 555b6cb1 Michael Hanselmann
1513 555b6cb1 Michael Hanselmann
    return (True, None)
1514 555b6cb1 Michael Hanselmann
1515 555b6cb1 Michael Hanselmann
1516 129cce69 Michael Hanselmann
class TestWipeDisks(unittest.TestCase):
1517 555b6cb1 Michael Hanselmann
  def _FailingPauseCb(self, (disks, _), pause):
1518 555b6cb1 Michael Hanselmann
    self.assertEqual(len(disks), 3)
1519 555b6cb1 Michael Hanselmann
    self.assertTrue(pause)
1520 555b6cb1 Michael Hanselmann
    # Simulate an RPC error
1521 555b6cb1 Michael Hanselmann
    return (False, "error")
1522 555b6cb1 Michael Hanselmann
1523 129cce69 Michael Hanselmann
  def testPauseFailure(self):
1524 555b6cb1 Michael Hanselmann
    node_name = "node1372.example.com"
1525 129cce69 Michael Hanselmann
1526 555b6cb1 Michael Hanselmann
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, self._FailingPauseCb,
1527 555b6cb1 Michael Hanselmann
                                     NotImplemented),
1528 555b6cb1 Michael Hanselmann
                 cfg=_ConfigForDiskWipe(node_name))
1529 129cce69 Michael Hanselmann
1530 129cce69 Michael Hanselmann
    disks = [
1531 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN),
1532 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN),
1533 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN),
1534 129cce69 Michael Hanselmann
      ]
1535 129cce69 Michael Hanselmann
1536 22b7f6f8 Thomas Thrainer
    inst = objects.Instance(name="inst21201",
1537 22b7f6f8 Thomas Thrainer
                            primary_node=node_name,
1538 22b7f6f8 Thomas Thrainer
                            disk_template=constants.DT_PLAIN,
1539 22b7f6f8 Thomas Thrainer
                            disks=disks)
1540 129cce69 Michael Hanselmann
1541 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpExecError, instance.WipeDisks, lu, inst)
1542 129cce69 Michael Hanselmann
1543 555b6cb1 Michael Hanselmann
  def _FailingWipeCb(self, (disk, _), offset, size):
1544 555b6cb1 Michael Hanselmann
    # This should only ever be called for the first disk
1545 555b6cb1 Michael Hanselmann
    self.assertEqual(disk.logical_id, "disk0")
1546 555b6cb1 Michael Hanselmann
    return (False, None)
1547 555b6cb1 Michael Hanselmann
1548 129cce69 Michael Hanselmann
  def testFailingWipe(self):
1549 1c3231aa Thomas Thrainer
    node_uuid = "node13445-uuid"
1550 129cce69 Michael Hanselmann
    pt = _DiskPauseTracker()
1551 129cce69 Michael Hanselmann
1552 1c3231aa Thomas Thrainer
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_uuid, pt, self._FailingWipeCb),
1553 1c3231aa Thomas Thrainer
                 cfg=_ConfigForDiskWipe(node_uuid))
1554 129cce69 Michael Hanselmann
1555 129cce69 Michael Hanselmann
    disks = [
1556 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk0",
1557 129cce69 Michael Hanselmann
                   size=100 * 1024),
1558 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk1",
1559 129cce69 Michael Hanselmann
                   size=500 * 1024),
1560 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk2", size=256),
1561 129cce69 Michael Hanselmann
      ]
1562 129cce69 Michael Hanselmann
1563 22b7f6f8 Thomas Thrainer
    inst = objects.Instance(name="inst562",
1564 1c3231aa Thomas Thrainer
                            primary_node=node_uuid,
1565 22b7f6f8 Thomas Thrainer
                            disk_template=constants.DT_PLAIN,
1566 22b7f6f8 Thomas Thrainer
                            disks=disks)
1567 129cce69 Michael Hanselmann
1568 129cce69 Michael Hanselmann
    try:
1569 5eacbcae Thomas Thrainer
      instance.WipeDisks(lu, inst)
1570 129cce69 Michael Hanselmann
    except errors.OpExecError, err:
1571 129cce69 Michael Hanselmann
      self.assertTrue(str(err), "Could not wipe disk 0 at offset 0 ")
1572 129cce69 Michael Hanselmann
    else:
1573 129cce69 Michael Hanselmann
      self.fail("Did not raise exception")
1574 129cce69 Michael Hanselmann
1575 555b6cb1 Michael Hanselmann
    # Check if all disks were paused and resumed
1576 129cce69 Michael Hanselmann
    self.assertEqual(pt.history, [
1577 129cce69 Michael Hanselmann
      ("disk0", 100 * 1024, True),
1578 129cce69 Michael Hanselmann
      ("disk1", 500 * 1024, True),
1579 129cce69 Michael Hanselmann
      ("disk2", 256, True),
1580 129cce69 Michael Hanselmann
      ("disk0", 100 * 1024, False),
1581 129cce69 Michael Hanselmann
      ("disk1", 500 * 1024, False),
1582 129cce69 Michael Hanselmann
      ("disk2", 256, False),
1583 129cce69 Michael Hanselmann
      ])
1584 129cce69 Michael Hanselmann
1585 555b6cb1 Michael Hanselmann
  def _PrepareWipeTest(self, start_offset, disks):
1586 555b6cb1 Michael Hanselmann
    node_name = "node-with-offset%s.example.com" % start_offset
1587 555b6cb1 Michael Hanselmann
    pauset = _DiskPauseTracker()
1588 555b6cb1 Michael Hanselmann
    progresst = _DiskWipeProgressTracker(start_offset)
1589 129cce69 Michael Hanselmann
1590 555b6cb1 Michael Hanselmann
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, pauset, progresst),
1591 555b6cb1 Michael Hanselmann
                 cfg=_ConfigForDiskWipe(node_name))
1592 129cce69 Michael Hanselmann
1593 555b6cb1 Michael Hanselmann
    instance = objects.Instance(name="inst3560",
1594 555b6cb1 Michael Hanselmann
                                primary_node=node_name,
1595 555b6cb1 Michael Hanselmann
                                disk_template=constants.DT_PLAIN,
1596 555b6cb1 Michael Hanselmann
                                disks=disks)
1597 129cce69 Michael Hanselmann
1598 555b6cb1 Michael Hanselmann
    return (lu, instance, pauset, progresst)
1599 555b6cb1 Michael Hanselmann
1600 555b6cb1 Michael Hanselmann
  def testNormalWipe(self):
1601 555b6cb1 Michael Hanselmann
    disks = [
1602 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk0", size=1024),
1603 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk1",
1604 555b6cb1 Michael Hanselmann
                   size=500 * 1024),
1605 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk2", size=128),
1606 cd3b4ff4 Helga Velroyen
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk3",
1607 555b6cb1 Michael Hanselmann
                   size=constants.MAX_WIPE_CHUNK),
1608 555b6cb1 Michael Hanselmann
      ]
1609 129cce69 Michael Hanselmann
1610 22b7f6f8 Thomas Thrainer
    (lu, inst, pauset, progresst) = self._PrepareWipeTest(0, disks)
1611 129cce69 Michael Hanselmann
1612 5eacbcae Thomas Thrainer
    instance.WipeDisks(lu, inst)
1613 129cce69 Michael Hanselmann
1614 555b6cb1 Michael Hanselmann
    self.assertEqual(pauset.history, [
1615 555b6cb1 Michael Hanselmann
      ("disk0", 1024, True),
1616 555b6cb1 Michael Hanselmann
      ("disk1", 500 * 1024, True),
1617 555b6cb1 Michael Hanselmann
      ("disk2", 128, True),
1618 555b6cb1 Michael Hanselmann
      ("disk3", constants.MAX_WIPE_CHUNK, True),
1619 555b6cb1 Michael Hanselmann
      ("disk0", 1024, False),
1620 555b6cb1 Michael Hanselmann
      ("disk1", 500 * 1024, False),
1621 555b6cb1 Michael Hanselmann
      ("disk2", 128, False),
1622 555b6cb1 Michael Hanselmann
      ("disk3", constants.MAX_WIPE_CHUNK, False),
1623 555b6cb1 Michael Hanselmann
      ])
1624 129cce69 Michael Hanselmann
1625 555b6cb1 Michael Hanselmann
    # Ensure the complete disk has been wiped
1626 555b6cb1 Michael Hanselmann
    self.assertEqual(progresst.progress,
1627 555b6cb1 Michael Hanselmann
                     dict((i.logical_id, i.size) for i in disks))
1628 129cce69 Michael Hanselmann
1629 555b6cb1 Michael Hanselmann
  def testWipeWithStartOffset(self):
1630 555b6cb1 Michael Hanselmann
    for start_offset in [0, 280, 8895, 1563204]:
1631 555b6cb1 Michael Hanselmann
      disks = [
1632 cd3b4ff4 Helga Velroyen
        objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk0",
1633 555b6cb1 Michael Hanselmann
                     size=128),
1634 cd3b4ff4 Helga Velroyen
        objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk1",
1635 555b6cb1 Michael Hanselmann
                     size=start_offset + (100 * 1024)),
1636 555b6cb1 Michael Hanselmann
        ]
1637 129cce69 Michael Hanselmann
1638 22b7f6f8 Thomas Thrainer
      (lu, inst, pauset, progresst) = \
1639 555b6cb1 Michael Hanselmann
        self._PrepareWipeTest(start_offset, disks)
1640 129cce69 Michael Hanselmann
1641 555b6cb1 Michael Hanselmann
      # Test start offset with only one disk
1642 5eacbcae Thomas Thrainer
      instance.WipeDisks(lu, inst,
1643 5eacbcae Thomas Thrainer
                         disks=[(1, disks[1], start_offset)])
1644 129cce69 Michael Hanselmann
1645 555b6cb1 Michael Hanselmann
      # Only the second disk may have been paused and wiped
1646 555b6cb1 Michael Hanselmann
      self.assertEqual(pauset.history, [
1647 555b6cb1 Michael Hanselmann
        ("disk1", start_offset + (100 * 1024), True),
1648 555b6cb1 Michael Hanselmann
        ("disk1", start_offset + (100 * 1024), False),
1649 555b6cb1 Michael Hanselmann
        ])
1650 555b6cb1 Michael Hanselmann
      self.assertEqual(progresst.progress, {
1651 555b6cb1 Michael Hanselmann
        "disk1": disks[1].size,
1652 555b6cb1 Michael Hanselmann
        })
1653 fa8ef9d6 Michael Hanselmann
1654 fa8ef9d6 Michael Hanselmann
1655 fa8ef9d6 Michael Hanselmann
class TestDiskSizeInBytesToMebibytes(unittest.TestCase):
1656 fa8ef9d6 Michael Hanselmann
  def testLessThanOneMebibyte(self):
1657 fa8ef9d6 Michael Hanselmann
    for i in [1, 2, 7, 512, 1000, 1023]:
1658 fa8ef9d6 Michael Hanselmann
      lu = _FakeLU()
1659 763ad5be Thomas Thrainer
      result = instance_storage._DiskSizeInBytesToMebibytes(lu, i)
1660 fa8ef9d6 Michael Hanselmann
      self.assertEqual(result, 1)
1661 fa8ef9d6 Michael Hanselmann
      self.assertEqual(len(lu.warning_log), 1)
1662 fa8ef9d6 Michael Hanselmann
      self.assertEqual(len(lu.warning_log[0]), 2)
1663 fa8ef9d6 Michael Hanselmann
      (_, (warnsize, )) = lu.warning_log[0]
1664 fa8ef9d6 Michael Hanselmann
      self.assertEqual(warnsize, (1024 * 1024) - i)
1665 fa8ef9d6 Michael Hanselmann
1666 fa8ef9d6 Michael Hanselmann
  def testEven(self):
1667 fa8ef9d6 Michael Hanselmann
    for i in [1, 2, 7, 512, 1000, 1023]:
1668 fa8ef9d6 Michael Hanselmann
      lu = _FakeLU()
1669 763ad5be Thomas Thrainer
      result = instance_storage._DiskSizeInBytesToMebibytes(lu,
1670 763ad5be Thomas Thrainer
                                                            i * 1024 * 1024)
1671 fa8ef9d6 Michael Hanselmann
      self.assertEqual(result, i)
1672 fa8ef9d6 Michael Hanselmann
      self.assertFalse(lu.warning_log)
1673 fa8ef9d6 Michael Hanselmann
1674 fa8ef9d6 Michael Hanselmann
  def testLargeNumber(self):
1675 fa8ef9d6 Michael Hanselmann
    for i in [1, 2, 7, 512, 1000, 1023, 2724, 12420]:
1676 fa8ef9d6 Michael Hanselmann
      for j in [1, 2, 486, 326, 986, 1023]:
1677 fa8ef9d6 Michael Hanselmann
        lu = _FakeLU()
1678 fa8ef9d6 Michael Hanselmann
        size = (1024 * 1024 * i) + j
1679 763ad5be Thomas Thrainer
        result = instance_storage._DiskSizeInBytesToMebibytes(lu, size)
1680 fa8ef9d6 Michael Hanselmann
        self.assertEqual(result, i + 1, msg="Amount was not rounded up")
1681 fa8ef9d6 Michael Hanselmann
        self.assertEqual(len(lu.warning_log), 1)
1682 fa8ef9d6 Michael Hanselmann
        self.assertEqual(len(lu.warning_log[0]), 2)
1683 fa8ef9d6 Michael Hanselmann
        (_, (warnsize, )) = lu.warning_log[0]
1684 fa8ef9d6 Michael Hanselmann
        self.assertEqual(warnsize, (1024 * 1024) - j)
1685 129cce69 Michael Hanselmann
1686 129cce69 Michael Hanselmann
1687 ef86bf28 Michael Hanselmann
class TestCopyLockList(unittest.TestCase):
1688 ef86bf28 Michael Hanselmann
  def test(self):
1689 5eacbcae Thomas Thrainer
    self.assertEqual(instance.CopyLockList([]), [])
1690 5eacbcae Thomas Thrainer
    self.assertEqual(instance.CopyLockList(None), None)
1691 5eacbcae Thomas Thrainer
    self.assertEqual(instance.CopyLockList(locking.ALL_SET), locking.ALL_SET)
1692 ef86bf28 Michael Hanselmann
1693 ef86bf28 Michael Hanselmann
    names = ["foo", "bar"]
1694 5eacbcae Thomas Thrainer
    output = instance.CopyLockList(names)
1695 ef86bf28 Michael Hanselmann
    self.assertEqual(names, output)
1696 ef86bf28 Michael Hanselmann
    self.assertNotEqual(id(names), id(output), msg="List was not copied")
1697 ef86bf28 Michael Hanselmann
1698 ef86bf28 Michael Hanselmann
1699 cfa79a23 Michael Hanselmann
class TestCheckOpportunisticLocking(unittest.TestCase):
1700 cfa79a23 Michael Hanselmann
  class OpTest(opcodes.OpCode):
1701 cfa79a23 Michael Hanselmann
    OP_PARAMS = [
1702 cfa79a23 Michael Hanselmann
      opcodes._POpportunisticLocking,
1703 cfa79a23 Michael Hanselmann
      opcodes._PIAllocFromDesc(""),
1704 cfa79a23 Michael Hanselmann
      ]
1705 cfa79a23 Michael Hanselmann
1706 cfa79a23 Michael Hanselmann
  @classmethod
1707 cfa79a23 Michael Hanselmann
  def _MakeOp(cls, **kwargs):
1708 cfa79a23 Michael Hanselmann
    op = cls.OpTest(**kwargs)
1709 cfa79a23 Michael Hanselmann
    op.Validate(True)
1710 cfa79a23 Michael Hanselmann
    return op
1711 cfa79a23 Michael Hanselmann
1712 cfa79a23 Michael Hanselmann
  def testMissingAttributes(self):
1713 22b7f6f8 Thomas Thrainer
    self.assertRaises(AttributeError, instance._CheckOpportunisticLocking,
1714 cfa79a23 Michael Hanselmann
                      object())
1715 cfa79a23 Michael Hanselmann
1716 cfa79a23 Michael Hanselmann
  def testDefaults(self):
1717 cfa79a23 Michael Hanselmann
    op = self._MakeOp()
1718 22b7f6f8 Thomas Thrainer
    instance._CheckOpportunisticLocking(op)
1719 cfa79a23 Michael Hanselmann
1720 cfa79a23 Michael Hanselmann
  def test(self):
1721 cfa79a23 Michael Hanselmann
    for iallocator in [None, "something", "other"]:
1722 cfa79a23 Michael Hanselmann
      for opplock in [False, True]:
1723 22b7f6f8 Thomas Thrainer
        op = self._MakeOp(iallocator=iallocator,
1724 22b7f6f8 Thomas Thrainer
                          opportunistic_locking=opplock)
1725 cfa79a23 Michael Hanselmann
        if opplock and not iallocator:
1726 cfa79a23 Michael Hanselmann
          self.assertRaises(errors.OpPrereqError,
1727 22b7f6f8 Thomas Thrainer
                            instance._CheckOpportunisticLocking, op)
1728 cfa79a23 Michael Hanselmann
        else:
1729 22b7f6f8 Thomas Thrainer
          instance._CheckOpportunisticLocking(op)
1730 cfa79a23 Michael Hanselmann
1731 cfa79a23 Michael Hanselmann
1732 8bb2df7d Bernardo Dal Seno
class _OpTestVerifyErrors(opcodes.OpCode):
1733 8bb2df7d Bernardo Dal Seno
  OP_PARAMS = [
1734 8bb2df7d Bernardo Dal Seno
    opcodes._PDebugSimulateErrors,
1735 8bb2df7d Bernardo Dal Seno
    opcodes._PErrorCodes,
1736 8bb2df7d Bernardo Dal Seno
    opcodes._PIgnoreErrors,
1737 8bb2df7d Bernardo Dal Seno
    ]
1738 8bb2df7d Bernardo Dal Seno
1739 8bb2df7d Bernardo Dal Seno
1740 7352d33b Thomas Thrainer
class _LuTestVerifyErrors(cluster._VerifyErrors):
1741 8bb2df7d Bernardo Dal Seno
  def __init__(self, **kwargs):
1742 7352d33b Thomas Thrainer
    cluster._VerifyErrors.__init__(self)
1743 8bb2df7d Bernardo Dal Seno
    self.op = _OpTestVerifyErrors(**kwargs)
1744 8bb2df7d Bernardo Dal Seno
    self.op.Validate(True)
1745 8bb2df7d Bernardo Dal Seno
    self.msglist = []
1746 8bb2df7d Bernardo Dal Seno
    self._feedback_fn = self.msglist.append
1747 8bb2df7d Bernardo Dal Seno
    self.bad = False
1748 8bb2df7d Bernardo Dal Seno
1749 8bb2df7d Bernardo Dal Seno
  def DispatchCallError(self, which, *args, **kwargs):
1750 8bb2df7d Bernardo Dal Seno
    if which:
1751 8bb2df7d Bernardo Dal Seno
      self._Error(*args, **kwargs)
1752 8bb2df7d Bernardo Dal Seno
    else:
1753 8bb2df7d Bernardo Dal Seno
      self._ErrorIf(True, *args, **kwargs)
1754 8bb2df7d Bernardo Dal Seno
1755 8bb2df7d Bernardo Dal Seno
  def CallErrorIf(self, c, *args, **kwargs):
1756 8bb2df7d Bernardo Dal Seno
    self._ErrorIf(c, *args, **kwargs)
1757 8bb2df7d Bernardo Dal Seno
1758 8bb2df7d Bernardo Dal Seno
1759 8bb2df7d Bernardo Dal Seno
class TestVerifyErrors(unittest.TestCase):
1760 8bb2df7d Bernardo Dal Seno
  # Fake cluster-verify error code structures; we use two arbitary real error
1761 8bb2df7d Bernardo Dal Seno
  # codes to pass validation of ignore_errors
1762 8bb2df7d Bernardo Dal Seno
  (_, _ERR1ID, _) = constants.CV_ECLUSTERCFG
1763 8bb2df7d Bernardo Dal Seno
  _NODESTR = "node"
1764 8bb2df7d Bernardo Dal Seno
  _NODENAME = "mynode"
1765 8bb2df7d Bernardo Dal Seno
  _ERR1CODE = (_NODESTR, _ERR1ID, "Error one")
1766 8bb2df7d Bernardo Dal Seno
  (_, _ERR2ID, _) = constants.CV_ECLUSTERCERT
1767 8bb2df7d Bernardo Dal Seno
  _INSTSTR = "instance"
1768 8bb2df7d Bernardo Dal Seno
  _INSTNAME = "myinstance"
1769 8bb2df7d Bernardo Dal Seno
  _ERR2CODE = (_INSTSTR, _ERR2ID, "Error two")
1770 8bb2df7d Bernardo Dal Seno
  # Arguments used to call _Error() or _ErrorIf()
1771 8bb2df7d Bernardo Dal Seno
  _ERR1ARGS = (_ERR1CODE, _NODENAME, "Error1 is %s", "an error")
1772 8bb2df7d Bernardo Dal Seno
  _ERR2ARGS = (_ERR2CODE, _INSTNAME, "Error2 has no argument")
1773 8bb2df7d Bernardo Dal Seno
  # Expected error messages
1774 8bb2df7d Bernardo Dal Seno
  _ERR1MSG = _ERR1ARGS[2] % _ERR1ARGS[3]
1775 8bb2df7d Bernardo Dal Seno
  _ERR2MSG = _ERR2ARGS[2]
1776 8bb2df7d Bernardo Dal Seno
1777 8bb2df7d Bernardo Dal Seno
  def testNoError(self):
1778 8bb2df7d Bernardo Dal Seno
    lu = _LuTestVerifyErrors()
1779 8bb2df7d Bernardo Dal Seno
    lu.CallErrorIf(False, self._ERR1CODE, *self._ERR1ARGS)
1780 8bb2df7d Bernardo Dal Seno
    self.assertFalse(lu.bad)
1781 8bb2df7d Bernardo Dal Seno
    self.assertFalse(lu.msglist)
1782 8bb2df7d Bernardo Dal Seno
1783 8bb2df7d Bernardo Dal Seno
  def _InitTest(self, **kwargs):
1784 8bb2df7d Bernardo Dal Seno
    self.lu1 = _LuTestVerifyErrors(**kwargs)
1785 8bb2df7d Bernardo Dal Seno
    self.lu2 = _LuTestVerifyErrors(**kwargs)
1786 8bb2df7d Bernardo Dal Seno
1787 8bb2df7d Bernardo Dal Seno
  def _CallError(self, *args, **kwargs):
1788 8bb2df7d Bernardo Dal Seno
    # Check that _Error() and _ErrorIf() produce the same results
1789 8bb2df7d Bernardo Dal Seno
    self.lu1.DispatchCallError(True, *args, **kwargs)
1790 8bb2df7d Bernardo Dal Seno
    self.lu2.DispatchCallError(False, *args, **kwargs)
1791 8bb2df7d Bernardo Dal Seno
    self.assertEqual(self.lu1.bad, self.lu2.bad)
1792 8bb2df7d Bernardo Dal Seno
    self.assertEqual(self.lu1.msglist, self.lu2.msglist)
1793 8bb2df7d Bernardo Dal Seno
    # Test-specific checks are made on one LU
1794 8bb2df7d Bernardo Dal Seno
    return self.lu1
1795 8bb2df7d Bernardo Dal Seno
1796 8bb2df7d Bernardo Dal Seno
  def _checkMsgCommon(self, logstr, errmsg, itype, item, warning):
1797 8bb2df7d Bernardo Dal Seno
    self.assertTrue(errmsg in logstr)
1798 8bb2df7d Bernardo Dal Seno
    if warning:
1799 8bb2df7d Bernardo Dal Seno
      self.assertTrue("WARNING" in logstr)
1800 8bb2df7d Bernardo Dal Seno
    else:
1801 8bb2df7d Bernardo Dal Seno
      self.assertTrue("ERROR" in logstr)
1802 8bb2df7d Bernardo Dal Seno
    self.assertTrue(itype in logstr)
1803 8bb2df7d Bernardo Dal Seno
    self.assertTrue(item in logstr)
1804 8bb2df7d Bernardo Dal Seno
1805 8bb2df7d Bernardo Dal Seno
  def _checkMsg1(self, logstr, warning=False):
1806 8bb2df7d Bernardo Dal Seno
    self._checkMsgCommon(logstr, self._ERR1MSG, self._NODESTR,
1807 8bb2df7d Bernardo Dal Seno
                         self._NODENAME, warning)
1808 8bb2df7d Bernardo Dal Seno
1809 8bb2df7d Bernardo Dal Seno
  def _checkMsg2(self, logstr, warning=False):
1810 8bb2df7d Bernardo Dal Seno
    self._checkMsgCommon(logstr, self._ERR2MSG, self._INSTSTR,
1811 8bb2df7d Bernardo Dal Seno
                         self._INSTNAME, warning)
1812 8bb2df7d Bernardo Dal Seno
1813 8bb2df7d Bernardo Dal Seno
  def testPlain(self):
1814 8bb2df7d Bernardo Dal Seno
    self._InitTest()
1815 8bb2df7d Bernardo Dal Seno
    lu = self._CallError(*self._ERR1ARGS)
1816 8bb2df7d Bernardo Dal Seno
    self.assertTrue(lu.bad)
1817 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 1)
1818 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0])
1819 8bb2df7d Bernardo Dal Seno
1820 8bb2df7d Bernardo Dal Seno
  def testMultiple(self):
1821 8bb2df7d Bernardo Dal Seno
    self._InitTest()
1822 8bb2df7d Bernardo Dal Seno
    self._CallError(*self._ERR1ARGS)
1823 8bb2df7d Bernardo Dal Seno
    lu = self._CallError(*self._ERR2ARGS)
1824 8bb2df7d Bernardo Dal Seno
    self.assertTrue(lu.bad)
1825 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 2)
1826 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0])
1827 8bb2df7d Bernardo Dal Seno
    self._checkMsg2(lu.msglist[1])
1828 8bb2df7d Bernardo Dal Seno
1829 8bb2df7d Bernardo Dal Seno
  def testIgnore(self):
1830 8bb2df7d Bernardo Dal Seno
    self._InitTest(ignore_errors=[self._ERR1ID])
1831 8bb2df7d Bernardo Dal Seno
    lu = self._CallError(*self._ERR1ARGS)
1832 8bb2df7d Bernardo Dal Seno
    self.assertFalse(lu.bad)
1833 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 1)
1834 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0], warning=True)
1835 8bb2df7d Bernardo Dal Seno
1836 8bb2df7d Bernardo Dal Seno
  def testWarning(self):
1837 8bb2df7d Bernardo Dal Seno
    self._InitTest()
1838 8bb2df7d Bernardo Dal Seno
    lu = self._CallError(*self._ERR1ARGS,
1839 8bb2df7d Bernardo Dal Seno
                         code=_LuTestVerifyErrors.ETYPE_WARNING)
1840 8bb2df7d Bernardo Dal Seno
    self.assertFalse(lu.bad)
1841 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 1)
1842 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0], warning=True)
1843 8bb2df7d Bernardo Dal Seno
1844 8bb2df7d Bernardo Dal Seno
  def testWarning2(self):
1845 8bb2df7d Bernardo Dal Seno
    self._InitTest()
1846 8bb2df7d Bernardo Dal Seno
    self._CallError(*self._ERR1ARGS)
1847 8bb2df7d Bernardo Dal Seno
    lu = self._CallError(*self._ERR2ARGS,
1848 8bb2df7d Bernardo Dal Seno
                         code=_LuTestVerifyErrors.ETYPE_WARNING)
1849 8bb2df7d Bernardo Dal Seno
    self.assertTrue(lu.bad)
1850 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 2)
1851 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0])
1852 8bb2df7d Bernardo Dal Seno
    self._checkMsg2(lu.msglist[1], warning=True)
1853 8bb2df7d Bernardo Dal Seno
1854 8bb2df7d Bernardo Dal Seno
  def testDebugSimulate(self):
1855 8bb2df7d Bernardo Dal Seno
    lu = _LuTestVerifyErrors(debug_simulate_errors=True)
1856 8bb2df7d Bernardo Dal Seno
    lu.CallErrorIf(False, *self._ERR1ARGS)
1857 8bb2df7d Bernardo Dal Seno
    self.assertTrue(lu.bad)
1858 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 1)
1859 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0])
1860 8bb2df7d Bernardo Dal Seno
1861 8bb2df7d Bernardo Dal Seno
  def testErrCodes(self):
1862 8bb2df7d Bernardo Dal Seno
    self._InitTest(error_codes=True)
1863 8bb2df7d Bernardo Dal Seno
    lu = self._CallError(*self._ERR1ARGS)
1864 8bb2df7d Bernardo Dal Seno
    self.assertTrue(lu.bad)
1865 8bb2df7d Bernardo Dal Seno
    self.assertEqual(len(lu.msglist), 1)
1866 8bb2df7d Bernardo Dal Seno
    self._checkMsg1(lu.msglist[0])
1867 8bb2df7d Bernardo Dal Seno
    self.assertTrue(self._ERR1ID in lu.msglist[0])
1868 8bb2df7d Bernardo Dal Seno
1869 8bb2df7d Bernardo Dal Seno
1870 5dd7d15b Bernardo Dal Seno
class TestGetUpdatedIPolicy(unittest.TestCase):
1871 5dd7d15b Bernardo Dal Seno
  """Tests for cmdlib._GetUpdatedIPolicy()"""
1872 5dd7d15b Bernardo Dal Seno
  _OLD_CLUSTER_POLICY = {
1873 5dd7d15b Bernardo Dal Seno
    constants.IPOLICY_VCPU_RATIO: 1.5,
1874 41044e04 Bernardo Dal Seno
    constants.ISPECS_MINMAX: [
1875 41044e04 Bernardo Dal Seno
      {
1876 41044e04 Bernardo Dal Seno
        constants.ISPECS_MIN: {
1877 41044e04 Bernardo Dal Seno
          constants.ISPEC_MEM_SIZE: 32768,
1878 41044e04 Bernardo Dal Seno
          constants.ISPEC_CPU_COUNT: 8,
1879 41044e04 Bernardo Dal Seno
          constants.ISPEC_DISK_COUNT: 1,
1880 41044e04 Bernardo Dal Seno
          constants.ISPEC_DISK_SIZE: 1024,
1881 41044e04 Bernardo Dal Seno
          constants.ISPEC_NIC_COUNT: 1,
1882 41044e04 Bernardo Dal Seno
          constants.ISPEC_SPINDLE_USE: 1,
1883 41044e04 Bernardo Dal Seno
          },
1884 41044e04 Bernardo Dal Seno
        constants.ISPECS_MAX: {
1885 41044e04 Bernardo Dal Seno
          constants.ISPEC_MEM_SIZE: 65536,
1886 41044e04 Bernardo Dal Seno
          constants.ISPEC_CPU_COUNT: 10,
1887 41044e04 Bernardo Dal Seno
          constants.ISPEC_DISK_COUNT: 5,
1888 41044e04 Bernardo Dal Seno
          constants.ISPEC_DISK_SIZE: 1024 * 1024,
1889 41044e04 Bernardo Dal Seno
          constants.ISPEC_NIC_COUNT: 3,
1890 41044e04 Bernardo Dal Seno
          constants.ISPEC_SPINDLE_USE: 12,
1891 41044e04 Bernardo Dal Seno
          },
1892 41044e04 Bernardo Dal Seno
        },
1893 41044e04 Bernardo Dal Seno
      constants.ISPECS_MINMAX_DEFAULTS,
1894 41044e04 Bernardo Dal Seno
      ],
1895 0f511c8a Bernardo Dal Seno
    constants.ISPECS_STD: constants.IPOLICY_DEFAULTS[constants.ISPECS_STD],
1896 5dd7d15b Bernardo Dal Seno
    }
1897 5dd7d15b Bernardo Dal Seno
  _OLD_GROUP_POLICY = {
1898 5dd7d15b Bernardo Dal Seno
    constants.IPOLICY_SPINDLE_RATIO: 2.5,
1899 41044e04 Bernardo Dal Seno
    constants.ISPECS_MINMAX: [{
1900 da5f09ef Bernardo Dal Seno
      constants.ISPECS_MIN: {
1901 0f511c8a Bernardo Dal Seno
        constants.ISPEC_MEM_SIZE: 128,
1902 0f511c8a Bernardo Dal Seno
        constants.ISPEC_CPU_COUNT: 1,
1903 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_COUNT: 1,
1904 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_SIZE: 1024,
1905 0f511c8a Bernardo Dal Seno
        constants.ISPEC_NIC_COUNT: 1,
1906 0f511c8a Bernardo Dal Seno
        constants.ISPEC_SPINDLE_USE: 1,
1907 0f511c8a Bernardo Dal Seno
        },
1908 0f511c8a Bernardo Dal Seno
      constants.ISPECS_MAX: {
1909 0f511c8a Bernardo Dal Seno
        constants.ISPEC_MEM_SIZE: 32768,
1910 0f511c8a Bernardo Dal Seno
        constants.ISPEC_CPU_COUNT: 8,
1911 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_COUNT: 5,
1912 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_SIZE: 1024 * 1024,
1913 0f511c8a Bernardo Dal Seno
        constants.ISPEC_NIC_COUNT: 3,
1914 0f511c8a Bernardo Dal Seno
        constants.ISPEC_SPINDLE_USE: 12,
1915 da5f09ef Bernardo Dal Seno
        },
1916 41044e04 Bernardo Dal Seno
      }],
1917 5dd7d15b Bernardo Dal Seno
    }
1918 5dd7d15b Bernardo Dal Seno
1919 5dd7d15b Bernardo Dal Seno
  def _TestSetSpecs(self, old_policy, isgroup):
1920 41044e04 Bernardo Dal Seno
    diff_minmax = [{
1921 0f511c8a Bernardo Dal Seno
      constants.ISPECS_MIN: {
1922 0f511c8a Bernardo Dal Seno
        constants.ISPEC_MEM_SIZE: 64,
1923 0f511c8a Bernardo Dal Seno
        constants.ISPEC_CPU_COUNT: 1,
1924 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_COUNT: 2,
1925 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_SIZE: 64,
1926 0f511c8a Bernardo Dal Seno
        constants.ISPEC_NIC_COUNT: 1,
1927 0f511c8a Bernardo Dal Seno
        constants.ISPEC_SPINDLE_USE: 1,
1928 0f511c8a Bernardo Dal Seno
        },
1929 0f511c8a Bernardo Dal Seno
      constants.ISPECS_MAX: {
1930 0f511c8a Bernardo Dal Seno
        constants.ISPEC_MEM_SIZE: 16384,
1931 0f511c8a Bernardo Dal Seno
        constants.ISPEC_CPU_COUNT: 10,
1932 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_COUNT: 12,
1933 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_SIZE: 1024,
1934 0f511c8a Bernardo Dal Seno
        constants.ISPEC_NIC_COUNT: 9,
1935 0f511c8a Bernardo Dal Seno
        constants.ISPEC_SPINDLE_USE: 18,
1936 0f511c8a Bernardo Dal Seno
        },
1937 41044e04 Bernardo Dal Seno
      }]
1938 0f511c8a Bernardo Dal Seno
    diff_std = {
1939 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_COUNT: 10,
1940 0f511c8a Bernardo Dal Seno
        constants.ISPEC_DISK_SIZE: 512,
1941 0f511c8a Bernardo Dal Seno
        }
1942 5dd7d15b Bernardo Dal Seno
    diff_policy = {
1943 0f511c8a Bernardo Dal Seno
      constants.ISPECS_MINMAX: diff_minmax
1944 5dd7d15b Bernardo Dal Seno
      }
1945 da5f09ef Bernardo Dal Seno
    if not isgroup:
1946 da5f09ef Bernardo Dal Seno
      diff_policy[constants.ISPECS_STD] = diff_std
1947 5eacbcae Thomas Thrainer
    new_policy = common.GetUpdatedIPolicy(old_policy, diff_policy,
1948 5eacbcae Thomas Thrainer
                                          group_policy=isgroup)
1949 da5f09ef Bernardo Dal Seno
1950 da5f09ef Bernardo Dal Seno
    self.assertTrue(constants.ISPECS_MINMAX in new_policy)
1951 0f511c8a Bernardo Dal Seno
    self.assertEqual(new_policy[constants.ISPECS_MINMAX], diff_minmax)
1952 5dd7d15b Bernardo Dal Seno
    for key in old_policy:
1953 5dd7d15b Bernardo Dal Seno
      if not key in diff_policy:
1954 5dd7d15b Bernardo Dal Seno
        self.assertTrue(key in new_policy)
1955 5dd7d15b Bernardo Dal Seno
        self.assertEqual(new_policy[key], old_policy[key])
1956 da5f09ef Bernardo Dal Seno
1957 da5f09ef Bernardo Dal Seno
    if not isgroup:
1958 da5f09ef Bernardo Dal Seno
      new_std = new_policy[constants.ISPECS_STD]
1959 da5f09ef Bernardo Dal Seno
      for key in diff_std:
1960 da5f09ef Bernardo Dal Seno
        self.assertTrue(key in new_std)
1961 da5f09ef Bernardo Dal Seno
        self.assertEqual(new_std[key], diff_std[key])
1962 0f511c8a Bernardo Dal Seno
      old_std = old_policy.get(constants.ISPECS_STD, {})
1963 0f511c8a Bernardo Dal Seno
      for key in old_std:
1964 0f511c8a Bernardo Dal Seno
        self.assertTrue(key in new_std)
1965 0f511c8a Bernardo Dal Seno
        if key not in diff_std:
1966 0f511c8a Bernardo Dal Seno
          self.assertEqual(new_std[key], old_std[key])
1967 da5f09ef Bernardo Dal Seno
1968 0f511c8a Bernardo Dal Seno
  def _TestSet(self, old_policy, diff_policy, isgroup):
1969 5eacbcae Thomas Thrainer
    new_policy = common.GetUpdatedIPolicy(old_policy, diff_policy,
1970 5dd7d15b Bernardo Dal Seno
                                           group_policy=isgroup)
1971 5dd7d15b Bernardo Dal Seno
    for key in diff_policy:
1972 5dd7d15b Bernardo Dal Seno
      self.assertTrue(key in new_policy)
1973 5dd7d15b Bernardo Dal Seno
      self.assertEqual(new_policy[key], diff_policy[key])
1974 5dd7d15b Bernardo Dal Seno
    for key in old_policy:
1975 5dd7d15b Bernardo Dal Seno
      if not key in diff_policy:
1976 5dd7d15b Bernardo Dal Seno
        self.assertTrue(key in new_policy)
1977 5dd7d15b Bernardo Dal Seno
        self.assertEqual(new_policy[key], old_policy[key])
1978 5dd7d15b Bernardo Dal Seno
1979 5dd7d15b Bernardo Dal Seno
  def testSet(self):
1980 0f511c8a Bernardo Dal Seno
    diff_policy = {
1981 0f511c8a Bernardo Dal Seno
      constants.IPOLICY_VCPU_RATIO: 3,
1982 0f511c8a Bernardo Dal Seno
      constants.IPOLICY_DTS: [constants.DT_FILE],
1983 0f511c8a Bernardo Dal Seno
      }
1984 0f511c8a Bernardo Dal Seno
    self._TestSet(self._OLD_GROUP_POLICY, diff_policy, True)
1985 5dd7d15b Bernardo Dal Seno
    self._TestSetSpecs(self._OLD_GROUP_POLICY, True)
1986 0f511c8a Bernardo Dal Seno
    self._TestSet({}, diff_policy, True)
1987 0f511c8a Bernardo Dal Seno
    self._TestSetSpecs({}, True)
1988 0f511c8a Bernardo Dal Seno
    self._TestSet(self._OLD_CLUSTER_POLICY, diff_policy, False)
1989 5dd7d15b Bernardo Dal Seno
    self._TestSetSpecs(self._OLD_CLUSTER_POLICY, False)
1990 5dd7d15b Bernardo Dal Seno
1991 5dd7d15b Bernardo Dal Seno
  def testUnset(self):
1992 5dd7d15b Bernardo Dal Seno
    old_policy = self._OLD_GROUP_POLICY
1993 5dd7d15b Bernardo Dal Seno
    diff_policy = {
1994 5dd7d15b Bernardo Dal Seno
      constants.IPOLICY_SPINDLE_RATIO: constants.VALUE_DEFAULT,
1995 5dd7d15b Bernardo Dal Seno
      }
1996 5eacbcae Thomas Thrainer
    new_policy = common.GetUpdatedIPolicy(old_policy, diff_policy,
1997 5eacbcae Thomas Thrainer
                                          group_policy=True)
1998 5dd7d15b Bernardo Dal Seno
    for key in diff_policy:
1999 5dd7d15b Bernardo Dal Seno
      self.assertFalse(key in new_policy)
2000 5dd7d15b Bernardo Dal Seno
    for key in old_policy:
2001 5dd7d15b Bernardo Dal Seno
      if not key in diff_policy:
2002 5dd7d15b Bernardo Dal Seno
        self.assertTrue(key in new_policy)
2003 5dd7d15b Bernardo Dal Seno
        self.assertEqual(new_policy[key], old_policy[key])
2004 5dd7d15b Bernardo Dal Seno
2005 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, common.GetUpdatedIPolicy,
2006 0f511c8a Bernardo Dal Seno
                      old_policy, diff_policy, group_policy=False)
2007 0f511c8a Bernardo Dal Seno
2008 41044e04 Bernardo Dal Seno
  def testUnsetEmpty(self):
2009 41044e04 Bernardo Dal Seno
    old_policy = {}
2010 41044e04 Bernardo Dal Seno
    for key in constants.IPOLICY_ALL_KEYS:
2011 41044e04 Bernardo Dal Seno
      diff_policy = {
2012 41044e04 Bernardo Dal Seno
        key: constants.VALUE_DEFAULT,
2013 41044e04 Bernardo Dal Seno
        }
2014 5eacbcae Thomas Thrainer
    new_policy = common.GetUpdatedIPolicy(old_policy, diff_policy,
2015 5eacbcae Thomas Thrainer
                                          group_policy=True)
2016 41044e04 Bernardo Dal Seno
    self.assertEqual(new_policy, old_policy)
2017 41044e04 Bernardo Dal Seno
2018 5dd7d15b Bernardo Dal Seno
  def _TestInvalidKeys(self, old_policy, isgroup):
2019 0f511c8a Bernardo Dal Seno
    INVALID_KEY = "this_key_shouldnt_be_allowed"
2020 5dd7d15b Bernardo Dal Seno
    INVALID_DICT = {
2021 0f511c8a Bernardo Dal Seno
      INVALID_KEY: 3,
2022 5dd7d15b Bernardo Dal Seno
      }
2023 5dd7d15b Bernardo Dal Seno
    invalid_policy = INVALID_DICT
2024 5eacbcae Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, common.GetUpdatedIPolicy,
2025 5dd7d15b Bernardo Dal Seno
                      old_policy, invalid_policy, group_policy=isgroup)
2026 da5f09ef Bernardo Dal Seno
    invalid_ispecs = {
2027 41044e04 Bernardo Dal Seno
      constants.ISPECS_MINMAX: [INVALID_DICT],
2028 da5f09ef Bernardo Dal Seno
      }
2029 5eacbcae Thomas Thrainer
    self.assertRaises(errors.TypeEnforcementError, common.GetUpdatedIPolicy,
2030 da5f09ef Bernardo Dal Seno
                      old_policy, invalid_ispecs, group_policy=isgroup)
2031 0f511c8a Bernardo Dal Seno
    if isgroup:
2032 0f511c8a Bernardo Dal Seno
      invalid_for_group = {
2033 0f511c8a Bernardo Dal Seno
        constants.ISPECS_STD: constants.IPOLICY_DEFAULTS[constants.ISPECS_STD],
2034 5dd7d15b Bernardo Dal Seno
        }
2035 5eacbcae Thomas Thrainer
      self.assertRaises(errors.OpPrereqError, common.GetUpdatedIPolicy,
2036 0f511c8a Bernardo Dal Seno
                        old_policy, invalid_for_group, group_policy=isgroup)
2037 0f511c8a Bernardo Dal Seno
    good_ispecs = self._OLD_CLUSTER_POLICY[constants.ISPECS_MINMAX]
2038 0f511c8a Bernardo Dal Seno
    invalid_ispecs = copy.deepcopy(good_ispecs)
2039 0f511c8a Bernardo Dal Seno
    invalid_policy = {
2040 0f511c8a Bernardo Dal Seno
      constants.ISPECS_MINMAX: invalid_ispecs,
2041 0f511c8a Bernardo Dal Seno
      }
2042 41044e04 Bernardo Dal Seno
    for minmax in invalid_ispecs:
2043 41044e04 Bernardo Dal Seno
      for key in constants.ISPECS_MINMAX_KEYS:
2044 41044e04 Bernardo Dal Seno
        ispec = minmax[key]
2045 41044e04 Bernardo Dal Seno
        ispec[INVALID_KEY] = None
2046 0f511c8a Bernardo Dal Seno
        self.assertRaises(errors.TypeEnforcementError,
2047 5eacbcae Thomas Thrainer
                          common.GetUpdatedIPolicy, old_policy,
2048 41044e04 Bernardo Dal Seno
                          invalid_policy, group_policy=isgroup)
2049 41044e04 Bernardo Dal Seno
        del ispec[INVALID_KEY]
2050 41044e04 Bernardo Dal Seno
        for par in constants.ISPECS_PARAMETERS:
2051 41044e04 Bernardo Dal Seno
          oldv = ispec[par]
2052 41044e04 Bernardo Dal Seno
          ispec[par] = "this_is_not_good"
2053 41044e04 Bernardo Dal Seno
          self.assertRaises(errors.TypeEnforcementError,
2054 5eacbcae Thomas Thrainer
                            common.GetUpdatedIPolicy,
2055 41044e04 Bernardo Dal Seno
                            old_policy, invalid_policy, group_policy=isgroup)
2056 41044e04 Bernardo Dal Seno
          ispec[par] = oldv
2057 0f511c8a Bernardo Dal Seno
    # This is to make sure that no two errors were present during the tests
2058 5eacbcae Thomas Thrainer
    common.GetUpdatedIPolicy(old_policy, invalid_policy,
2059 5eacbcae Thomas Thrainer
                             group_policy=isgroup)
2060 5dd7d15b Bernardo Dal Seno
2061 5dd7d15b Bernardo Dal Seno
  def testInvalidKeys(self):
2062 5dd7d15b Bernardo Dal Seno
    self._TestInvalidKeys(self._OLD_GROUP_POLICY, True)
2063 5dd7d15b Bernardo Dal Seno
    self._TestInvalidKeys(self._OLD_CLUSTER_POLICY, False)
2064 5dd7d15b Bernardo Dal Seno
2065 0f511c8a Bernardo Dal Seno
  def testInvalidValues(self):
2066 0f511c8a Bernardo Dal Seno
    for par in (constants.IPOLICY_PARAMETERS |
2067 0f511c8a Bernardo Dal Seno
                frozenset([constants.IPOLICY_DTS])):
2068 0f511c8a Bernardo Dal Seno
      bad_policy = {
2069 0f511c8a Bernardo Dal Seno
        par: "invalid_value",
2070 0f511c8a Bernardo Dal Seno
        }
2071 5eacbcae Thomas Thrainer
      self.assertRaises(errors.OpPrereqError, common.GetUpdatedIPolicy, {},
2072 0f511c8a Bernardo Dal Seno
                        bad_policy, group_policy=True)
2073 5dd7d15b Bernardo Dal Seno
2074 b98bf262 Michael Hanselmann
if __name__ == "__main__":
2075 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()