Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.cmdlib_unittest.py @ 1a2eb2dc

History | View | Annotate | Download (51.1 kB)

1 6de7c41d Iustin Pop
#!/usr/bin/python
2 6de7c41d Iustin Pop
#
3 6de7c41d Iustin Pop
4 0c2e59ac Iustin Pop
# Copyright (C) 2008, 2011, 2012 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 6de7c41d Iustin Pop
import time
28 b98bf262 Michael Hanselmann
import tempfile
29 b98bf262 Michael Hanselmann
import shutil
30 64c7b383 Michael Hanselmann
import operator
31 d755483c Michael Hanselmann
import itertools
32 99ccf8b9 René Nussbaumer
import copy
33 6de7c41d Iustin Pop
34 83f72637 Michael Hanselmann
from ganeti import constants
35 b8812691 Iustin Pop
from ganeti import mcpu
36 6de7c41d Iustin Pop
from ganeti import cmdlib
37 b8812691 Iustin Pop
from ganeti import opcodes
38 6de7c41d Iustin Pop
from ganeti import errors
39 b8812691 Iustin Pop
from ganeti import utils
40 e58f87a9 Michael Hanselmann
from ganeti import luxi
41 65e183af Michael Hanselmann
from ganeti import ht
42 8ec505dd Adeodato Simo
from ganeti import objects
43 170b02b7 Michael Hanselmann
from ganeti import compat
44 170b02b7 Michael Hanselmann
from ganeti import rpc
45 ef86bf28 Michael Hanselmann
from ganeti import locking
46 a56625a2 Michael Hanselmann
from ganeti import pathutils
47 0fcd0cad René Nussbaumer
from ganeti.masterd import iallocator
48 0ad1ea40 Guido Trotter
from ganeti.hypervisor import hv_xen
49 6de7c41d Iustin Pop
50 25231ec5 Michael Hanselmann
import testutils
51 bd5f214b Apollon Oikonomopoulos
import mocks
52 25231ec5 Michael Hanselmann
53 6de7c41d Iustin Pop
54 b98bf262 Michael Hanselmann
class TestCertVerification(testutils.GanetiTestCase):
55 b98bf262 Michael Hanselmann
  def setUp(self):
56 b98bf262 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
57 b98bf262 Michael Hanselmann
58 b98bf262 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
59 b98bf262 Michael Hanselmann
60 b98bf262 Michael Hanselmann
  def tearDown(self):
61 b98bf262 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
62 b98bf262 Michael Hanselmann
63 b98bf262 Michael Hanselmann
  def testVerifyCertificate(self):
64 b98bf262 Michael Hanselmann
    cmdlib._VerifyCertificate(self._TestDataFilename("cert1.pem"))
65 b98bf262 Michael Hanselmann
66 b98bf262 Michael Hanselmann
    nonexist_filename = os.path.join(self.tmpdir, "does-not-exist")
67 b98bf262 Michael Hanselmann
68 b98bf262 Michael Hanselmann
    (errcode, msg) = cmdlib._VerifyCertificate(nonexist_filename)
69 bf93ae69 Adeodato Simo
    self.assertEqual(errcode, cmdlib.LUClusterVerifyConfig.ETYPE_ERROR)
70 b98bf262 Michael Hanselmann
71 b98bf262 Michael Hanselmann
    # Try to load non-certificate file
72 24d70417 Michael Hanselmann
    invalid_cert = self._TestDataFilename("bdev-net.txt")
73 b98bf262 Michael Hanselmann
    (errcode, msg) = cmdlib._VerifyCertificate(invalid_cert)
74 bf93ae69 Adeodato Simo
    self.assertEqual(errcode, cmdlib.LUClusterVerifyConfig.ETYPE_ERROR)
75 b98bf262 Michael Hanselmann
76 b98bf262 Michael Hanselmann
77 b8812691 Iustin Pop
class TestOpcodeParams(testutils.GanetiTestCase):
78 b8812691 Iustin Pop
  def testParamsStructures(self):
79 b8812691 Iustin Pop
    for op in sorted(mcpu.Processor.DISPATCH_TABLE):
80 b8812691 Iustin Pop
      lu = mcpu.Processor.DISPATCH_TABLE[op]
81 b8812691 Iustin Pop
      lu_name = lu.__name__
82 0bff0b12 Michael Hanselmann
      self.failIf(hasattr(lu, "_OP_REQP"),
83 0bff0b12 Michael Hanselmann
                  msg=("LU '%s' has old-style _OP_REQP" % lu_name))
84 0bff0b12 Michael Hanselmann
      self.failIf(hasattr(lu, "_OP_DEFS"),
85 0bff0b12 Michael Hanselmann
                  msg=("LU '%s' has old-style _OP_DEFS" % lu_name))
86 0bff0b12 Michael Hanselmann
      self.failIf(hasattr(lu, "_OP_PARAMS"),
87 0bff0b12 Michael Hanselmann
                  msg=("LU '%s' has old-style _OP_PARAMS" % lu_name))
88 b8812691 Iustin Pop
89 b8812691 Iustin Pop
90 bd5f214b Apollon Oikonomopoulos
class TestIAllocatorChecks(testutils.GanetiTestCase):
91 bd5f214b Apollon Oikonomopoulos
  def testFunction(self):
92 bd5f214b Apollon Oikonomopoulos
    class TestLU(object):
93 bd5f214b Apollon Oikonomopoulos
      def __init__(self, opcode):
94 bd5f214b Apollon Oikonomopoulos
        self.cfg = mocks.FakeConfig()
95 bd5f214b Apollon Oikonomopoulos
        self.op = opcode
96 bd5f214b Apollon Oikonomopoulos
97 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
98 ff0d18e6 Iustin Pop
       OP_PARAMS = [
99 197b323b Michael Hanselmann
        ("iallocator", None, ht.NoType, None),
100 197b323b Michael Hanselmann
        ("node", None, ht.NoType, None),
101 65e183af Michael Hanselmann
        ]
102 bd5f214b Apollon Oikonomopoulos
103 bd5f214b Apollon Oikonomopoulos
    default_iallocator = mocks.FakeConfig().GetDefaultIAllocator()
104 bd5f214b Apollon Oikonomopoulos
    other_iallocator = default_iallocator + "_not"
105 bd5f214b Apollon Oikonomopoulos
106 ff0d18e6 Iustin Pop
    op = OpTest()
107 bd5f214b Apollon Oikonomopoulos
    lu = TestLU(op)
108 bd5f214b Apollon Oikonomopoulos
109 bd5f214b Apollon Oikonomopoulos
    c_i = lambda: cmdlib._CheckIAllocatorOrNode(lu, "iallocator", "node")
110 bd5f214b Apollon Oikonomopoulos
111 bd5f214b Apollon Oikonomopoulos
    # Neither node nor iallocator given
112 43a8f36a Bernardo Dal Seno
    for n in (None, []):
113 43a8f36a Bernardo Dal Seno
      op.iallocator = None
114 43a8f36a Bernardo Dal Seno
      op.node = n
115 43a8f36a Bernardo Dal Seno
      c_i()
116 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.iallocator, default_iallocator)
117 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.node, n)
118 bd5f214b Apollon Oikonomopoulos
119 bd5f214b Apollon Oikonomopoulos
    # Both, iallocator and node given
120 43a8f36a Bernardo Dal Seno
    for a in ("test", constants.DEFAULT_IALLOCATOR_SHORTCUT):
121 43a8f36a Bernardo Dal Seno
      op.iallocator = a
122 43a8f36a Bernardo Dal Seno
      op.node = "test"
123 43a8f36a Bernardo Dal Seno
      self.assertRaises(errors.OpPrereqError, c_i)
124 bd5f214b Apollon Oikonomopoulos
125 bd5f214b Apollon Oikonomopoulos
    # Only iallocator given
126 43a8f36a Bernardo Dal Seno
    for n in (None, []):
127 43a8f36a Bernardo Dal Seno
      op.iallocator = other_iallocator
128 43a8f36a Bernardo Dal Seno
      op.node = n
129 43a8f36a Bernardo Dal Seno
      c_i()
130 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.iallocator, other_iallocator)
131 43a8f36a Bernardo Dal Seno
      self.assertEqual(lu.op.node, n)
132 bd5f214b Apollon Oikonomopoulos
133 bd5f214b Apollon Oikonomopoulos
    # Only node given
134 bd5f214b Apollon Oikonomopoulos
    op.iallocator = None
135 bd5f214b Apollon Oikonomopoulos
    op.node = "node"
136 bd5f214b Apollon Oikonomopoulos
    c_i()
137 bd5f214b Apollon Oikonomopoulos
    self.assertEqual(lu.op.iallocator, None)
138 bd5f214b Apollon Oikonomopoulos
    self.assertEqual(lu.op.node, "node")
139 bd5f214b Apollon Oikonomopoulos
140 43a8f36a Bernardo Dal Seno
    # Asked for default iallocator, no node given
141 43a8f36a Bernardo Dal Seno
    op.iallocator = constants.DEFAULT_IALLOCATOR_SHORTCUT
142 43a8f36a Bernardo Dal Seno
    op.node = None
143 43a8f36a Bernardo Dal Seno
    c_i()
144 43a8f36a Bernardo Dal Seno
    self.assertEqual(lu.op.iallocator, default_iallocator)
145 43a8f36a Bernardo Dal Seno
    self.assertEqual(lu.op.node, None)
146 43a8f36a Bernardo Dal Seno
147 bd5f214b Apollon Oikonomopoulos
    # No node, iallocator or default iallocator
148 bd5f214b Apollon Oikonomopoulos
    op.iallocator = None
149 bd5f214b Apollon Oikonomopoulos
    op.node = None
150 bd5f214b Apollon Oikonomopoulos
    lu.cfg.GetDefaultIAllocator = lambda: None
151 bd5f214b Apollon Oikonomopoulos
    self.assertRaises(errors.OpPrereqError, c_i)
152 bd5f214b Apollon Oikonomopoulos
153 bd5f214b Apollon Oikonomopoulos
154 b469eb4d Iustin Pop
class TestLUTestJqueue(unittest.TestCase):
155 e58f87a9 Michael Hanselmann
  def test(self):
156 b469eb4d Iustin Pop
    self.assert_(cmdlib.LUTestJqueue._CLIENT_CONNECT_TIMEOUT <
157 e58f87a9 Michael Hanselmann
                 (luxi.WFJC_TIMEOUT * 0.75),
158 e58f87a9 Michael Hanselmann
                 msg=("Client timeout too high, might not notice bugs"
159 e58f87a9 Michael Hanselmann
                      " in WaitForJobChange"))
160 e58f87a9 Michael Hanselmann
161 e58f87a9 Michael Hanselmann
162 83f72637 Michael Hanselmann
class TestLUQuery(unittest.TestCase):
163 83f72637 Michael Hanselmann
  def test(self):
164 83f72637 Michael Hanselmann
    self.assertEqual(sorted(cmdlib._QUERY_IMPL.keys()),
165 abd66bf8 Michael Hanselmann
                     sorted(constants.QR_VIA_OP))
166 83f72637 Michael Hanselmann
167 abd66bf8 Michael Hanselmann
    assert constants.QR_NODE in constants.QR_VIA_OP
168 abd66bf8 Michael Hanselmann
    assert constants.QR_INSTANCE in constants.QR_VIA_OP
169 83f72637 Michael Hanselmann
170 abd66bf8 Michael Hanselmann
    for i in constants.QR_VIA_OP:
171 83f72637 Michael Hanselmann
      self.assert_(cmdlib._GetQueryImplementation(i))
172 83f72637 Michael Hanselmann
173 83f72637 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, cmdlib._GetQueryImplementation, "")
174 83f72637 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, cmdlib._GetQueryImplementation,
175 83f72637 Michael Hanselmann
                      "xyz")
176 83f72637 Michael Hanselmann
177 83f72637 Michael Hanselmann
178 934704ae Iustin Pop
class TestLUGroupAssignNodes(unittest.TestCase):
179 8ec505dd Adeodato Simo
180 8ec505dd Adeodato Simo
  def testCheckAssignmentForSplitInstances(self):
181 8ec505dd Adeodato Simo
    node_data = dict((name, objects.Node(name=name, group=group))
182 8ec505dd Adeodato Simo
                     for (name, group) in [("n1a", "g1"), ("n1b", "g1"),
183 8ec505dd Adeodato Simo
                                           ("n2a", "g2"), ("n2b", "g2"),
184 8ec505dd Adeodato Simo
                                           ("n3a", "g3"), ("n3b", "g3"),
185 8ec505dd Adeodato Simo
                                           ("n3c", "g3"),
186 8ec505dd Adeodato Simo
                                           ])
187 8ec505dd Adeodato Simo
188 8ec505dd Adeodato Simo
    def Instance(name, pnode, snode):
189 8ec505dd Adeodato Simo
      if snode is None:
190 8ec505dd Adeodato Simo
        disks = []
191 8ec505dd Adeodato Simo
        disk_template = constants.DT_DISKLESS
192 8ec505dd Adeodato Simo
      else:
193 8ec505dd Adeodato Simo
        disks = [objects.Disk(dev_type=constants.LD_DRBD8,
194 8ec505dd Adeodato Simo
                              logical_id=[pnode, snode, 1, 17, 17])]
195 8ec505dd Adeodato Simo
        disk_template = constants.DT_DRBD8
196 8ec505dd Adeodato Simo
197 8ec505dd Adeodato Simo
      return objects.Instance(name=name, primary_node=pnode, disks=disks,
198 8ec505dd Adeodato Simo
                              disk_template=disk_template)
199 8ec505dd Adeodato Simo
200 8ec505dd Adeodato Simo
    instance_data = dict((name, Instance(name, pnode, snode))
201 8ec505dd Adeodato Simo
                         for name, pnode, snode in [("inst1a", "n1a", "n1b"),
202 8ec505dd Adeodato Simo
                                                    ("inst1b", "n1b", "n1a"),
203 8ec505dd Adeodato Simo
                                                    ("inst2a", "n2a", "n2b"),
204 8ec505dd Adeodato Simo
                                                    ("inst3a", "n3a", None),
205 8ec505dd Adeodato Simo
                                                    ("inst3b", "n3b", "n1b"),
206 8ec505dd Adeodato Simo
                                                    ("inst3c", "n3b", "n2b"),
207 8ec505dd Adeodato Simo
                                                    ])
