Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.cmdlib_unittest.py @ 688b5752

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