208 8ec505dd Adeodato Simo
209 8ec505dd Adeodato Simo
    # Test first with the existing state.
210 8ec505dd Adeodato Simo
    (new, prev) = \
211 934704ae Iustin Pop
      cmdlib.LUGroupAssignNodes.CheckAssignmentForSplitInstances([],
212 8ec505dd Adeodato Simo
                                                                 node_data,
213 8ec505dd Adeodato Simo
                                                                 instance_data)
214 8ec505dd Adeodato Simo
215 8ec505dd Adeodato Simo
    self.assertEqual([], new)
216 8ec505dd Adeodato Simo
    self.assertEqual(set(["inst3b", "inst3c"]), set(prev))
217 8ec505dd Adeodato Simo
218 8ec505dd Adeodato Simo
    # And now some changes.
219 8ec505dd Adeodato Simo
    (new, prev) = \
220 934704ae Iustin Pop
      cmdlib.LUGroupAssignNodes.CheckAssignmentForSplitInstances([("n1b",
221 8ec505dd Adeodato Simo
                                                                   "g3")],
222 8ec505dd Adeodato Simo
                                                                 node_data,
223 8ec505dd Adeodato Simo
                                                                 instance_data)
224 8ec505dd Adeodato Simo
225 8ec505dd Adeodato Simo
    self.assertEqual(set(["inst1a", "inst1b"]), set(new))
226 8ec505dd Adeodato Simo
    self.assertEqual(set(["inst3c"]), set(prev))
227 8ec505dd Adeodato Simo
228 8ec505dd Adeodato Simo
229 64c7b383 Michael Hanselmann
class TestClusterVerifySsh(unittest.TestCase):
230 64c7b383 Michael Hanselmann
  def testMultipleGroups(self):
231 64c7b383 Michael Hanselmann
    fn = cmdlib.LUClusterVerifyGroup._SelectSshCheckNodes
232 64c7b383 Michael Hanselmann
    mygroupnodes = [
233 64c7b383 Michael Hanselmann
      objects.Node(name="node20", group="my", offline=False),
234 64c7b383 Michael Hanselmann
      objects.Node(name="node21", group="my", offline=False),
235 64c7b383 Michael Hanselmann
      objects.Node(name="node22", group="my", offline=False),
236 64c7b383 Michael Hanselmann
      objects.Node(name="node23", group="my", offline=False),
237 64c7b383 Michael Hanselmann
      objects.Node(name="node24", group="my", offline=False),
238 64c7b383 Michael Hanselmann
      objects.Node(name="node25", group="my", offline=False),
239 64c7b383 Michael Hanselmann
      objects.Node(name="node26", group="my", offline=True),
240 64c7b383 Michael Hanselmann
      ]
241 64c7b383 Michael Hanselmann
    nodes = [
242 64c7b383 Michael Hanselmann
      objects.Node(name="node1", group="g1", offline=True),
243 64c7b383 Michael Hanselmann
      objects.Node(name="node2", group="g1", offline=False),
244 64c7b383 Michael Hanselmann
      objects.Node(name="node3", group="g1", offline=False),
245 64c7b383 Michael Hanselmann
      objects.Node(name="node4", group="g1", offline=True),
246 64c7b383 Michael Hanselmann
      objects.Node(name="node5", group="g1", offline=False),
247 64c7b383 Michael Hanselmann
      objects.Node(name="node10", group="xyz", offline=False),
248 64c7b383 Michael Hanselmann
      objects.Node(name="node11", group="xyz", offline=False),
249 64c7b383 Michael Hanselmann
      objects.Node(name="node40", group="alloff", offline=True),
250 64c7b383 Michael Hanselmann
      objects.Node(name="node41", group="alloff", offline=True),
251 64c7b383 Michael Hanselmann
      objects.Node(name="node50", group="aaa", offline=False),
252 64c7b383 Michael Hanselmann
      ] + mygroupnodes
253 64c7b383 Michael Hanselmann
    assert not utils.FindDuplicates(map(operator.attrgetter("name"), nodes))
254 64c7b383 Michael Hanselmann
255 64c7b383 Michael Hanselmann
    (online, perhost) = fn(mygroupnodes, "my", nodes)
256 64c7b383 Michael Hanselmann
    self.assertEqual(online, ["node%s" % i for i in range(20, 26)])
257 64c7b383 Michael Hanselmann
    self.assertEqual(set(perhost.keys()), set(online))
258 64c7b383 Michael Hanselmann
259 64c7b383 Michael Hanselmann
    self.assertEqual(perhost, {
260 64c7b383 Michael Hanselmann
      "node20": ["node10", "node2", "node50"],
261 64c7b383 Michael Hanselmann
      "node21": ["node11", "node3", "node50"],
262 64c7b383 Michael Hanselmann
      "node22": ["node10", "node5", "node50"],
263 64c7b383 Michael Hanselmann
      "node23": ["node11", "node2", "node50"],
264 64c7b383 Michael Hanselmann
      "node24": ["node10", "node3", "node50"],
265 64c7b383 Michael Hanselmann
      "node25": ["node11", "node5", "node50"],
266 64c7b383 Michael Hanselmann
      })
267 64c7b383 Michael Hanselmann
268 64c7b383 Michael Hanselmann
  def testSingleGroup(self):
269 64c7b383 Michael Hanselmann
    fn = cmdlib.LUClusterVerifyGroup._SelectSshCheckNodes
270 64c7b383 Michael Hanselmann
    nodes = [
271 64c7b383 Michael Hanselmann
      objects.Node(name="node1", group="default", offline=True),
272 64c7b383 Michael Hanselmann
      objects.Node(name="node2", group="default", offline=False),
273 64c7b383 Michael Hanselmann
      objects.Node(name="node3", group="default", offline=False),
274 64c7b383 Michael Hanselmann
      objects.Node(name="node4", group="default", offline=True),
275 64c7b383 Michael Hanselmann
      ]
276 64c7b383 Michael Hanselmann
    assert not utils.FindDuplicates(map(operator.attrgetter("name"), nodes))
277 64c7b383 Michael Hanselmann
278 64c7b383 Michael Hanselmann
    (online, perhost) = fn(nodes, "default", nodes)
279 64c7b383 Michael Hanselmann
    self.assertEqual(online, ["node2", "node3"])
280 64c7b383 Michael Hanselmann
    self.assertEqual(set(perhost.keys()), set(online))
281 64c7b383 Michael Hanselmann
282 64c7b383 Michael Hanselmann
    self.assertEqual(perhost, {
283 64c7b383 Michael Hanselmann
      "node2": [],
284 64c7b383 Michael Hanselmann
      "node3": [],
285 64c7b383 Michael Hanselmann
      })
286 64c7b383 Michael Hanselmann
287 64c7b383 Michael Hanselmann
288 170b02b7 Michael Hanselmann
class TestClusterVerifyFiles(unittest.TestCase):
289 170b02b7 Michael Hanselmann
  @staticmethod
290 170b02b7 Michael Hanselmann
  def _FakeErrorIf(errors, cond, ecode, item, msg, *args, **kwargs):
291 eedf99b5 Andrea Spadaccini
    assert ((ecode == constants.CV_ENODEFILECHECK and
292 170b02b7 Michael Hanselmann
             ht.TNonEmptyString(item)) or
293 eedf99b5 Andrea Spadaccini
            (ecode == constants.CV_ECLUSTERFILECHECK and
294 170b02b7 Michael Hanselmann
             item is None))
295 170b02b7 Michael Hanselmann
296 170b02b7 Michael Hanselmann
    if args:
297 170b02b7 Michael Hanselmann
      msg = msg % args
298 170b02b7 Michael Hanselmann
299 170b02b7 Michael Hanselmann
    if cond:
300 170b02b7 Michael Hanselmann
      errors.append((item, msg))
301 170b02b7 Michael Hanselmann
302 170b02b7 Michael Hanselmann
  _VerifyFiles = cmdlib.LUClusterVerifyGroup._VerifyFiles
303 170b02b7 Michael Hanselmann
304 170b02b7 Michael Hanselmann
  def test(self):
305 170b02b7 Michael Hanselmann
    errors = []
306 170b02b7 Michael Hanselmann
    master_name = "master.example.com"
307 170b02b7 Michael Hanselmann
    nodeinfo = [
308 0ad1ea40 Guido Trotter
      objects.Node(name=master_name, offline=False, vm_capable=True),
309 0ad1ea40 Guido Trotter
      objects.Node(name="node2.example.com", offline=False, vm_capable=True),
310 0ad1ea40 Guido Trotter
      objects.Node(name="node3.example.com", master_candidate=True,
311 0ad1ea40 Guido Trotter
                   vm_capable=False),
312 0ad1ea40 Guido Trotter
      objects.Node(name="node4.example.com", offline=False, vm_capable=True),
313 0ad1ea40 Guido Trotter
      objects.Node(name="nodata.example.com", offline=False, vm_capable=True),
314 170b02b7 Michael Hanselmann
      objects.Node(name="offline.example.com", offline=True),
315 170b02b7 Michael Hanselmann
      ]
316 170b02b7 Michael Hanselmann
    cluster = objects.Cluster(modify_etc_hosts=True,
317 170b02b7 Michael Hanselmann
                              enabled_hypervisors=[constants.HT_XEN_HVM])
318 170b02b7 Michael Hanselmann
    files_all = set([
319 a56625a2 Michael Hanselmann
      pathutils.CLUSTER_DOMAIN_SECRET_FILE,
320 a56625a2 Michael Hanselmann
      pathutils.RAPI_CERT_FILE,
321 a56625a2 Michael Hanselmann
      pathutils.RAPI_USERS_FILE,
322 170b02b7 Michael Hanselmann
      ])
323 0ad1ea40 Guido Trotter
    files_opt = set([
324 a56625a2 Michael Hanselmann
      pathutils.RAPI_USERS_FILE,
325 0ad1ea40 Guido Trotter
      hv_xen.XL_CONFIG_FILE,
326 a56625a2 Michael Hanselmann
      pathutils.VNC_PASSWORD_FILE,
327 170b02b7 Michael Hanselmann
      ])
328 170b02b7 Michael Hanselmann
    files_mc = set([
329 a56625a2 Michael Hanselmann
      pathutils.CLUSTER_CONF_FILE,
330 170b02b7 Michael Hanselmann
      ])
331 0ad1ea40 Guido Trotter
    files_vm = set([
332 0ad1ea40 Guido Trotter
      hv_xen.XEND_CONFIG_FILE,
333 0ad1ea40 Guido Trotter
      hv_xen.XL_CONFIG_FILE,
334 a56625a2 Michael Hanselmann
      pathutils.VNC_PASSWORD_FILE,
335 0ad1ea40 Guido Trotter
      ])
336 170b02b7 Michael Hanselmann
    nvinfo = {
337 170b02b7 Michael Hanselmann
      master_name: rpc.RpcResult(data=(True, {
338 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
339 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_CONF_FILE: "82314f897f38b35f9dab2f7c6b1593e0",
340 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "babbce8f387bc082228e544a2146fee4",
341 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
342 0ad1ea40 Guido Trotter
          hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310",
343 0ad1ea40 Guido Trotter
          hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9"
344 170b02b7 Michael Hanselmann
        }})),
345 170b02b7 Michael Hanselmann
      "node2.example.com": rpc.RpcResult(data=(True, {
346 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
347 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
348 0ad1ea40 Guido Trotter
          hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310",
349 170b02b7 Michael Hanselmann
          }
350 170b02b7 Michael Hanselmann
        })),
351 170b02b7 Michael Hanselmann
      "node3.example.com": rpc.RpcResult(data=(True, {
352 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
353 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
354 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
355 170b02b7 Michael Hanselmann
          }
356 170b02b7 Michael Hanselmann
        })),
357 170b02b7 Michael Hanselmann
      "node4.example.com": rpc.RpcResult(data=(True, {
358 170b02b7 Michael Hanselmann
        constants.NV_FILELIST: {
359 a56625a2 Michael Hanselmann
          pathutils.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a",
360 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_CONF_FILE: "conf-a6d4b13e407867f7a7b4f0f232a8f527",
361 a56625a2 Michael Hanselmann
          pathutils.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4",
362 a56625a2 Michael Hanselmann
          pathutils.RAPI_USERS_FILE: "rapiusers-ea3271e8d810ef3",
363 0ad1ea40 Guido Trotter
          hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9"
364 170b02b7 Michael Hanselmann
          }
365 170b02b7 Michael Hanselmann
        })),
366 170b02b7 Michael Hanselmann
      "nodata.example.com": rpc.RpcResult(data=(True, {})),
367 170b02b7 Michael Hanselmann
      "offline.example.com": rpc.RpcResult(offline=True),
368 170b02b7 Michael Hanselmann
      }
369 170b02b7 Michael Hanselmann
    assert set(nvinfo.keys()) == set(map(operator.attrgetter("name"), nodeinfo))
370 170b02b7 Michael Hanselmann
371 170b02b7 Michael Hanselmann
    self._VerifyFiles(compat.partial(self._FakeErrorIf, errors), nodeinfo,
372 170b02b7 Michael Hanselmann
                      master_name, nvinfo,
373 0ad1ea40 Guido Trotter
                      (files_all, files_opt, files_mc, files_vm))
374 170b02b7 Michael Hanselmann
    self.assertEqual(sorted(errors), sorted([
375 170b02b7 Michael Hanselmann
      (None, ("File %s found with 2 different checksums (variant 1 on"
376 170b02b7 Michael Hanselmann
              " node2.example.com, node3.example.com, node4.example.com;"
377 a56625a2 Michael Hanselmann
              " variant 2 on master.example.com)" % pathutils.RAPI_CERT_FILE)),
378 170b02b7 Michael Hanselmann
      (None, ("File %s is missing from node(s) node2.example.com" %
379 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_DOMAIN_SECRET_FILE)),
380 170b02b7 Michael Hanselmann
      (None, ("File %s should not exist on node(s) node4.example.com" %
381 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_CONF_FILE)),
382 0ad1ea40 Guido Trotter
      (None, ("File %s is missing from node(s) node4.example.com" %
383 0ad1ea40 Guido Trotter
              hv_xen.XEND_CONFIG_FILE)),
384 170b02b7 Michael Hanselmann
      (None, ("File %s is missing from node(s) node3.example.com" %
385 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_CONF_FILE)),
386 170b02b7 Michael Hanselmann
      (None, ("File %s found with 2 different checksums (variant 1 on"
387 170b02b7 Michael Hanselmann
              " master.example.com; variant 2 on node4.example.com)" %
388 a56625a2 Michael Hanselmann
              pathutils.CLUSTER_CONF_FILE)),
389 170b02b7 Michael Hanselmann
      (None, ("File %s is optional, but it must exist on all or no nodes (not"
390 170b02b7 Michael Hanselmann
              " found on master.example.com, node2.example.com,"
391 a56625a2 Michael Hanselmann
              " node3.example.com)" % pathutils.RAPI_USERS_FILE)),
392 0ad1ea40 Guido Trotter
      (None, ("File %s is optional, but it must exist on all or no nodes (not"
393 0ad1ea40 Guido Trotter
              " found on node2.example.com)" % hv_xen.XL_CONFIG_FILE)),
394 170b02b7 Michael Hanselmann
      ("nodata.example.com", "Node did not return file checksum data"),
395 170b02b7 Michael Hanselmann
      ]))
396 170b02b7 Michael Hanselmann
397 170b02b7 Michael Hanselmann
398 d755483c Michael Hanselmann
class _FakeLU:
399 129cce69 Michael Hanselmann
  def __init__(self, cfg=NotImplemented, proc=NotImplemented,
400 129cce69 Michael Hanselmann
               rpc=NotImplemented):
401 d755483c Michael Hanselmann
    self.warning_log = []
402 d755483c Michael Hanselmann
    self.info_log = []
403 ff02b60f René Nussbaumer
    self.cfg = cfg
404 a8e3e009 Michael Hanselmann
    self.proc = proc
405 129cce69 Michael Hanselmann
    self.rpc = rpc
406 d755483c Michael Hanselmann
407 d755483c Michael Hanselmann
  def LogWarning(self, text, *args):
408 d755483c Michael Hanselmann
    self.warning_log.append((text, args))
409 d755483c Michael Hanselmann
410 d755483c Michael Hanselmann
  def LogInfo(self, text, *args):
411 d755483c Michael Hanselmann
    self.info_log.append((text, args))
412 d755483c Michael Hanselmann
413 d755483c Michael Hanselmann
414 d755483c Michael Hanselmann
class TestLoadNodeEvacResult(unittest.TestCase):
415 d755483c Michael Hanselmann
  def testSuccess(self):
416 d755483c Michael Hanselmann
    for moved in [[], [
417 d755483c Michael Hanselmann
      ("inst20153.example.com", "grp2", ["nodeA4509", "nodeB2912"]),
418 d755483c Michael Hanselmann
      ]]:
419 d755483c Michael Hanselmann
      for early_release in [False, True]:
420 d755483c Michael Hanselmann
        for use_nodes in [False, True]:
421 d755483c Michael Hanselmann
          jobs = [
422 d755483c Michael Hanselmann
            [opcodes.OpInstanceReplaceDisks().__getstate__()],
423 d755483c Michael Hanselmann
            [opcodes.OpInstanceMigrate().__getstate__()],
424 d755483c Michael Hanselmann
            ]
425 d755483c Michael Hanselmann
426 d755483c Michael Hanselmann
          alloc_result = (moved, [], jobs)
427 0fcd0cad René Nussbaumer
          assert iallocator._NEVAC_RESULT(alloc_result)
428 d755483c Michael Hanselmann
429 d755483c Michael Hanselmann
          lu = _FakeLU()
430 d755483c Michael Hanselmann
          result = cmdlib._LoadNodeEvacResult(lu, alloc_result,
431 d755483c Michael Hanselmann
                                              early_release, use_nodes)
432 d755483c Michael Hanselmann
433 d755483c Michael Hanselmann
          if moved:
434 d755483c Michael Hanselmann
            (_, (info_args, )) = lu.info_log.pop(0)
435 d755483c Michael Hanselmann
            for (instname, instgroup, instnodes) in moved:
436 d755483c Michael Hanselmann
              self.assertTrue(instname in info_args)
437 d755483c Michael Hanselmann
              if use_nodes:
438 d755483c Michael Hanselmann
                for i in instnodes:
439 d755483c Michael Hanselmann
                  self.assertTrue(i in info_args)
440 d755483c Michael Hanselmann
              else:
441 d755483c Michael Hanselmann
                self.assertTrue(instgroup in info_args)
442 d755483c Michael Hanselmann
443 d755483c Michael Hanselmann
          self.assertFalse(lu.info_log)
444 d755483c Michael Hanselmann
          self.assertFalse(lu.warning_log)
445 d755483c Michael Hanselmann
446 d755483c Michael Hanselmann
          for op in itertools.chain(*result):
447 d755483c Michael Hanselmann
            if hasattr(op.__class__, "early_release"):
448 d755483c Michael Hanselmann
              self.assertEqual(op.early_release, early_release)
449 d755483c Michael Hanselmann
            else:
450 d755483c Michael Hanselmann
              self.assertFalse(hasattr(op, "early_release"))
451 d755483c Michael Hanselmann
452 d755483c Michael Hanselmann
  def testFailed(self):
453 d755483c Michael Hanselmann
    alloc_result = ([], [
454 d755483c Michael Hanselmann
      ("inst5191.example.com", "errormsg21178"),
455 d755483c Michael Hanselmann
      ], [])
456 0fcd0cad René Nussbaumer
    assert iallocator._NEVAC_RESULT(alloc_result)
457 d755483c Michael Hanselmann
458 d755483c Michael Hanselmann
    lu = _FakeLU()
459 d755483c Michael Hanselmann
    self.assertRaises(errors.OpExecError, cmdlib._LoadNodeEvacResult,
460 d755483c Michael Hanselmann
                      lu, alloc_result, False, False)
461 d755483c Michael Hanselmann
    self.assertFalse(lu.info_log)
462 d755483c Michael Hanselmann
    (_, (args, )) = lu.warning_log.pop(0)
463 d755483c Michael Hanselmann
    self.assertTrue("inst5191.example.com" in args)
464 d755483c Michael Hanselmann
    self.assertTrue("errormsg21178" in args)
465 d755483c Michael Hanselmann
    self.assertFalse(lu.warning_log)
466 d755483c Michael Hanselmann
467 d755483c Michael Hanselmann
468 784cd737 René Nussbaumer
class TestUpdateAndVerifySubDict(unittest.TestCase):
469 784cd737 René Nussbaumer
  def setUp(self):
470 784cd737 René Nussbaumer
    self.type_check = {
471 784cd737 René Nussbaumer
        "a": constants.VTYPE_INT,
472 784cd737 René Nussbaumer
        "b": constants.VTYPE_STRING,
473 784cd737 René Nussbaumer
        "c": constants.VTYPE_BOOL,
474 784cd737 René Nussbaumer
        "d": constants.VTYPE_STRING,
475 784cd737 René Nussbaumer
        }
476 784cd737 René Nussbaumer
477 784cd737 René Nussbaumer
  def test(self):
478 784cd737 René Nussbaumer
    old_test = {
479 784cd737 René Nussbaumer
      "foo": {
480 784cd737 René Nussbaumer
        "d": "blubb",
481 784cd737 René Nussbaumer
        "a": 321,
482 784cd737 René Nussbaumer
        },
483 784cd737 René Nussbaumer
      "baz": {
484 784cd737 René Nussbaumer
        "a": 678,
485 784cd737 René Nussbaumer
        "b": "678",
486 784cd737 René Nussbaumer
        "c": True,
487 784cd737 René Nussbaumer
        },
488 784cd737 René Nussbaumer
      }
489 784cd737 René Nussbaumer
    test = {
490 784cd737 René Nussbaumer
      "foo": {
491 784cd737 René Nussbaumer
        "a": 123,
492 784cd737 René Nussbaumer
        "b": "123",
493 784cd737 René Nussbaumer
        "c": True,
494 784cd737 René Nussbaumer
        },
495 784cd737 René Nussbaumer
      "bar": {
496 784cd737 René Nussbaumer
        "a": 321,
497 784cd737 René Nussbaumer
        "b": "321",
498 784cd737 René Nussbaumer
        "c": False,
499 784cd737 René Nussbaumer
        },
500 784cd737 René Nussbaumer
      }
501 784cd737 René Nussbaumer
502 784cd737 René Nussbaumer
    mv = {
503 784cd737 René Nussbaumer
      "foo": {
504 784cd737 René Nussbaumer
        "a": 123,
505 784cd737 René Nussbaumer
        "b": "123",
506 784cd737 René Nussbaumer
        "c": True,
507 784cd737 René Nussbaumer
        "d": "blubb"
508 784cd737 René Nussbaumer
        },
509 784cd737 René Nussbaumer
      "bar": {
510 784cd737 René Nussbaumer
        "a": 321,
511 784cd737 René Nussbaumer
        "b": "321",
512 784cd737 René Nussbaumer
        "c": False,
513 784cd737 René Nussbaumer
        },
514 784cd737 René Nussbaumer
      "baz": {
515 784cd737 René Nussbaumer
        "a": 678,
516 784cd737 René Nussbaumer
        "b": "678",
517 784cd737 René Nussbaumer
        "c": True,
518 784cd737 René Nussbaumer
        },
519 784cd737 René Nussbaumer
      }
520 784cd737 René Nussbaumer
521 784cd737 René Nussbaumer
    verified = cmdlib._UpdateAndVerifySubDict(old_test, test, self.type_check)
522 784cd737 René Nussbaumer
    self.assertEqual(verified, mv)
523 784cd737 René Nussbaumer
524 784cd737 René Nussbaumer
  def testWrong(self):
525 784cd737 René Nussbaumer
    test = {
526 784cd737 René Nussbaumer
      "foo": {
527 784cd737 René Nussbaumer
        "a": "blubb",
528 784cd737 René Nussbaumer
        "b": "123",
529 784cd737 René Nussbaumer
        "c": True,
530 784cd737 René Nussbaumer
        },
531 784cd737 René Nussbaumer
      "bar": {
532 784cd737 René Nussbaumer
        "a": 321,
533 784cd737 René Nussbaumer
        "b": "321",
534 784cd737 René Nussbaumer
        "c": False,
535 784cd737 René Nussbaumer
        },
536 784cd737 René Nussbaumer
      }
537 784cd737 René Nussbaumer
538 784cd737 René Nussbaumer
    self.assertRaises(errors.TypeEnforcementError,
539 784cd737 René Nussbaumer
                      cmdlib._UpdateAndVerifySubDict, {}, test, self.type_check)
540 784cd737 René Nussbaumer
541 784cd737 René Nussbaumer
542 0ba177e2 René Nussbaumer
class TestHvStateHelper(unittest.TestCase):
543 0ba177e2 René Nussbaumer
  def testWithoutOpData(self):
544 0ba177e2 René Nussbaumer
    self.assertEqual(cmdlib._MergeAndVerifyHvState(None, NotImplemented), None)
545 0ba177e2 René Nussbaumer
546 0ba177e2 René Nussbaumer
  def testWithoutOldData(self):
547 0ba177e2 René Nussbaumer
    new = {
548 0ba177e2 René Nussbaumer
      constants.HT_XEN_PVM: {
549 0ba177e2 René Nussbaumer
        constants.HVST_MEMORY_TOTAL: 4096,
550 0ba177e2 René Nussbaumer
        },
551 0ba177e2 René Nussbaumer
      }
552 0ba177e2 René Nussbaumer
    self.assertEqual(cmdlib._MergeAndVerifyHvState(new, None), new)
553 0ba177e2 René Nussbaumer
554 0ba177e2 René Nussbaumer
  def testWithWrongHv(self):
555 0ba177e2 René Nussbaumer
    new = {
556 0ba177e2 René Nussbaumer
      "i-dont-exist": {
557 0ba177e2 René Nussbaumer
        constants.HVST_MEMORY_TOTAL: 4096,
558 0ba177e2 René Nussbaumer
        },
559 0ba177e2 René Nussbaumer
      }
560 0ba177e2 René Nussbaumer
    self.assertRaises(errors.OpPrereqError, cmdlib._MergeAndVerifyHvState, new,
561 0ba177e2 René Nussbaumer
                      None)
562 0ba177e2 René Nussbaumer
563 0ba177e2 René Nussbaumer
class TestDiskStateHelper(unittest.TestCase):
564 0ba177e2 René Nussbaumer
  def testWithoutOpData(self):
565 0ba177e2 René Nussbaumer
    self.assertEqual(cmdlib._MergeAndVerifyDiskState(None, NotImplemented),
566 0ba177e2 René Nussbaumer
                     None)
567 0ba177e2 René Nussbaumer
568 0ba177e2 René Nussbaumer
  def testWithoutOldData(self):
569 0ba177e2 René Nussbaumer
    new = {
570 0ba177e2 René Nussbaumer
      constants.LD_LV: {
571 0ba177e2 René Nussbaumer
        "xenvg": {
572 0ba177e2 René Nussbaumer
          constants.DS_DISK_RESERVED: 1024,
573 0ba177e2 René Nussbaumer
          },
574 0ba177e2 René Nussbaumer
        },
575 0ba177e2 René Nussbaumer
      }
576 0ba177e2 René Nussbaumer
    self.assertEqual(cmdlib._MergeAndVerifyDiskState(new, None), new)
577 0ba177e2 René Nussbaumer
578 0ba177e2 René Nussbaumer
  def testWithWrongStorageType(self):
579 0ba177e2 René Nussbaumer
    new = {
580 0ba177e2 René Nussbaumer
      "i-dont-exist": {
581 0ba177e2 René Nussbaumer
        "xenvg": {
582 0ba177e2 René Nussbaumer
          constants.DS_DISK_RESERVED: 1024,
583 0ba177e2 René Nussbaumer
          },
584 0ba177e2 René Nussbaumer
        },
585 0ba177e2 René Nussbaumer
      }
586 0ba177e2 René Nussbaumer
    self.assertRaises(errors.OpPrereqError, cmdlib._MergeAndVerifyDiskState,
587 0ba177e2 René Nussbaumer
                      new, None)
588 0ba177e2 René Nussbaumer
589 0ba177e2 René Nussbaumer
590 2096d068 René Nussbaumer
class TestComputeMinMaxSpec(unittest.TestCase):
591 2096d068 René Nussbaumer
  def setUp(self):
592 2096d068 René Nussbaumer
    self.ipolicy = {
593 2096d068 René Nussbaumer
      constants.ISPECS_MAX: {
594 2096d068 René Nussbaumer
        constants.ISPEC_MEM_SIZE: 512,
595 2096d068 René Nussbaumer
        constants.ISPEC_DISK_SIZE: 1024,
596 2096d068 René Nussbaumer
        },
597 2096d068 René Nussbaumer
      constants.ISPECS_MIN: {
598 2096d068 René Nussbaumer
        constants.ISPEC_MEM_SIZE: 128,
599 2096d068 René Nussbaumer
        constants.ISPEC_DISK_COUNT: 1,
600 2096d068 René Nussbaumer
        },
601 2096d068 René Nussbaumer
      }
602 2096d068 René Nussbaumer
603 2096d068 René Nussbaumer
  def testNoneValue(self):
604 0c2e59ac Iustin Pop
    self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_MEM_SIZE, None,
605 2096d068 René Nussbaumer
                                              self.ipolicy, None) is None)
606 2096d068 René Nussbaumer
607 2096d068 René Nussbaumer
  def testAutoValue(self):
608 0c2e59ac Iustin Pop
    self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_MEM_SIZE, None,
609 2096d068 René Nussbaumer
                                              self.ipolicy,
610 2096d068 René Nussbaumer
                                              constants.VALUE_AUTO) is None)
611 2096d068 René Nussbaumer
612 2096d068 René Nussbaumer
  def testNotDefined(self):
613 0c2e59ac Iustin Pop
    self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_NIC_COUNT, None,
614 2096d068 René Nussbaumer
                                              self.ipolicy, 3) is None)
615 2096d068 René Nussbaumer
616 2096d068 René Nussbaumer
  def testNoMinDefined(self):
617 0c2e59ac Iustin Pop
    self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_DISK_SIZE, None,
618 2096d068 René Nussbaumer
                                              self.ipolicy, 128) is None)
619 2096d068 René Nussbaumer
620 2096d068 René Nussbaumer
  def testNoMaxDefined(self):
621 0c2e59ac Iustin Pop
    self.assertTrue(cmdlib._ComputeMinMaxSpec(constants.ISPEC_DISK_COUNT, None,
622 2096d068 René Nussbaumer
                                                self.ipolicy, 16) is None)
623 2096d068 René Nussbaumer
624 2096d068 René Nussbaumer
  def testOutOfRange(self):
625 2096d068 René Nussbaumer
    for (name, val) in ((constants.ISPEC_MEM_SIZE, 64),
626 2096d068 René Nussbaumer
                        (constants.ISPEC_MEM_SIZE, 768),
627 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_SIZE, 4096),
628 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_COUNT, 0)):
629 2096d068 René Nussbaumer
      min_v = self.ipolicy[constants.ISPECS_MIN].get(name, val)
630 2096d068 René Nussbaumer
      max_v = self.ipolicy[constants.ISPECS_MAX].get(name, val)
631 0c2e59ac Iustin Pop
      self.assertEqual(cmdlib._ComputeMinMaxSpec(name, None,
632 0c2e59ac Iustin Pop
                                                 self.ipolicy, val),
633 2096d068 René Nussbaumer
                       "%s value %s is not in range [%s, %s]" %
634 2096d068 René Nussbaumer
                       (name, val,min_v, max_v))
635 0c2e59ac Iustin Pop
      self.assertEqual(cmdlib._ComputeMinMaxSpec(name, "1",
636 0c2e59ac Iustin Pop
                                                 self.ipolicy, val),
637 0c2e59ac Iustin Pop
                       "%s/1 value %s is not in range [%s, %s]" %
638 0c2e59ac Iustin Pop
                       (name, val,min_v, max_v))
639 2096d068 René Nussbaumer
640 2096d068 René Nussbaumer
  def test(self):
641 2096d068 René Nussbaumer
    for (name, val) in ((constants.ISPEC_MEM_SIZE, 256),
642 2096d068 René Nussbaumer
                        (constants.ISPEC_MEM_SIZE, 128),
643 2096d068 René Nussbaumer
                        (constants.ISPEC_MEM_SIZE, 512),
644 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_SIZE, 1024),
645 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_SIZE, 0),
646 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_COUNT, 1),
647 2096d068 René Nussbaumer
                        (constants.ISPEC_DISK_COUNT, 5)):
648 0c2e59ac Iustin Pop
      self.assertTrue(cmdlib._ComputeMinMaxSpec(name, None, self.ipolicy, val)
649 2096d068 René Nussbaumer
                      is None)
650 2096d068 René Nussbaumer
651 2096d068 René Nussbaumer
652 0e68bf27 René Nussbaumer
def _ValidateComputeMinMaxSpec(name, *_):
653 0fb81174 René Nussbaumer
  assert name in constants.ISPECS_PARAMETERS
654 0fb81174 René Nussbaumer
  return None
655 0fb81174 René Nussbaumer
656 0fb81174 René Nussbaumer
657 0fb81174 René Nussbaumer
class _SpecWrapper:
658 0fb81174 René Nussbaumer
  def __init__(self, spec):
659 0fb81174 René Nussbaumer
    self.spec = spec
660 0fb81174 René Nussbaumer
661 0e68bf27 René Nussbaumer
  def ComputeMinMaxSpec(self, *args):
662 0fb81174 René Nussbaumer
    return self.spec.pop(0)
663 0fb81174 René Nussbaumer
664 0fb81174 René Nussbaumer
665 0fb81174 René Nussbaumer
class TestComputeIPolicySpecViolation(unittest.TestCase):
666 0fb81174 René Nussbaumer
  def test(self):
667 0e68bf27 René Nussbaumer
    compute_fn = _ValidateComputeMinMaxSpec
668 0fb81174 René Nussbaumer
    ret = cmdlib._ComputeIPolicySpecViolation(NotImplemented, 1024, 1, 1, 1,
669 553cb5f7 René Nussbaumer
                                              [1024], 1, _compute_fn=compute_fn)
670 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
671 0fb81174 René Nussbaumer
672 0fb81174 René Nussbaumer
  def testInvalidArguments(self):
673 0fb81174 René Nussbaumer
    self.assertRaises(AssertionError, cmdlib._ComputeIPolicySpecViolation,
674 553cb5f7 René Nussbaumer
                      NotImplemented, 1024, 1, 1, 1, [], 1)
675 0fb81174 René Nussbaumer
676 0fb81174 René Nussbaumer
  def testInvalidSpec(self):
677 553cb5f7 René Nussbaumer
    spec = _SpecWrapper([None, False, "foo", None, "bar", None])
678 0e68bf27 René Nussbaumer
    compute_fn = spec.ComputeMinMaxSpec
679 0fb81174 René Nussbaumer
    ret = cmdlib._ComputeIPolicySpecViolation(NotImplemented, 1024, 1, 1, 1,
680 553cb5f7 René Nussbaumer
                                              [1024], 1, _compute_fn=compute_fn)
681 0fb81174 René Nussbaumer
    self.assertEqual(ret, ["foo", "bar"])
682 0fb81174 René Nussbaumer
    self.assertFalse(spec.spec)
683 0fb81174 René Nussbaumer
684 0fb81174 René Nussbaumer
685 0fb81174 René Nussbaumer
class _StubComputeIPolicySpecViolation:
686 553cb5f7 René Nussbaumer
  def __init__(self, mem_size, cpu_count, disk_count, nic_count, disk_sizes,
687 553cb5f7 René Nussbaumer
               spindle_use):
688 0fb81174 René Nussbaumer
    self.mem_size = mem_size
689 0fb81174 René Nussbaumer
    self.cpu_count = cpu_count
690 0fb81174 René Nussbaumer
    self.disk_count = disk_count
691 0fb81174 René Nussbaumer
    self.nic_count = nic_count
692 0fb81174 René Nussbaumer
    self.disk_sizes = disk_sizes
693 553cb5f7 René Nussbaumer
    self.spindle_use = spindle_use
694 0fb81174 René Nussbaumer
695 553cb5f7 René Nussbaumer
  def __call__(self, _, mem_size, cpu_count, disk_count, nic_count, disk_sizes,
696 553cb5f7 René Nussbaumer
               spindle_use):
697 0fb81174 René Nussbaumer
    assert self.mem_size == mem_size
698 0fb81174 René Nussbaumer
    assert self.cpu_count == cpu_count
699 0fb81174 René Nussbaumer
    assert self.disk_count == disk_count
700 0fb81174 René Nussbaumer
    assert self.nic_count == nic_count
701 0fb81174 René Nussbaumer
    assert self.disk_sizes == disk_sizes
702 553cb5f7 René Nussbaumer
    assert self.spindle_use == spindle_use
703 0fb81174 René Nussbaumer
704 0fb81174 René Nussbaumer
    return []
705 0fb81174 René Nussbaumer
706 0fb81174 René Nussbaumer
707 0fb81174 René Nussbaumer
class TestComputeIPolicyInstanceViolation(unittest.TestCase):
708 0fb81174 René Nussbaumer
  def test(self):
709 0fb81174 René Nussbaumer
    beparams = {
710 0fb81174 René Nussbaumer
      constants.BE_MAXMEM: 2048,
711 0fb81174 René Nussbaumer
      constants.BE_VCPUS: 2,
712 34700f5b René Nussbaumer
      constants.BE_SPINDLE_USE: 4,
713 0fb81174 René Nussbaumer
      }
714 0fb81174 René Nussbaumer
    disks = [objects.Disk(size=512)]
715 0fb81174 René Nussbaumer
    instance = objects.Instance(beparams=beparams, disks=disks, nics=[])
716 553cb5f7 René Nussbaumer
    stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 4)
717 0fb81174 René Nussbaumer
    ret = cmdlib._ComputeIPolicyInstanceViolation(NotImplemented, instance,
718 0fb81174 René Nussbaumer
                                                  _compute_fn=stub)
719 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
720 0fb81174 René Nussbaumer
721 0fb81174 René Nussbaumer
722 0fb81174 René Nussbaumer
class TestComputeIPolicyInstanceSpecViolation(unittest.TestCase):
723 0fb81174 René Nussbaumer
  def test(self):
724 0fb81174 René Nussbaumer
    ispec = {
725 0fb81174 René Nussbaumer
      constants.ISPEC_MEM_SIZE: 2048,
726 0fb81174 René Nussbaumer
      constants.ISPEC_CPU_COUNT: 2,
727 0fb81174 René Nussbaumer
      constants.ISPEC_DISK_COUNT: 1,
728 0fb81174 René Nussbaumer
      constants.ISPEC_DISK_SIZE: [512],
729 0fb81174 René Nussbaumer
      constants.ISPEC_NIC_COUNT: 0,
730 553cb5f7 René Nussbaumer
      constants.ISPEC_SPINDLE_USE: 1,
731 0fb81174 René Nussbaumer
      }
732 553cb5f7 René Nussbaumer
    stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 1)
733 0fb81174 René Nussbaumer
    ret = cmdlib._ComputeIPolicyInstanceSpecViolation(NotImplemented, ispec,
734 0fb81174 René Nussbaumer
                                                      _compute_fn=stub)
735 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
736 0fb81174 René Nussbaumer
737 0fb81174 René Nussbaumer
738 0fb81174 René Nussbaumer
class _CallRecorder:
739 0fb81174 René Nussbaumer
  def __init__(self, return_value=None):
740 0fb81174 René Nussbaumer
    self.called = False
741 0fb81174 René Nussbaumer
    self.return_value = return_value
742 0fb81174 René Nussbaumer
743 0fb81174 René Nussbaumer
  def __call__(self, *args):
744 0fb81174 René Nussbaumer
    self.called = True
745 0fb81174 René Nussbaumer
    return self.return_value
746 0fb81174 René Nussbaumer
747 0fb81174 René Nussbaumer
748 0fb81174 René Nussbaumer
class TestComputeIPolicyNodeViolation(unittest.TestCase):
749 0fb81174 René Nussbaumer
  def setUp(self):
750 0fb81174 René Nussbaumer
    self.recorder = _CallRecorder(return_value=[])
751 0fb81174 René Nussbaumer
752 0fb81174 René Nussbaumer
  def testSameGroup(self):
753 0fb81174 René Nussbaumer
    ret = cmdlib._ComputeIPolicyNodeViolation(NotImplemented, NotImplemented,
754 0fb81174 René Nussbaumer
                                              "foo", "foo",
755 0fb81174 René Nussbaumer
                                              _compute_fn=self.recorder)
756 0fb81174 René Nussbaumer
    self.assertFalse(self.recorder.called)
757 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
758 0fb81174 René Nussbaumer
759 0fb81174 René Nussbaumer
  def testDifferentGroup(self):
760 0fb81174 René Nussbaumer
    ret = cmdlib._ComputeIPolicyNodeViolation(NotImplemented, NotImplemented,
761 0fb81174 René Nussbaumer
                                              "foo", "bar",
762 0fb81174 René Nussbaumer
                                              _compute_fn=self.recorder)
763 0fb81174 René Nussbaumer
    self.assertTrue(self.recorder.called)
764 0fb81174 René Nussbaumer
    self.assertEqual(ret, [])
765 0fb81174 René Nussbaumer
766 0fb81174 René Nussbaumer
767 ff02b60f René Nussbaumer
class _FakeConfigForTargetNodeIPolicy:
768 ff02b60f René Nussbaumer
  def __init__(self, node_info=NotImplemented):
769 ff02b60f René Nussbaumer
    self._node_info = node_info
770 ff02b60f René Nussbaumer
771 ff02b60f René Nussbaumer
  def GetNodeInfo(self, _):
772 ff02b60f René Nussbaumer
    return self._node_info
773 ff02b60f René Nussbaumer
774 ff02b60f René Nussbaumer
775 0fb81174 René Nussbaumer
class TestCheckTargetNodeIPolicy(unittest.TestCase):
776 0fb81174 René Nussbaumer
  def setUp(self):
777 ff02b60f René Nussbaumer
    self.instance = objects.Instance(primary_node="blubb")
778 0fb81174 René Nussbaumer
    self.target_node = objects.Node(group="bar")
779 ff02b60f René Nussbaumer
    node_info = objects.Node(group="foo")
780 ff02b60f René Nussbaumer
    fake_cfg = _FakeConfigForTargetNodeIPolicy(node_info=node_info)
781 ff02b60f René Nussbaumer
    self.lu = _FakeLU(cfg=fake_cfg)
782 0fb81174 René Nussbaumer
783 0fb81174 René Nussbaumer
  def testNoViolation(self):
784 0fb81174 René Nussbaumer
    compute_recoder = _CallRecorder(return_value=[])
785 0fb81174 René Nussbaumer
    cmdlib._CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
786 0fb81174 René Nussbaumer
                                   self.target_node,
787 0fb81174 René Nussbaumer
                                   _compute_fn=compute_recoder)
788 0fb81174 René Nussbaumer
    self.assertTrue(compute_recoder.called)
789 0fb81174 René Nussbaumer
    self.assertEqual(self.lu.warning_log, [])
790 0fb81174 René Nussbaumer
791 0fb81174 René Nussbaumer
  def testNoIgnore(self):
792 0fb81174 René Nussbaumer
    compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
793 0fb81174 René Nussbaumer
    self.assertRaises(errors.OpPrereqError, cmdlib._CheckTargetNodeIPolicy,
794 0fb81174 René Nussbaumer
                      self.lu, NotImplemented, self.instance, self.target_node,
795 0fb81174 René Nussbaumer
                      _compute_fn=compute_recoder)
796 0fb81174 René Nussbaumer
    self.assertTrue(compute_recoder.called)
797 0fb81174 René Nussbaumer
    self.assertEqual(self.lu.warning_log, [])
798 0fb81174 René Nussbaumer
799 0fb81174 René Nussbaumer
  def testIgnoreViolation(self):
800 0fb81174 René Nussbaumer
    compute_recoder = _CallRecorder(return_value=["mem_size not in range"])
801 0fb81174 René Nussbaumer
    cmdlib._CheckTargetNodeIPolicy(self.lu, NotImplemented, self.instance,
802 0fb81174 René Nussbaumer
                                   self.target_node, ignore=True,
803 0fb81174 René Nussbaumer
                                   _compute_fn=compute_recoder)
804 0fb81174 René Nussbaumer
    self.assertTrue(compute_recoder.called)
805 0fb81174 René Nussbaumer
    msg = ("Instance does not meet target node group's (bar) instance policy:"
806 0fb81174 René Nussbaumer
           " mem_size not in range")
807 0fb81174 René Nussbaumer
    self.assertEqual(self.lu.warning_log, [(msg, ())])
808 0fb81174 René Nussbaumer
809 0fb81174 René Nussbaumer
810 8301885b Michael Hanselmann
class TestApplyContainerMods(unittest.TestCase):
811 8301885b Michael Hanselmann
  def testEmptyContainer(self):
812 8301885b Michael Hanselmann
    container = []
813 8301885b Michael Hanselmann
    chgdesc = []
814 8301885b Michael Hanselmann
    cmdlib.ApplyContainerMods("test", container, chgdesc, [], None, None, None)
815 8301885b Michael Hanselmann
    self.assertEqual(container, [])
816 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [])
817 8301885b Michael Hanselmann
818 8301885b Michael Hanselmann
  def testAdd(self):
819 8301885b Michael Hanselmann
    container = []
820 8301885b Michael Hanselmann
    chgdesc = []
821 8301885b Michael Hanselmann
    mods = cmdlib.PrepareContainerMods([
822 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "Hello"),
823 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "World"),
824 8301885b Michael Hanselmann
      (constants.DDM_ADD, 0, "Start"),
825 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "End"),
826 8301885b Michael Hanselmann
      ], None)
827 8301885b Michael Hanselmann
    cmdlib.ApplyContainerMods("test", container, chgdesc, mods,
828 8301885b Michael Hanselmann
                              None, None, None)
829 8301885b Michael Hanselmann
    self.assertEqual(container, ["Start", "Hello", "World", "End"])
830 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [])
831 8301885b Michael Hanselmann
832 35554b4f Michael Hanselmann
    mods = cmdlib.PrepareContainerMods([
833 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 0, "zero"),
834 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 3, "Added"),
835 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 5, "four"),
836 35554b4f Michael Hanselmann
      (constants.DDM_ADD, 7, "xyz"),
837 35554b4f Michael Hanselmann
      ], None)
838 35554b4f Michael Hanselmann
    cmdlib.ApplyContainerMods("test", container, chgdesc, mods,
839 35554b4f Michael Hanselmann
                              None, None, None)
840 35554b4f Michael Hanselmann
    self.assertEqual(container,
841 35554b4f Michael Hanselmann
                     ["zero", "Start", "Hello", "Added", "World", "four",
842 35554b4f Michael Hanselmann
                      "End", "xyz"])
843 35554b4f Michael Hanselmann
    self.assertEqual(chgdesc, [])
844 35554b4f Michael Hanselmann
845 35554b4f Michael Hanselmann
    for idx in [-2, len(container) + 1]:
846 35554b4f Michael Hanselmann
      mods = cmdlib.PrepareContainerMods([
847 35554b4f Michael Hanselmann
        (constants.DDM_ADD, idx, "error"),
848 35554b4f Michael Hanselmann
        ], None)
849 35554b4f Michael Hanselmann
      self.assertRaises(IndexError, cmdlib.ApplyContainerMods,
850 35554b4f Michael Hanselmann
                        "test", container, None, mods, None, None, None)
851 35554b4f Michael Hanselmann
852 8301885b Michael Hanselmann
  def testRemoveError(self):
853 8301885b Michael Hanselmann
    for idx in [0, 1, 2, 100, -1, -4]:
854 8301885b Michael Hanselmann
      mods = cmdlib.PrepareContainerMods([
855 8301885b Michael Hanselmann
        (constants.DDM_REMOVE, idx, None),
856 8301885b Michael Hanselmann
        ], None)
857 8301885b Michael Hanselmann
      self.assertRaises(IndexError, cmdlib.ApplyContainerMods,
858 8301885b Michael Hanselmann
                        "test", [], None, mods, None, None, None)
859 8301885b Michael Hanselmann
860 8301885b Michael Hanselmann
    mods = cmdlib.PrepareContainerMods([
861 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, 0, object()),
862 8301885b Michael Hanselmann
      ], None)
863 8301885b Michael Hanselmann
    self.assertRaises(AssertionError, cmdlib.ApplyContainerMods,
864 8301885b Michael Hanselmann
                      "test", [""], None, mods, None, None, None)
865 8301885b Michael Hanselmann
866 8301885b Michael Hanselmann
  def testAddError(self):
867 35554b4f Michael Hanselmann
    for idx in range(-100, -1) + [100]:
868 8301885b Michael Hanselmann
      mods = cmdlib.PrepareContainerMods([
869 8301885b Michael Hanselmann
        (constants.DDM_ADD, idx, None),
870 8301885b Michael Hanselmann
        ], None)
871 8301885b Michael Hanselmann
      self.assertRaises(IndexError, cmdlib.ApplyContainerMods,
872 8301885b Michael Hanselmann
                        "test", [], None, mods, None, None, None)
873 8301885b Michael Hanselmann
874 8301885b Michael Hanselmann
  def testRemove(self):
875 8301885b Michael Hanselmann
    container = ["item 1", "item 2"]
876 8301885b Michael Hanselmann
    mods = cmdlib.PrepareContainerMods([
877 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "aaa"),
878 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, -1, None),
879 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "bbb"),
880 8301885b Michael Hanselmann
      ], None)
881 8301885b Michael Hanselmann
    chgdesc = []
882 8301885b Michael Hanselmann
    cmdlib.ApplyContainerMods("test", container, chgdesc, mods,
883 8301885b Michael Hanselmann
                              None, None, None)
884 8301885b Michael Hanselmann
    self.assertEqual(container, ["item 1", "item 2", "bbb"])
885 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [
886 8301885b Michael Hanselmann
      ("test/2", "remove"),
887 8301885b Michael Hanselmann
      ])
888 8301885b Michael Hanselmann
889 35554b4f Michael Hanselmann
  def testModify(self):
890 35554b4f Michael Hanselmann
    container = ["item 1", "item 2"]
891 35554b4f Michael Hanselmann
    mods = cmdlib.PrepareContainerMods([
892 35554b4f Michael Hanselmann
      (constants.DDM_MODIFY, -1, "a"),
893 35554b4f Michael Hanselmann
      (constants.DDM_MODIFY, 0, "b"),
894 35554b4f Michael Hanselmann
      (constants.DDM_MODIFY, 1, "c"),
895 35554b4f Michael Hanselmann
      ], None)
896 35554b4f Michael Hanselmann
    chgdesc = []
897 35554b4f Michael Hanselmann
    cmdlib.ApplyContainerMods("test", container, chgdesc, mods,
898 35554b4f Michael Hanselmann
                              None, None, None)
899 35554b4f Michael Hanselmann
    self.assertEqual(container, ["item 1", "item 2"])
900 35554b4f Michael Hanselmann
    self.assertEqual(chgdesc, [])
901 35554b4f Michael Hanselmann
902 35554b4f Michael Hanselmann
    for idx in [-2, len(container) + 1]:
903 35554b4f Michael Hanselmann
      mods = cmdlib.PrepareContainerMods([
904 35554b4f Michael Hanselmann
        (constants.DDM_MODIFY, idx, "error"),
905 35554b4f Michael Hanselmann
        ], None)
906 35554b4f Michael Hanselmann
      self.assertRaises(IndexError, cmdlib.ApplyContainerMods,
907 35554b4f Michael Hanselmann
                        "test", container, None, mods, None, None, None)
908 35554b4f Michael Hanselmann
909 8301885b Michael Hanselmann
  class _PrivateData:
910 8301885b Michael Hanselmann
    def __init__(self):
911 8301885b Michael Hanselmann
      self.data = None
912 8301885b Michael Hanselmann
913 8301885b Michael Hanselmann
  @staticmethod
914 efcfa99d Michael Hanselmann
  def _CreateTestFn(idx, params, private):
915 8301885b Michael Hanselmann
    private.data = ("add", idx, params)
916 efcfa99d Michael Hanselmann
    return ((100 * idx, params), [
917 efcfa99d Michael Hanselmann
      ("test/%s" % idx, hex(idx)),
918 efcfa99d Michael Hanselmann
      ])
919 8301885b Michael Hanselmann
920 8301885b Michael Hanselmann
  @staticmethod
921 efcfa99d Michael Hanselmann
  def _ModifyTestFn(idx, item, params, private):
922 8301885b Michael Hanselmann
    private.data = ("modify", idx, params)
923 efcfa99d Michael Hanselmann
    return [
924 efcfa99d Michael Hanselmann
      ("test/%s" % idx, "modify %s" % params),
925 efcfa99d Michael Hanselmann
      ]
926 8301885b Michael Hanselmann
927 8301885b Michael Hanselmann
  @staticmethod
928 efcfa99d Michael Hanselmann
  def _RemoveTestFn(idx, item, private):
929 8301885b Michael Hanselmann
    private.data = ("remove", idx, item)
930 8301885b Michael Hanselmann
931 8301885b Michael Hanselmann
  def testAddWithCreateFunction(self):
932 8301885b Michael Hanselmann
    container = []
933 8301885b Michael Hanselmann
    chgdesc = []
934 8301885b Michael Hanselmann
    mods = cmdlib.PrepareContainerMods([
935 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "Hello"),
936 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "World"),
937 8301885b Michael Hanselmann
      (constants.DDM_ADD, 0, "Start"),
938 8301885b Michael Hanselmann
      (constants.DDM_ADD, -1, "End"),
939 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, 2, None),
940 8301885b Michael Hanselmann
      (constants.DDM_MODIFY, -1, "foobar"),
941 8301885b Michael Hanselmann
      (constants.DDM_REMOVE, 2, None),
942 8301885b Michael Hanselmann
      (constants.DDM_ADD, 1, "More"),
943 8301885b Michael Hanselmann
      ], self._PrivateData)
944 8301885b Michael Hanselmann
    cmdlib.ApplyContainerMods("test", container, chgdesc, mods,
945 8301885b Michael Hanselmann
      self._CreateTestFn, self._ModifyTestFn, self._RemoveTestFn)
946 8301885b Michael Hanselmann
    self.assertEqual(container, [
947 35554b4f Michael Hanselmann
      (000, "Start"),
948 35554b4f Michael Hanselmann
      (100, "More"),
949 35554b4f Michael Hanselmann
      (000, "Hello"),
950 8301885b Michael Hanselmann
      ])
951 8301885b Michael Hanselmann
    self.assertEqual(chgdesc, [
952 8301885b Michael Hanselmann
      ("test/0", "0x0"),
953 8301885b Michael Hanselmann
      ("test/1", "0x1"),
954 35554b4f Michael Hanselmann
      ("test/0", "0x0"),
955 8301885b Michael Hanselmann
      ("test/3", "0x3"),
956 8301885b Michael Hanselmann
      ("test/2", "remove"),
957 8301885b Michael Hanselmann
      ("test/2", "modify foobar"),
958 8301885b Michael Hanselmann
      ("test/2", "remove"),
959 35554b4f Michael Hanselmann
      ("test/1", "0x1")
960 8301885b Michael Hanselmann
      ])
961 8301885b Michael Hanselmann
    self.assertTrue(compat.all(op == private.data[0]
962 8301885b Michael Hanselmann
                               for (op, _, _, private) in mods))
963 8301885b Michael Hanselmann
    self.assertEqual([private.data for (op, _, _, private) in mods], [
964 8301885b Michael Hanselmann
      ("add", 0, "Hello"),
965 8301885b Michael Hanselmann
      ("add", 1, "World"),
966 35554b4f Michael Hanselmann
      ("add", 0, "Start"),
967 8301885b Michael Hanselmann
      ("add", 3, "End"),
968 8301885b Michael Hanselmann
      ("remove", 2, (100, "World")),
969 8301885b Michael Hanselmann
      ("modify", 2, "foobar"),
970 8301885b Michael Hanselmann
      ("remove", 2, (300, "End")),
971 35554b4f Michael Hanselmann
      ("add", 1, "More"),
972 8301885b Michael Hanselmann
      ])
973 8301885b Michael Hanselmann
974 8301885b Michael Hanselmann
975 a8e3e009 Michael Hanselmann
class _FakeConfigForGenDiskTemplate:
976 a8e3e009 Michael Hanselmann
  def __init__(self):
977 a8e3e009 Michael Hanselmann
    self._unique_id = itertools.count()
978 a8e3e009 Michael Hanselmann
    self._drbd_minor = itertools.count(20)
979 a8e3e009 Michael Hanselmann
    self._port = itertools.count(constants.FIRST_DRBD_PORT)
980 a8e3e009 Michael Hanselmann
    self._secret = itertools.count()
981 a8e3e009 Michael Hanselmann
982 a8e3e009 Michael Hanselmann
  def GetVGName(self):
983 a8e3e009 Michael Hanselmann
    return "testvg"
984 a8e3e009 Michael Hanselmann
985 a8e3e009 Michael Hanselmann
  def GenerateUniqueID(self, ec_id):
986 a8e3e009 Michael Hanselmann
    return "ec%s-uq%s" % (ec_id, self._unique_id.next())
987 a8e3e009 Michael Hanselmann
988 a8e3e009 Michael Hanselmann
  def AllocateDRBDMinor(self, nodes, instance):
989 a8e3e009 Michael Hanselmann
    return [self._drbd_minor.next()
990 a8e3e009 Michael Hanselmann
            for _ in nodes]
991 a8e3e009 Michael Hanselmann
992 a8e3e009 Michael Hanselmann
  def AllocatePort(self):
993 a8e3e009 Michael Hanselmann
    return self._port.next()
994 a8e3e009 Michael Hanselmann
995 a8e3e009 Michael Hanselmann
  def GenerateDRBDSecret(self, ec_id):
996 a8e3e009 Michael Hanselmann
    return "ec%s-secret%s" % (ec_id, self._secret.next())
997 a8e3e009 Michael Hanselmann
998 99ccf8b9 René Nussbaumer
  def GetInstanceInfo(self, _):
999 99ccf8b9 René Nussbaumer
    return "foobar"
1000 99ccf8b9 René Nussbaumer
1001 a8e3e009 Michael Hanselmann
1002 a8e3e009 Michael Hanselmann
class _FakeProcForGenDiskTemplate:
1003 a8e3e009 Michael Hanselmann
  def GetECId(self):
1004 a8e3e009 Michael Hanselmann
    return 0
1005 a8e3e009 Michael Hanselmann
1006 a8e3e009 Michael Hanselmann
1007 a8e3e009 Michael Hanselmann
class TestGenerateDiskTemplate(unittest.TestCase):
1008 a8e3e009 Michael Hanselmann
  def setUp(self):
1009 a8e3e009 Michael Hanselmann
    nodegroup = objects.NodeGroup(name="ng")
1010 a8e3e009 Michael Hanselmann
    nodegroup.UpgradeConfig()
1011 a8e3e009 Michael Hanselmann
1012 a8e3e009 Michael Hanselmann
    cfg = _FakeConfigForGenDiskTemplate()
1013 a8e3e009 Michael Hanselmann
    proc = _FakeProcForGenDiskTemplate()
1014 a8e3e009 Michael Hanselmann
1015 a8e3e009 Michael Hanselmann
    self.lu = _FakeLU(cfg=cfg, proc=proc)
1016 a8e3e009 Michael Hanselmann
    self.nodegroup = nodegroup
1017 a8e3e009 Michael Hanselmann
1018 99ccf8b9 René Nussbaumer
  @staticmethod
1019 99ccf8b9 René Nussbaumer
  def GetDiskParams():
1020 99ccf8b9 René Nussbaumer
    return copy.deepcopy(constants.DISK_DT_DEFAULTS)
1021 99ccf8b9 René Nussbaumer
1022 a8e3e009 Michael Hanselmann
  def testWrongDiskTemplate(self):
1023 a8e3e009 Michael Hanselmann
    gdt = cmdlib._GenerateDiskTemplate
1024 a8e3e009 Michael Hanselmann
    disk_template = "##unknown##"
1025 a8e3e009 Michael Hanselmann
1026 a8e3e009 Michael Hanselmann
    assert disk_template not in constants.DISK_TEMPLATES
1027 a8e3e009 Michael Hanselmann
1028 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, gdt, self.lu, disk_template,
1029 a8e3e009 Michael Hanselmann
                      "inst26831.example.com", "node30113.example.com", [], [],
1030 a8e3e009 Michael Hanselmann
                      NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1031 99ccf8b9 René Nussbaumer
                      self.GetDiskParams())
1032 a8e3e009 Michael Hanselmann
1033 a8e3e009 Michael Hanselmann
  def testDiskless(self):
1034 a8e3e009 Michael Hanselmann
    gdt = cmdlib._GenerateDiskTemplate
1035 a8e3e009 Michael Hanselmann
1036 a8e3e009 Michael Hanselmann
    result = gdt(self.lu, constants.DT_DISKLESS, "inst27734.example.com",
1037 a8e3e009 Michael Hanselmann
                 "node30113.example.com", [], [],
1038 a8e3e009 Michael Hanselmann
                 NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1039 99ccf8b9 René Nussbaumer
                 self.GetDiskParams())
1040 a8e3e009 Michael Hanselmann
    self.assertEqual(result, [])
1041 a8e3e009 Michael Hanselmann
1042 a8e3e009 Michael Hanselmann
  def _TestTrivialDisk(self, template, disk_info, base_index, exp_dev_type,
1043 a8e3e009 Michael Hanselmann
                       file_storage_dir=NotImplemented,
1044 a8e3e009 Michael Hanselmann
                       file_driver=NotImplemented,
1045 a8e3e009 Michael Hanselmann
                       req_file_storage=NotImplemented,
1046 a8e3e009 Michael Hanselmann
                       req_shr_file_storage=NotImplemented):
1047 a8e3e009 Michael Hanselmann
    gdt = cmdlib._GenerateDiskTemplate
1048 a8e3e009 Michael Hanselmann
1049 a8e3e009 Michael Hanselmann
    map(lambda params: utils.ForceDictType(params,
1050 a8e3e009 Michael Hanselmann
                                           constants.IDISK_PARAMS_TYPES),
1051 a8e3e009 Michael Hanselmann
        disk_info)
1052 a8e3e009 Michael Hanselmann
1053 a8e3e009 Michael Hanselmann
    # Check if non-empty list of secondaries is rejected
1054 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, gdt, self.lu,
1055 a8e3e009 Michael Hanselmann
                      template, "inst25088.example.com",
1056 a8e3e009 Michael Hanselmann
                      "node185.example.com", ["node323.example.com"], [],
1057 a8e3e009 Michael Hanselmann
                      NotImplemented, NotImplemented, base_index,
1058 99ccf8b9 René Nussbaumer
                      self.lu.LogInfo, self.GetDiskParams(),
1059 a8e3e009 Michael Hanselmann
                      _req_file_storage=req_file_storage,
1060 a8e3e009 Michael Hanselmann
                      _req_shr_file_storage=req_shr_file_storage)
1061 a8e3e009 Michael Hanselmann
1062 a8e3e009 Michael Hanselmann
    result = gdt(self.lu, template, "inst21662.example.com",
1063 a8e3e009 Michael Hanselmann
                 "node21741.example.com", [],
1064 a8e3e009 Michael Hanselmann
                 disk_info, file_storage_dir, file_driver, base_index,
1065 99ccf8b9 René Nussbaumer
                 self.lu.LogInfo, self.GetDiskParams(),
1066 a8e3e009 Michael Hanselmann
                 _req_file_storage=req_file_storage,
1067 a8e3e009 Michael Hanselmann
                 _req_shr_file_storage=req_shr_file_storage)
1068 a8e3e009 Michael Hanselmann
1069 a8e3e009 Michael Hanselmann
    for (idx, disk) in enumerate(result):
1070 a8e3e009 Michael Hanselmann
      self.assertTrue(isinstance(disk, objects.Disk))
1071 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.dev_type, exp_dev_type)
1072 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.size, disk_info[idx][constants.IDISK_SIZE])
1073 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.mode, disk_info[idx][constants.IDISK_MODE])
1074 a8e3e009 Michael Hanselmann
      self.assertTrue(disk.children is None)
1075 a8e3e009 Michael Hanselmann
1076 0356a13d Michael Hanselmann
    self._CheckIvNames(result, base_index, base_index + len(disk_info))
1077 0356a13d Michael Hanselmann
    cmdlib._UpdateIvNames(base_index, result)
1078 0356a13d Michael Hanselmann
    self._CheckIvNames(result, base_index, base_index + len(disk_info))
1079 a8e3e009 Michael Hanselmann
1080 a8e3e009 Michael Hanselmann
    return result
1081 a8e3e009 Michael Hanselmann
1082 0356a13d Michael Hanselmann
  def _CheckIvNames(self, disks, base_index, end_index):
1083 0356a13d Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("iv_name"), disks),
1084 0356a13d Michael Hanselmann
                     ["disk/%s" % i for i in range(base_index, end_index)])
1085 0356a13d Michael Hanselmann
1086 a8e3e009 Michael Hanselmann
  def testPlain(self):
1087 a8e3e009 Michael Hanselmann
    disk_info = [{
1088 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 1024,
1089 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1090 a8e3e009 Michael Hanselmann
      }, {
1091 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 4096,
1092 a8e3e009 Michael Hanselmann
      constants.IDISK_VG: "othervg",
1093 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1094 a8e3e009 Michael Hanselmann
      }]
1095 a8e3e009 Michael Hanselmann
1096 a8e3e009 Michael Hanselmann
    result = self._TestTrivialDisk(constants.DT_PLAIN, disk_info, 3,
1097 a8e3e009 Michael Hanselmann
                                   constants.LD_LV)
1098 a8e3e009 Michael Hanselmann
1099 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1100 a8e3e009 Michael Hanselmann
      ("testvg", "ec0-uq0.disk3"),
1101 a8e3e009 Michael Hanselmann
      ("othervg", "ec0-uq1.disk4"),
1102 a8e3e009 Michael Hanselmann
      ])
1103 a8e3e009 Michael Hanselmann
1104 a8e3e009 Michael Hanselmann
  @staticmethod
1105 a8e3e009 Michael Hanselmann
  def _AllowFileStorage():
1106 a8e3e009 Michael Hanselmann
    pass
1107 a8e3e009 Michael Hanselmann
1108 a8e3e009 Michael Hanselmann
  @staticmethod
1109 a8e3e009 Michael Hanselmann
  def _ForbidFileStorage():
1110 a8e3e009 Michael Hanselmann
    raise errors.OpPrereqError("Disallowed in test")
1111 a8e3e009 Michael Hanselmann
1112 a8e3e009 Michael Hanselmann
  def testFile(self):
1113 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, self._TestTrivialDisk,
1114 a8e3e009 Michael Hanselmann
                      constants.DT_FILE, [], 0, NotImplemented,
1115 a8e3e009 Michael Hanselmann
                      req_file_storage=self._ForbidFileStorage)
1116 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, self._TestTrivialDisk,
1117 a8e3e009 Michael Hanselmann
                      constants.DT_SHARED_FILE, [], 0, NotImplemented,
1118 a8e3e009 Michael Hanselmann
                      req_shr_file_storage=self._ForbidFileStorage)
1119 a8e3e009 Michael Hanselmann
1120 a8e3e009 Michael Hanselmann
    for disk_template in [constants.DT_FILE, constants.DT_SHARED_FILE]:
1121 a8e3e009 Michael Hanselmann
      disk_info = [{
1122 a8e3e009 Michael Hanselmann
        constants.IDISK_SIZE: 80 * 1024,
1123 a8e3e009 Michael Hanselmann
        constants.IDISK_MODE: constants.DISK_RDONLY,
1124 a8e3e009 Michael Hanselmann
        }, {
1125 a8e3e009 Michael Hanselmann
        constants.IDISK_SIZE: 4096,
1126 a8e3e009 Michael Hanselmann
        constants.IDISK_MODE: constants.DISK_RDWR,
1127 a8e3e009 Michael Hanselmann
        }, {
1128 a8e3e009 Michael Hanselmann
        constants.IDISK_SIZE: 6 * 1024,
1129 a8e3e009 Michael Hanselmann
        constants.IDISK_MODE: constants.DISK_RDWR,
1130 a8e3e009 Michael Hanselmann
        }]
1131 a8e3e009 Michael Hanselmann
1132 a8e3e009 Michael Hanselmann
      result = self._TestTrivialDisk(disk_template, disk_info, 2,
1133 a8e3e009 Michael Hanselmann
        constants.LD_FILE, file_storage_dir="/tmp",
1134 a8e3e009 Michael Hanselmann
        file_driver=constants.FD_BLKTAP,
1135 a8e3e009 Michael Hanselmann
        req_file_storage=self._AllowFileStorage,
1136 a8e3e009 Michael Hanselmann
        req_shr_file_storage=self._AllowFileStorage)
1137 a8e3e009 Michael Hanselmann
1138 a8e3e009 Michael Hanselmann
      self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1139 a8e3e009 Michael Hanselmann
        (constants.FD_BLKTAP, "/tmp/disk2"),
1140 a8e3e009 Michael Hanselmann
        (constants.FD_BLKTAP, "/tmp/disk3"),
1141 a8e3e009 Michael Hanselmann
        (constants.FD_BLKTAP, "/tmp/disk4"),
1142 a8e3e009 Michael Hanselmann
        ])
1143 a8e3e009 Michael Hanselmann
1144 a8e3e009 Michael Hanselmann
  def testBlock(self):
1145 a8e3e009 Michael Hanselmann
    disk_info = [{
1146 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 8 * 1024,
1147 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1148 a8e3e009 Michael Hanselmann
      constants.IDISK_ADOPT: "/tmp/some/block/dev",
1149 a8e3e009 Michael Hanselmann
      }]
1150 a8e3e009 Michael Hanselmann
1151 a8e3e009 Michael Hanselmann
    result = self._TestTrivialDisk(constants.DT_BLOCK, disk_info, 10,
1152 a8e3e009 Michael Hanselmann
                                   constants.LD_BLOCKDEV)
1153 a8e3e009 Michael Hanselmann
1154 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1155 a8e3e009 Michael Hanselmann
      (constants.BLOCKDEV_DRIVER_MANUAL, "/tmp/some/block/dev"),
1156 a8e3e009 Michael Hanselmann
      ])
1157 a8e3e009 Michael Hanselmann
1158 a8e3e009 Michael Hanselmann
  def testRbd(self):
1159 a8e3e009 Michael Hanselmann
    disk_info = [{
1160 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 8 * 1024,
1161 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDONLY,
1162 a8e3e009 Michael Hanselmann
      }, {
1163 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 100 * 1024,
1164 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1165 a8e3e009 Michael Hanselmann
      }]
1166 a8e3e009 Michael Hanselmann
1167 a8e3e009 Michael Hanselmann
    result = self._TestTrivialDisk(constants.DT_RBD, disk_info, 0,
1168 a8e3e009 Michael Hanselmann
                                   constants.LD_RBD)
1169 a8e3e009 Michael Hanselmann
1170 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1171 a8e3e009 Michael Hanselmann
      ("rbd", "ec0-uq0.rbd.disk0"),
1172 a8e3e009 Michael Hanselmann
      ("rbd", "ec0-uq1.rbd.disk1"),
1173 a8e3e009 Michael Hanselmann
      ])
1174 a8e3e009 Michael Hanselmann
1175 a8e3e009 Michael Hanselmann
  def testDrbd8(self):
1176 a8e3e009 Michael Hanselmann
    gdt = cmdlib._GenerateDiskTemplate
1177 a8e3e009 Michael Hanselmann
    drbd8_defaults = constants.DISK_LD_DEFAULTS[constants.LD_DRBD8]
1178 a8e3e009 Michael Hanselmann
    drbd8_default_metavg = drbd8_defaults[constants.LDP_DEFAULT_METAVG]
1179 a8e3e009 Michael Hanselmann
1180 a8e3e009 Michael Hanselmann
    disk_info = [{
1181 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 1024,
1182 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1183 a8e3e009 Michael Hanselmann
      }, {
1184 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 100 * 1024,
1185 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDONLY,
1186 a8e3e009 Michael Hanselmann
      constants.IDISK_METAVG: "metavg",
1187 a8e3e009 Michael Hanselmann
      }, {
1188 a8e3e009 Michael Hanselmann
      constants.IDISK_SIZE: 4096,
1189 a8e3e009 Michael Hanselmann
      constants.IDISK_MODE: constants.DISK_RDWR,
1190 a8e3e009 Michael Hanselmann
      constants.IDISK_VG: "vgxyz",
1191 a8e3e009 Michael Hanselmann
      },
1192 a8e3e009 Michael Hanselmann
      ]
1193 a8e3e009 Michael Hanselmann
1194 a8e3e009 Michael Hanselmann
    exp_logical_ids = [[
1195 a8e3e009 Michael Hanselmann
      (self.lu.cfg.GetVGName(), "ec0-uq0.disk0_data"),
1196 a8e3e009 Michael Hanselmann
      (drbd8_default_metavg, "ec0-uq0.disk0_meta"),
1197 a8e3e009 Michael Hanselmann
      ], [
1198 a8e3e009 Michael Hanselmann
      (self.lu.cfg.GetVGName(), "ec0-uq1.disk1_data"),
1199 a8e3e009 Michael Hanselmann
      ("metavg", "ec0-uq1.disk1_meta"),
1200 a8e3e009 Michael Hanselmann
      ], [
1201 a8e3e009 Michael Hanselmann
      ("vgxyz", "ec0-uq2.disk2_data"),
1202 a8e3e009 Michael Hanselmann
      (drbd8_default_metavg, "ec0-uq2.disk2_meta"),
1203 a8e3e009 Michael Hanselmann
      ]]
1204 a8e3e009 Michael Hanselmann
1205 a8e3e009 Michael Hanselmann
    assert len(exp_logical_ids) == len(disk_info)
1206 a8e3e009 Michael Hanselmann
1207 a8e3e009 Michael Hanselmann
    map(lambda params: utils.ForceDictType(params,
1208 a8e3e009 Michael Hanselmann
                                           constants.IDISK_PARAMS_TYPES),
1209 a8e3e009 Michael Hanselmann
        disk_info)
1210 a8e3e009 Michael Hanselmann
1211 a8e3e009 Michael Hanselmann
    # Check if empty list of secondaries is rejected
1212 a8e3e009 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, gdt, self.lu, constants.DT_DRBD8,
1213 a8e3e009 Michael Hanselmann
                      "inst827.example.com", "node1334.example.com", [],
1214 a8e3e009 Michael Hanselmann
                      disk_info, NotImplemented, NotImplemented, 0,
1215 99ccf8b9 René Nussbaumer
                      self.lu.LogInfo, self.GetDiskParams())
1216 a8e3e009 Michael Hanselmann
1217 a8e3e009 Michael Hanselmann
    result = gdt(self.lu, constants.DT_DRBD8, "inst827.example.com",
1218 a8e3e009 Michael Hanselmann
                 "node1334.example.com", ["node12272.example.com"],
1219 a8e3e009 Michael Hanselmann
                 disk_info, NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1220 99ccf8b9 René Nussbaumer
                 self.GetDiskParams())
1221 a8e3e009 Michael Hanselmann
1222 a8e3e009 Michael Hanselmann
    for (idx, disk) in enumerate(result):
1223 a8e3e009 Michael Hanselmann
      self.assertTrue(isinstance(disk, objects.Disk))
1224 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.dev_type, constants.LD_DRBD8)
1225 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.size, disk_info[idx][constants.IDISK_SIZE])
1226 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.mode, disk_info[idx][constants.IDISK_MODE])
1227 a8e3e009 Michael Hanselmann
1228 a8e3e009 Michael Hanselmann
      for child in disk.children:
1229 a8e3e009 Michael Hanselmann
        self.assertTrue(isinstance(disk, objects.Disk))
1230 a8e3e009 Michael Hanselmann
        self.assertEqual(child.dev_type, constants.LD_LV)
1231 a8e3e009 Michael Hanselmann
        self.assertTrue(child.children is None)
1232 a8e3e009 Michael Hanselmann
1233 a8e3e009 Michael Hanselmann
      self.assertEqual(map(operator.attrgetter("logical_id"), disk.children),
1234 a8e3e009 Michael Hanselmann
                       exp_logical_ids[idx])
1235 a8e3e009 Michael Hanselmann
1236 a8e3e009 Michael Hanselmann
      self.assertEqual(len(disk.children), 2)
1237 a8e3e009 Michael Hanselmann
      self.assertEqual(disk.children[0].size, disk.size)
1238 0c77c331 René Nussbaumer
      self.assertEqual(disk.children[1].size, constants.DRBD_META_SIZE)
1239 a8e3e009 Michael Hanselmann
1240 0356a13d Michael Hanselmann
    self._CheckIvNames(result, 0, len(disk_info))
1241 0356a13d Michael Hanselmann
    cmdlib._UpdateIvNames(0, result)
1242 0356a13d Michael Hanselmann
    self._CheckIvNames(result, 0, len(disk_info))
1243 a8e3e009 Michael Hanselmann
1244 a8e3e009 Michael Hanselmann
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1245 a8e3e009 Michael Hanselmann
      ("node1334.example.com", "node12272.example.com",
1246 a8e3e009 Michael Hanselmann
       constants.FIRST_DRBD_PORT, 20, 21, "ec0-secret0"),
1247 a8e3e009 Michael Hanselmann
      ("node1334.example.com", "node12272.example.com",
1248 a8e3e009 Michael Hanselmann
       constants.FIRST_DRBD_PORT + 1, 22, 23, "ec0-secret1"),
1249 a8e3e009 Michael Hanselmann
      ("node1334.example.com", "node12272.example.com",
1250 a8e3e009 Michael Hanselmann
       constants.FIRST_DRBD_PORT + 2, 24, 25, "ec0-secret2"),
1251 a8e3e009 Michael Hanselmann
      ])
1252 a8e3e009 Michael Hanselmann
1253 a8e3e009 Michael Hanselmann
1254 129cce69 Michael Hanselmann
class _ConfigForDiskWipe:
1255 555b6cb1 Michael Hanselmann
  def __init__(self, exp_node):
1256 555b6cb1 Michael Hanselmann
    self._exp_node = exp_node
1257 555b6cb1 Michael Hanselmann
1258 129cce69 Michael Hanselmann
  def SetDiskID(self, device, node):
1259 129cce69 Michael Hanselmann
    assert isinstance(device, objects.Disk)
1260 555b6cb1 Michael Hanselmann
    assert node == self._exp_node
1261 129cce69 Michael Hanselmann
1262 129cce69 Michael Hanselmann
1263 129cce69 Michael Hanselmann
class _RpcForDiskWipe:
1264 555b6cb1 Michael Hanselmann
  def __init__(self, exp_node, pause_cb, wipe_cb):
1265 555b6cb1 Michael Hanselmann
    self._exp_node = exp_node
1266 129cce69 Michael Hanselmann
    self._pause_cb = pause_cb
1267 129cce69 Michael Hanselmann
    self._wipe_cb = wipe_cb
1268 129cce69 Michael Hanselmann
1269 129cce69 Michael Hanselmann
  def call_blockdev_pause_resume_sync(self, node, disks, pause):
1270 555b6cb1 Michael Hanselmann
    assert node == self._exp_node
1271 129cce69 Michael Hanselmann
    return rpc.RpcResult(data=self._pause_cb(disks, pause))
1272 129cce69 Michael Hanselmann
1273 129cce69 Michael Hanselmann
  def call_blockdev_wipe(self, node, bdev, offset, size):
1274 555b6cb1 Michael Hanselmann
    assert node == self._exp_node
1275 129cce69 Michael Hanselmann
    return rpc.RpcResult(data=self._wipe_cb(bdev, offset, size))
1276 129cce69 Michael Hanselmann
1277 129cce69 Michael Hanselmann
1278 129cce69 Michael Hanselmann
class _DiskPauseTracker:
1279 129cce69 Michael Hanselmann
  def __init__(self):
1280 129cce69 Michael Hanselmann
    self.history = []
1281 129cce69 Michael Hanselmann
1282 129cce69 Michael Hanselmann
  def __call__(self, (disks, instance), pause):
1283 fa8ef9d6 Michael Hanselmann
    assert not (set(disks) - set(instance.disks))
1284 129cce69 Michael Hanselmann
1285 129cce69 Michael Hanselmann
    self.history.extend((i.logical_id, i.size, pause)
1286 129cce69 Michael Hanselmann
                        for i in disks)
1287 129cce69 Michael Hanselmann
1288 129cce69 Michael Hanselmann
    return (True, [True] * len(disks))
1289 129cce69 Michael Hanselmann
1290 129cce69 Michael Hanselmann
1291 555b6cb1 Michael Hanselmann
class _DiskWipeProgressTracker:
1292 555b6cb1 Michael Hanselmann
  def __init__(self, start_offset):
1293 555b6cb1 Michael Hanselmann
    self._start_offset = start_offset
1294 555b6cb1 Michael Hanselmann
    self.progress = {}
1295 555b6cb1 Michael Hanselmann
1296 555b6cb1 Michael Hanselmann
  def __call__(self, (disk, _), offset, size):
1297 555b6cb1 Michael Hanselmann
    assert isinstance(offset, (long, int))
1298 555b6cb1 Michael Hanselmann
    assert isinstance(size, (long, int))
1299 555b6cb1 Michael Hanselmann
1300 555b6cb1 Michael Hanselmann
    max_chunk_size = (disk.size / 100.0 * constants.MIN_WIPE_CHUNK_PERCENT)
1301 555b6cb1 Michael Hanselmann
1302 555b6cb1 Michael Hanselmann
    assert offset >= self._start_offset
1303 555b6cb1 Michael Hanselmann
    assert (offset + size) <= disk.size
1304 555b6cb1 Michael Hanselmann
1305 555b6cb1 Michael Hanselmann
    assert size > 0
1306 555b6cb1 Michael Hanselmann
    assert size <= constants.MAX_WIPE_CHUNK
1307 555b6cb1 Michael Hanselmann
    assert size <= max_chunk_size
1308 555b6cb1 Michael Hanselmann
1309 555b6cb1 Michael Hanselmann
    assert offset == self._start_offset or disk.logical_id in self.progress
1310 555b6cb1 Michael Hanselmann
1311 555b6cb1 Michael Hanselmann
    # Keep track of progress
1312 555b6cb1 Michael Hanselmann
    cur_progress = self.progress.setdefault(disk.logical_id, self._start_offset)
1313 555b6cb1 Michael Hanselmann
1314 555b6cb1 Michael Hanselmann
    assert cur_progress == offset
1315 555b6cb1 Michael Hanselmann
1316 555b6cb1 Michael Hanselmann
    # Record progress
1317 555b6cb1 Michael Hanselmann
    self.progress[disk.logical_id] += size
1318 555b6cb1 Michael Hanselmann
1319 555b6cb1 Michael Hanselmann
    return (True, None)
1320 555b6cb1 Michael Hanselmann
1321 555b6cb1 Michael Hanselmann
1322 129cce69 Michael Hanselmann
class TestWipeDisks(unittest.TestCase):
1323 555b6cb1 Michael Hanselmann
  def _FailingPauseCb(self, (disks, _), pause):
1324 555b6cb1 Michael Hanselmann
    self.assertEqual(len(disks), 3)
1325 555b6cb1 Michael Hanselmann
    self.assertTrue(pause)
1326 555b6cb1 Michael Hanselmann
    # Simulate an RPC error
1327 555b6cb1 Michael Hanselmann
    return (False, "error")
1328 555b6cb1 Michael Hanselmann
1329 129cce69 Michael Hanselmann
  def testPauseFailure(self):
1330 555b6cb1 Michael Hanselmann
    node_name = "node1372.example.com"
1331 129cce69 Michael Hanselmann
1332 555b6cb1 Michael Hanselmann
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, self._FailingPauseCb,
1333 555b6cb1 Michael Hanselmann
                                     NotImplemented),
1334 555b6cb1 Michael Hanselmann
                 cfg=_ConfigForDiskWipe(node_name))
1335 129cce69 Michael Hanselmann
1336 129cce69 Michael Hanselmann
    disks = [
1337 129cce69 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV),
1338 129cce69 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV),
1339 129cce69 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV),
1340 129cce69 Michael Hanselmann
      ]
1341 129cce69 Michael Hanselmann
1342 129cce69 Michael Hanselmann
    instance = objects.Instance(name="inst21201",
1343 555b6cb1 Michael Hanselmann
                                primary_node=node_name,
1344 129cce69 Michael Hanselmann
                                disk_template=constants.DT_PLAIN,
1345 129cce69 Michael Hanselmann
                                disks=disks)
1346 129cce69 Michael Hanselmann
1347 129cce69 Michael Hanselmann
    self.assertRaises(errors.OpExecError, cmdlib._WipeDisks, lu, instance)
1348 129cce69 Michael Hanselmann
1349 555b6cb1 Michael Hanselmann
  def _FailingWipeCb(self, (disk, _), offset, size):
1350 555b6cb1 Michael Hanselmann
    # This should only ever be called for the first disk
1351 555b6cb1 Michael Hanselmann
    self.assertEqual(disk.logical_id, "disk0")
1352 555b6cb1 Michael Hanselmann
    return (False, None)
1353 555b6cb1 Michael Hanselmann
1354 129cce69 Michael Hanselmann
  def testFailingWipe(self):
1355 555b6cb1 Michael Hanselmann
    node_name = "node13445.example.com"
1356 129cce69 Michael Hanselmann
    pt = _DiskPauseTracker()
1357 129cce69 Michael Hanselmann
1358 555b6cb1 Michael Hanselmann
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, pt, self._FailingWipeCb),
1359 555b6cb1 Michael Hanselmann
                 cfg=_ConfigForDiskWipe(node_name))
1360 129cce69 Michael Hanselmann
1361 129cce69 Michael Hanselmann
    disks = [
1362 129cce69 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk0",
1363 129cce69 Michael Hanselmann
                   size=100 * 1024),
1364 129cce69 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1365 129cce69 Michael Hanselmann
                   size=500 * 1024),
1366 129cce69 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk2", size=256),
1367 129cce69 Michael Hanselmann
      ]
1368 129cce69 Michael Hanselmann
1369 129cce69 Michael Hanselmann
    instance = objects.Instance(name="inst562",
1370 555b6cb1 Michael Hanselmann
                                primary_node=node_name,
1371 129cce69 Michael Hanselmann
                                disk_template=constants.DT_PLAIN,
1372 129cce69 Michael Hanselmann
                                disks=disks)
1373 129cce69 Michael Hanselmann
1374 129cce69 Michael Hanselmann
    try:
1375 129cce69 Michael Hanselmann
      cmdlib._WipeDisks(lu, instance)
1376 129cce69 Michael Hanselmann
    except errors.OpExecError, err:
1377 129cce69 Michael Hanselmann
      self.assertTrue(str(err), "Could not wipe disk 0 at offset 0 ")
1378 129cce69 Michael Hanselmann
    else:
1379 129cce69 Michael Hanselmann
      self.fail("Did not raise exception")
1380 129cce69 Michael Hanselmann
1381 555b6cb1 Michael Hanselmann
    # Check if all disks were paused and resumed
1382 129cce69 Michael Hanselmann
    self.assertEqual(pt.history, [
1383 129cce69 Michael Hanselmann
      ("disk0", 100 * 1024, True),
1384 129cce69 Michael Hanselmann
      ("disk1", 500 * 1024, True),
1385 129cce69 Michael Hanselmann
      ("disk2", 256, True),
1386 129cce69 Michael Hanselmann
      ("disk0", 100 * 1024, False),
1387 129cce69 Michael Hanselmann
      ("disk1", 500 * 1024, False),
1388 129cce69 Michael Hanselmann
      ("disk2", 256, False),
1389 129cce69 Michael Hanselmann
      ])
1390 129cce69 Michael Hanselmann
1391 555b6cb1 Michael Hanselmann
  def _PrepareWipeTest(self, start_offset, disks):
1392 555b6cb1 Michael Hanselmann
    node_name = "node-with-offset%s.example.com" % start_offset
1393 555b6cb1 Michael Hanselmann
    pauset = _DiskPauseTracker()
1394 555b6cb1 Michael Hanselmann
    progresst = _DiskWipeProgressTracker(start_offset)
1395 129cce69 Michael Hanselmann
1396 555b6cb1 Michael Hanselmann
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, pauset, progresst),
1397 555b6cb1 Michael Hanselmann
                 cfg=_ConfigForDiskWipe(node_name))
1398 129cce69 Michael Hanselmann
1399 555b6cb1 Michael Hanselmann
    instance = objects.Instance(name="inst3560",
1400 555b6cb1 Michael Hanselmann
                                primary_node=node_name,
1401 555b6cb1 Michael Hanselmann
                                disk_template=constants.DT_PLAIN,
1402 555b6cb1 Michael Hanselmann
                                disks=disks)
1403 129cce69 Michael Hanselmann
1404 555b6cb1 Michael Hanselmann
    return (lu, instance, pauset, progresst)
1405 555b6cb1 Michael Hanselmann
1406 555b6cb1 Michael Hanselmann
  def testNormalWipe(self):
1407 555b6cb1 Michael Hanselmann
    disks = [
1408 555b6cb1 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk0", size=1024),
1409 555b6cb1 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1410 555b6cb1 Michael Hanselmann
                   size=500 * 1024),
1411 555b6cb1 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk2", size=128),
1412 555b6cb1 Michael Hanselmann
      objects.Disk(dev_type=constants.LD_LV, logical_id="disk3",
1413 555b6cb1 Michael Hanselmann
                   size=constants.MAX_WIPE_CHUNK),
1414 555b6cb1 Michael Hanselmann
      ]
1415 129cce69 Michael Hanselmann
1416 555b6cb1 Michael Hanselmann
    (lu, instance, pauset, progresst) = self._PrepareWipeTest(0, disks)
1417 129cce69 Michael Hanselmann
1418 555b6cb1 Michael Hanselmann
    cmdlib._WipeDisks(lu, instance)
1419 129cce69 Michael Hanselmann
1420 555b6cb1 Michael Hanselmann
    self.assertEqual(pauset.history, [
1421 555b6cb1 Michael Hanselmann
      ("disk0", 1024, True),
1422 555b6cb1 Michael Hanselmann
      ("disk1", 500 * 1024, True),
1423 555b6cb1 Michael Hanselmann
      ("disk2", 128, True),
1424 555b6cb1 Michael Hanselmann
      ("disk3", constants.MAX_WIPE_CHUNK, True),
1425 555b6cb1 Michael Hanselmann
      ("disk0", 1024, False),
1426 555b6cb1 Michael Hanselmann
      ("disk1", 500 * 1024, False),
1427 555b6cb1 Michael Hanselmann
      ("disk2", 128, False),
1428 555b6cb1 Michael Hanselmann
      ("disk3", constants.MAX_WIPE_CHUNK, False),
1429 555b6cb1 Michael Hanselmann
      ])
1430 129cce69 Michael Hanselmann
1431 555b6cb1 Michael Hanselmann
    # Ensure the complete disk has been wiped
1432 555b6cb1 Michael Hanselmann
    self.assertEqual(progresst.progress,
1433 555b6cb1 Michael Hanselmann
                     dict((i.logical_id, i.size) for i in disks))
1434 129cce69 Michael Hanselmann
1435 555b6cb1 Michael Hanselmann
  def testWipeWithStartOffset(self):
1436 555b6cb1 Michael Hanselmann
    for start_offset in [0, 280, 8895, 1563204]:
1437 555b6cb1 Michael Hanselmann
      disks = [
1438 555b6cb1 Michael Hanselmann
        objects.Disk(dev_type=constants.LD_LV, logical_id="disk0",
1439 555b6cb1 Michael Hanselmann
                     size=128),
1440 555b6cb1 Michael Hanselmann
        objects.Disk(dev_type=constants.LD_LV, logical_id="disk1",
1441 555b6cb1 Michael Hanselmann
                     size=start_offset + (100 * 1024)),
1442 555b6cb1 Michael Hanselmann
        ]
1443 129cce69 Michael Hanselmann
1444 555b6cb1 Michael Hanselmann
      (lu, instance, pauset, progresst) = \
1445 555b6cb1 Michael Hanselmann
        self._PrepareWipeTest(start_offset, disks)
1446 129cce69 Michael Hanselmann
1447 555b6cb1 Michael Hanselmann
      # Test start offset with only one disk
1448 555b6cb1 Michael Hanselmann
      cmdlib._WipeDisks(lu, instance,
1449 555b6cb1 Michael Hanselmann
                        disks=[(1, disks[1], start_offset)])
1450 129cce69 Michael Hanselmann
1451 555b6cb1 Michael Hanselmann
      # Only the second disk may have been paused and wiped
1452 555b6cb1 Michael Hanselmann
      self.assertEqual(pauset.history, [
1453 555b6cb1 Michael Hanselmann
        ("disk1", start_offset + (100 * 1024), True),
1454 555b6cb1 Michael Hanselmann
        ("disk1", start_offset + (100 * 1024), False),
1455 555b6cb1 Michael Hanselmann
        ])
1456 555b6cb1 Michael Hanselmann
      self.assertEqual(progresst.progress, {
1457 555b6cb1 Michael Hanselmann
        "disk1": disks[1].size,
1458 555b6cb1 Michael Hanselmann
        })
1459 fa8ef9d6 Michael Hanselmann
1460 fa8ef9d6 Michael Hanselmann
1461 fa8ef9d6 Michael Hanselmann
class TestDiskSizeInBytesToMebibytes(unittest.TestCase):
1462 fa8ef9d6 Michael Hanselmann
  def testLessThanOneMebibyte(self):
1463 fa8ef9d6 Michael Hanselmann
    for i in [1, 2, 7, 512, 1000, 1023]:
1464 fa8ef9d6 Michael Hanselmann
      lu = _FakeLU()
1465 fa8ef9d6 Michael Hanselmann
      result = cmdlib._DiskSizeInBytesToMebibytes(lu, i)
1466 fa8ef9d6 Michael Hanselmann
      self.assertEqual(result, 1)
1467 fa8ef9d6 Michael Hanselmann
      self.assertEqual(len(lu.warning_log), 1)
1468 fa8ef9d6 Michael Hanselmann
      self.assertEqual(len(lu.warning_log[0]), 2)
1469 fa8ef9d6 Michael Hanselmann
      (_, (warnsize, )) = lu.warning_log[0]
1470 fa8ef9d6 Michael Hanselmann
      self.assertEqual(warnsize, (1024 * 1024) - i)
1471 fa8ef9d6 Michael Hanselmann
1472 fa8ef9d6 Michael Hanselmann
  def testEven(self):
1473 fa8ef9d6 Michael Hanselmann
    for i in [1, 2, 7, 512, 1000, 1023]:
1474 fa8ef9d6 Michael Hanselmann
      lu = _FakeLU()
1475 fa8ef9d6 Michael Hanselmann
      result = cmdlib._DiskSizeInBytesToMebibytes(lu, i * 1024 * 1024)
1476 fa8ef9d6 Michael Hanselmann
      self.assertEqual(result, i)
1477 fa8ef9d6 Michael Hanselmann
      self.assertFalse(lu.warning_log)
1478 fa8ef9d6 Michael Hanselmann
1479 fa8ef9d6 Michael Hanselmann
  def testLargeNumber(self):
1480 fa8ef9d6 Michael Hanselmann
    for i in [1, 2, 7, 512, 1000, 1023, 2724, 12420]:
1481 fa8ef9d6 Michael Hanselmann
      for j in [1, 2, 486, 326, 986, 1023]:
1482 fa8ef9d6 Michael Hanselmann
        lu = _FakeLU()
1483 fa8ef9d6 Michael Hanselmann
        size = (1024 * 1024 * i) + j
1484 fa8ef9d6 Michael Hanselmann
        result = cmdlib._DiskSizeInBytesToMebibytes(lu, size)
1485 fa8ef9d6 Michael Hanselmann
        self.assertEqual(result, i + 1, msg="Amount was not rounded up")
1486 fa8ef9d6 Michael Hanselmann
        self.assertEqual(len(lu.warning_log), 1)
1487 fa8ef9d6 Michael Hanselmann
        self.assertEqual(len(lu.warning_log[0]), 2)
1488 fa8ef9d6 Michael Hanselmann
        (_, (warnsize, )) = lu.warning_log[0]
1489 fa8ef9d6 Michael Hanselmann
        self.assertEqual(warnsize, (1024 * 1024) - j)
1490 129cce69 Michael Hanselmann
1491 129cce69 Michael Hanselmann
1492 ef86bf28 Michael Hanselmann
class TestCopyLockList(unittest.TestCase):
1493 ef86bf28 Michael Hanselmann
  def test(self):
1494 ef86bf28 Michael Hanselmann
    self.assertEqual(cmdlib._CopyLockList([]), [])
1495 ef86bf28 Michael Hanselmann
    self.assertEqual(cmdlib._CopyLockList(None), None)
1496 ef86bf28 Michael Hanselmann
    self.assertEqual(cmdlib._CopyLockList(locking.ALL_SET), locking.ALL_SET)
1497 ef86bf28 Michael Hanselmann
1498 ef86bf28 Michael Hanselmann
    names = ["foo", "bar"]
1499 ef86bf28 Michael Hanselmann
    output = cmdlib._CopyLockList(names)
1500 ef86bf28 Michael Hanselmann
    self.assertEqual(names, output)
1501 ef86bf28 Michael Hanselmann
    self.assertNotEqual(id(names), id(output), msg="List was not copied")
1502 ef86bf28 Michael Hanselmann
1503 ef86bf28 Michael Hanselmann
1504 b98bf262 Michael Hanselmann
if __name__ == "__main__":
1505 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()