Statistics
| Branch: | Tag: | Revision:

root / test / py / cmdlib / instance_unittest.py @ ac156ecd

History | View | Annotate | Download (83.5 kB)

1 66222813 Thomas Thrainer
#!/usr/bin/python
2 66222813 Thomas Thrainer
#
3 66222813 Thomas Thrainer
4 66222813 Thomas Thrainer
# Copyright (C) 2008, 2011, 2012, 2013 Google Inc.
5 66222813 Thomas Thrainer
#
6 66222813 Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 66222813 Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 66222813 Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 66222813 Thomas Thrainer
# (at your option) any later version.
10 66222813 Thomas Thrainer
#
11 66222813 Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 66222813 Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 66222813 Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 66222813 Thomas Thrainer
# General Public License for more details.
15 66222813 Thomas Thrainer
#
16 66222813 Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 66222813 Thomas Thrainer
# along with this program; if not, write to the Free Software
18 66222813 Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 66222813 Thomas Thrainer
# 02110-1301, USA.
20 66222813 Thomas Thrainer
21 66222813 Thomas Thrainer
22 66222813 Thomas Thrainer
"""Tests for LUInstance*
23 66222813 Thomas Thrainer

24 66222813 Thomas Thrainer
"""
25 66222813 Thomas Thrainer
26 66222813 Thomas Thrainer
import copy
27 66222813 Thomas Thrainer
import itertools
28 66222813 Thomas Thrainer
import unittest
29 66222813 Thomas Thrainer
import mock
30 66222813 Thomas Thrainer
import operator
31 66222813 Thomas Thrainer
32 66222813 Thomas Thrainer
from ganeti import compat
33 66222813 Thomas Thrainer
from ganeti import constants
34 66222813 Thomas Thrainer
from ganeti import errors
35 66222813 Thomas Thrainer
from ganeti import ht
36 66222813 Thomas Thrainer
from ganeti import opcodes
37 66222813 Thomas Thrainer
from ganeti import objects
38 66222813 Thomas Thrainer
from ganeti import rpc
39 66222813 Thomas Thrainer
from ganeti import utils
40 66222813 Thomas Thrainer
from ganeti.cmdlib import instance
41 66222813 Thomas Thrainer
42 66222813 Thomas Thrainer
from cmdlib.cmdlib_unittest import _StubComputeIPolicySpecViolation, _FakeLU
43 66222813 Thomas Thrainer
44 66222813 Thomas Thrainer
from testsupport import *
45 66222813 Thomas Thrainer
46 66222813 Thomas Thrainer
import testutils
47 66222813 Thomas Thrainer
48 66222813 Thomas Thrainer
49 66222813 Thomas Thrainer
class TestComputeIPolicyInstanceSpecViolation(unittest.TestCase):
50 66222813 Thomas Thrainer
  def test(self):
51 66222813 Thomas Thrainer
    ispec = {
52 66222813 Thomas Thrainer
      constants.ISPEC_MEM_SIZE: 2048,
53 66222813 Thomas Thrainer
      constants.ISPEC_CPU_COUNT: 2,
54 66222813 Thomas Thrainer
      constants.ISPEC_DISK_COUNT: 1,
55 66222813 Thomas Thrainer
      constants.ISPEC_DISK_SIZE: [512],
56 66222813 Thomas Thrainer
      constants.ISPEC_NIC_COUNT: 0,
57 66222813 Thomas Thrainer
      constants.ISPEC_SPINDLE_USE: 1,
58 66222813 Thomas Thrainer
      }
59 66222813 Thomas Thrainer
    stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 1,
60 66222813 Thomas Thrainer
                                            constants.DT_PLAIN)
61 66222813 Thomas Thrainer
    ret = instance._ComputeIPolicyInstanceSpecViolation(NotImplemented, ispec,
62 66222813 Thomas Thrainer
                                                        constants.DT_PLAIN,
63 66222813 Thomas Thrainer
                                                        _compute_fn=stub)
64 66222813 Thomas Thrainer
    self.assertEqual(ret, [])
65 66222813 Thomas Thrainer
66 66222813 Thomas Thrainer
67 66222813 Thomas Thrainer
class TestLUInstanceCreate(CmdlibTestCase):
68 66222813 Thomas Thrainer
  def setUp(self):
69 66222813 Thomas Thrainer
    super(TestLUInstanceCreate, self).setUp()
70 66222813 Thomas Thrainer
71 66222813 Thomas Thrainer
    self.net = self.cfg.AddNewNetwork()
72 66222813 Thomas Thrainer
    self.cfg.ConnectNetworkToGroup(self.net, self.group)
73 66222813 Thomas Thrainer
74 66222813 Thomas Thrainer
    self.node1 = self.cfg.AddNewNode()
75 66222813 Thomas Thrainer
    self.node2 = self.cfg.AddNewNode()
76 66222813 Thomas Thrainer
77 66222813 Thomas Thrainer
    self.rpc.call_os_get.side_effect = \
78 66222813 Thomas Thrainer
      lambda node, _: self.RpcResultsBuilder() \
79 66222813 Thomas Thrainer
                        .CreateSuccessfulNodeResult(node, self.os)
80 66222813 Thomas Thrainer
81 66222813 Thomas Thrainer
    hv_info = ("bootid",
82 66222813 Thomas Thrainer
               [{
83 66222813 Thomas Thrainer
                 "type": constants.ST_LVM_VG,
84 66222813 Thomas Thrainer
                 "storage_free": 10000
85 66222813 Thomas Thrainer
               }],
86 66222813 Thomas Thrainer
               ({"memory_free": 10000}, ))
87 66222813 Thomas Thrainer
    self.rpc.call_node_info.return_value = \
88 66222813 Thomas Thrainer
      self.RpcResultsBuilder() \
89 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.master, hv_info) \
90 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.node1, hv_info) \
91 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.node2, hv_info) \
92 66222813 Thomas Thrainer
        .Build()
93 66222813 Thomas Thrainer
94 66222813 Thomas Thrainer
    self.rpc.call_blockdev_getmirrorstatus.side_effect = \
95 66222813 Thomas Thrainer
      lambda node, _: self.RpcResultsBuilder() \
96 66222813 Thomas Thrainer
                        .CreateSuccessfulNodeResult(node, [])
97 66222813 Thomas Thrainer
98 66222813 Thomas Thrainer
    self.iallocator_cls.return_value.result = [self.node1.name, self.node2.name]
99 66222813 Thomas Thrainer
100 66222813 Thomas Thrainer
    self.diskless_op = opcodes.OpInstanceCreate(
101 66222813 Thomas Thrainer
      instance_name="diskless.test.com",
102 66222813 Thomas Thrainer
      pnode=self.master.name,
103 66222813 Thomas Thrainer
      disk_template=constants.DT_DISKLESS,
104 66222813 Thomas Thrainer
      mode=constants.INSTANCE_CREATE,
105 66222813 Thomas Thrainer
      nics=[{}],
106 66222813 Thomas Thrainer
      disks=[],
107 66222813 Thomas Thrainer
      os_type=self.os_name_variant)
108 66222813 Thomas Thrainer
109 66222813 Thomas Thrainer
    self.plain_op = opcodes.OpInstanceCreate(
110 66222813 Thomas Thrainer
      instance_name="plain.test.com",
111 66222813 Thomas Thrainer
      pnode=self.master.name,
112 66222813 Thomas Thrainer
      disk_template=constants.DT_PLAIN,
113 66222813 Thomas Thrainer
      mode=constants.INSTANCE_CREATE,
114 66222813 Thomas Thrainer
      nics=[{}],
115 66222813 Thomas Thrainer
      disks=[{
116 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 1024
117 66222813 Thomas Thrainer
      }],
118 66222813 Thomas Thrainer
      os_type=self.os_name_variant)
119 66222813 Thomas Thrainer
120 66222813 Thomas Thrainer
    self.block_op = opcodes.OpInstanceCreate(
121 66222813 Thomas Thrainer
      instance_name="block.test.com",
122 66222813 Thomas Thrainer
      pnode=self.master.name,
123 66222813 Thomas Thrainer
      disk_template=constants.DT_BLOCK,
124 66222813 Thomas Thrainer
      mode=constants.INSTANCE_CREATE,
125 66222813 Thomas Thrainer
      nics=[{}],
126 66222813 Thomas Thrainer
      disks=[{
127 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 1024,
128 66222813 Thomas Thrainer
        constants.IDISK_ADOPT: "/dev/disk/block0"
129 66222813 Thomas Thrainer
      }],
130 66222813 Thomas Thrainer
      os_type=self.os_name_variant)
131 66222813 Thomas Thrainer
132 66222813 Thomas Thrainer
    self.drbd_op = opcodes.OpInstanceCreate(
133 66222813 Thomas Thrainer
      instance_name="drbd.test.com",
134 66222813 Thomas Thrainer
      pnode=self.node1.name,
135 66222813 Thomas Thrainer
      snode=self.node2.name,
136 66222813 Thomas Thrainer
      disk_template=constants.DT_DRBD8,
137 66222813 Thomas Thrainer
      mode=constants.INSTANCE_CREATE,
138 66222813 Thomas Thrainer
      nics=[{}],
139 66222813 Thomas Thrainer
      disks=[{
140 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 1024
141 66222813 Thomas Thrainer
      }],
142 66222813 Thomas Thrainer
      os_type=self.os_name_variant)
143 66222813 Thomas Thrainer
144 66222813 Thomas Thrainer
    self.file_op = opcodes.OpInstanceCreate(
145 66222813 Thomas Thrainer
      instance_name="file.test.com",
146 66222813 Thomas Thrainer
      pnode=self.node1.name,
147 66222813 Thomas Thrainer
      disk_template=constants.DT_FILE,
148 66222813 Thomas Thrainer
      mode=constants.INSTANCE_CREATE,
149 66222813 Thomas Thrainer
      nics=[{}],
150 66222813 Thomas Thrainer
      disks=[{
151 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 1024
152 66222813 Thomas Thrainer
      }],
153 66222813 Thomas Thrainer
      os_type=self.os_name_variant)
154 66222813 Thomas Thrainer
155 66222813 Thomas Thrainer
  def testSimpleCreate(self):
156 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op)
157 66222813 Thomas Thrainer
    self.ExecOpCode(op)
158 66222813 Thomas Thrainer
159 66222813 Thomas Thrainer
  def testStrangeHostnameResolve(self):
160 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op)
161 66222813 Thomas Thrainer
    self.netutils_mod.GetHostname.return_value = \
162 11414807 Klaus Aehlig
      HostnameMock("random.host.example.com", "203.0.113.1")
163 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
164 66222813 Thomas Thrainer
      op, "Resolved hostname .* does not look the same as given hostname")
165 66222813 Thomas Thrainer
166 66222813 Thomas Thrainer
  def testOpportunisticLockingNoIAllocator(self):
167 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
168 66222813 Thomas Thrainer
                         opportunistic_locking=True,
169 66222813 Thomas Thrainer
                         iallocator=None)
170 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
171 66222813 Thomas Thrainer
      op, "Opportunistic locking is only available in combination with an"
172 66222813 Thomas Thrainer
          " instance allocator")
173 66222813 Thomas Thrainer
174 66222813 Thomas Thrainer
  def testNicWithNetAndMode(self):
175 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
176 66222813 Thomas Thrainer
                         nics=[{
177 66222813 Thomas Thrainer
                           constants.INIC_NETWORK: self.net.name,
178 66222813 Thomas Thrainer
                           constants.INIC_MODE: constants.NIC_MODE_BRIDGED
179 66222813 Thomas Thrainer
                         }])
180 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
181 66222813 Thomas Thrainer
      op, "If network is given, no mode or link is allowed to be passed")
182 66222813 Thomas Thrainer
183 66222813 Thomas Thrainer
  def testAutoIpNoNameCheck(self):
184 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
185 66222813 Thomas Thrainer
                         nics=[{
186 66222813 Thomas Thrainer
                           constants.INIC_IP: constants.VALUE_AUTO
187 66222813 Thomas Thrainer
                         }],
188 66222813 Thomas Thrainer
                         ip_check=False,
189 66222813 Thomas Thrainer
                         name_check=False)
190 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
191 66222813 Thomas Thrainer
      op, "IP address set to auto but name checks have been skipped")
192 66222813 Thomas Thrainer
193 66222813 Thomas Thrainer
  def testAutoIp(self):
194 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
195 66222813 Thomas Thrainer
                         nics=[{
196 66222813 Thomas Thrainer
                           constants.INIC_IP: constants.VALUE_AUTO
197 66222813 Thomas Thrainer
                         }])
198 66222813 Thomas Thrainer
    self.ExecOpCode(op)
199 66222813 Thomas Thrainer
200 66222813 Thomas Thrainer
  def testPoolIpNoNetwork(self):
201 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
202 66222813 Thomas Thrainer
                         nics=[{
203 66222813 Thomas Thrainer
                           constants.INIC_IP: constants.NIC_IP_POOL
204 66222813 Thomas Thrainer
                         }])
205 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
206 66222813 Thomas Thrainer
      op, "if ip=pool, parameter network must be passed too")
207 66222813 Thomas Thrainer
208 66222813 Thomas Thrainer
  def testValidIp(self):
209 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
210 66222813 Thomas Thrainer
                         nics=[{
211 11414807 Klaus Aehlig
                           constants.INIC_IP: "203.0.113.1"
212 66222813 Thomas Thrainer
                         }])
213 66222813 Thomas Thrainer
    self.ExecOpCode(op)
214 66222813 Thomas Thrainer
215 66222813 Thomas Thrainer
  def testRoutedNoIp(self):
216 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
217 66222813 Thomas Thrainer
                         nics=[{
218 66222813 Thomas Thrainer
                           constants.INIC_MODE: constants.NIC_MODE_ROUTED
219 66222813 Thomas Thrainer
                         }])
220 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
221 66222813 Thomas Thrainer
      op, "Routed nic mode requires an ip address")
222 66222813 Thomas Thrainer
223 66222813 Thomas Thrainer
  def testValicMac(self):
224 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
225 66222813 Thomas Thrainer
                         nics=[{
226 66222813 Thomas Thrainer
                           constants.INIC_MAC: "f0:df:f4:a3:d1:cf"
227 66222813 Thomas Thrainer
                         }])
228 66222813 Thomas Thrainer
    self.ExecOpCode(op)
229 66222813 Thomas Thrainer
230 66222813 Thomas Thrainer
  def testValidNicParams(self):
231 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
232 66222813 Thomas Thrainer
                         nics=[{
233 66222813 Thomas Thrainer
                           constants.INIC_MODE: constants.NIC_MODE_BRIDGED,
234 66222813 Thomas Thrainer
                           constants.INIC_LINK: "br_mock"
235 66222813 Thomas Thrainer
                         }])
236 66222813 Thomas Thrainer
    self.ExecOpCode(op)
237 66222813 Thomas Thrainer
238 66222813 Thomas Thrainer
  def testValidNicParamsOpenVSwitch(self):
239 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
240 66222813 Thomas Thrainer
                         nics=[{
241 66222813 Thomas Thrainer
                           constants.INIC_MODE: constants.NIC_MODE_OVS,
242 66222813 Thomas Thrainer
                           constants.INIC_VLAN: "1"
243 66222813 Thomas Thrainer
                         }])
244 66222813 Thomas Thrainer
    self.ExecOpCode(op)
245 66222813 Thomas Thrainer
246 66222813 Thomas Thrainer
  def testNicNoneName(self):
247 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
248 66222813 Thomas Thrainer
                         nics=[{
249 66222813 Thomas Thrainer
                           constants.INIC_NAME: constants.VALUE_NONE
250 66222813 Thomas Thrainer
                         }])
251 66222813 Thomas Thrainer
    self.ExecOpCode(op)
252 66222813 Thomas Thrainer
253 66222813 Thomas Thrainer
  def testConflictingIP(self):
254 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
255 66222813 Thomas Thrainer
                         nics=[{
256 66222813 Thomas Thrainer
                           constants.INIC_IP: self.net.gateway[:-1] + "2"
257 66222813 Thomas Thrainer
                         }])
258 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
259 66222813 Thomas Thrainer
      op, "The requested IP address .* belongs to network .*, but the target"
260 66222813 Thomas Thrainer
          " NIC does not.")
261 66222813 Thomas Thrainer
262 66222813 Thomas Thrainer
  def testVLanFormat(self):
263 66222813 Thomas Thrainer
    for vlan in [".pinky", ":bunny", ":1:pinky", "bunny"]:
264 66222813 Thomas Thrainer
      self.ResetMocks()
265 66222813 Thomas Thrainer
      op = self.CopyOpCode(self.diskless_op,
266 66222813 Thomas Thrainer
                           nics=[{
267 66222813 Thomas Thrainer
                             constants.INIC_VLAN: vlan
268 66222813 Thomas Thrainer
                           }])
269 66222813 Thomas Thrainer
      self.ExecOpCodeExpectOpPrereqError(
270 66222813 Thomas Thrainer
        op, "Specified VLAN parameter is invalid")
271 66222813 Thomas Thrainer
272 66222813 Thomas Thrainer
  def testPoolIp(self):
273 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
274 66222813 Thomas Thrainer
                         nics=[{
275 66222813 Thomas Thrainer
                           constants.INIC_IP: constants.NIC_IP_POOL,
276 66222813 Thomas Thrainer
                           constants.INIC_NETWORK: self.net.name
277 66222813 Thomas Thrainer
                         }])
278 66222813 Thomas Thrainer
    self.ExecOpCode(op)
279 66222813 Thomas Thrainer
280 66222813 Thomas Thrainer
  def testPoolIpUnconnectedNetwork(self):
281 66222813 Thomas Thrainer
    net = self.cfg.AddNewNetwork()
282 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
283 66222813 Thomas Thrainer
                         nics=[{
284 66222813 Thomas Thrainer
                           constants.INIC_IP: constants.NIC_IP_POOL,
285 66222813 Thomas Thrainer
                           constants.INIC_NETWORK: net.name
286 66222813 Thomas Thrainer
                         }])
287 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
288 66222813 Thomas Thrainer
      op, "No netparams found for network .*.")
289 66222813 Thomas Thrainer
290 66222813 Thomas Thrainer
  def testIpNotInNetwork(self):
291 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
292 66222813 Thomas Thrainer
                         nics=[{
293 11414807 Klaus Aehlig
                           constants.INIC_IP: "203.0.113.1",
294 66222813 Thomas Thrainer
                           constants.INIC_NETWORK: self.net.name
295 66222813 Thomas Thrainer
                         }])
296 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
297 66222813 Thomas Thrainer
      op, "IP address .* already in use or does not belong to network .*")
298 66222813 Thomas Thrainer
299 66222813 Thomas Thrainer
  def testMixAdoptAndNotAdopt(self):
300 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
301 66222813 Thomas Thrainer
                         disk_template=constants.DT_PLAIN,
302 66222813 Thomas Thrainer
                         disks=[{
303 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "lv1"
304 66222813 Thomas Thrainer
                         }, {}])
305 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
306 66222813 Thomas Thrainer
      op, "Either all disks are adopted or none is")
307 66222813 Thomas Thrainer
308 66222813 Thomas Thrainer
  def testMustAdoptWithoutAdopt(self):
309 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
310 66222813 Thomas Thrainer
                         disk_template=constants.DT_BLOCK,
311 66222813 Thomas Thrainer
                         disks=[{}])
312 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
313 66222813 Thomas Thrainer
      op, "Disk template blockdev requires disk adoption, but no 'adopt'"
314 66222813 Thomas Thrainer
          " parameter given")
315 66222813 Thomas Thrainer
316 66222813 Thomas Thrainer
  def testDontAdoptWithAdopt(self):
317 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
318 66222813 Thomas Thrainer
                         disk_template=constants.DT_DRBD8,
319 66222813 Thomas Thrainer
                         disks=[{
320 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "lv1"
321 66222813 Thomas Thrainer
                         }])
322 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
323 66222813 Thomas Thrainer
      op, "Disk adoption is not supported for the 'drbd' disk template")
324 66222813 Thomas Thrainer
325 66222813 Thomas Thrainer
  def testAdoptWithIAllocator(self):
326 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
327 66222813 Thomas Thrainer
                         disk_template=constants.DT_PLAIN,
328 66222813 Thomas Thrainer
                         disks=[{
329 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "lv1"
330 66222813 Thomas Thrainer
                         }],
331 66222813 Thomas Thrainer
                         iallocator="mock")
332 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
333 66222813 Thomas Thrainer
      op, "Disk adoption not allowed with an iallocator script")
334 66222813 Thomas Thrainer
335 66222813 Thomas Thrainer
  def testAdoptWithImport(self):
336 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
337 66222813 Thomas Thrainer
                         disk_template=constants.DT_PLAIN,
338 66222813 Thomas Thrainer
                         disks=[{
339 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "lv1"
340 66222813 Thomas Thrainer
                         }],
341 66222813 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT)
342 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
343 66222813 Thomas Thrainer
      op, "Disk adoption not allowed for instance import")
344 66222813 Thomas Thrainer
345 66222813 Thomas Thrainer
  def testArgumentCombinations(self):
346 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
347 66222813 Thomas Thrainer
                         # start flag will be flipped
348 66222813 Thomas Thrainer
                         no_install=True,
349 66222813 Thomas Thrainer
                         start=True,
350 66222813 Thomas Thrainer
                         # no allowed combination
351 66222813 Thomas Thrainer
                         ip_check=True,
352 66222813 Thomas Thrainer
                         name_check=False)
353 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
354 66222813 Thomas Thrainer
      op, "Cannot do IP address check without a name check")
355 66222813 Thomas Thrainer
356 66222813 Thomas Thrainer
  def testInvalidFileDriver(self):
357 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
358 66222813 Thomas Thrainer
                         file_driver="invalid_file_driver")
359 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
360 66222813 Thomas Thrainer
      op, "Parameter 'OP_INSTANCE_CREATE.file_driver' fails validation")
361 66222813 Thomas Thrainer
362 66222813 Thomas Thrainer
  def testMissingSecondaryNode(self):
363 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
364 66222813 Thomas Thrainer
                         pnode=self.master.name,
365 66222813 Thomas Thrainer
                         disk_template=constants.DT_DRBD8)
366 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
367 66222813 Thomas Thrainer
      op, "The networked disk templates need a mirror node")
368 66222813 Thomas Thrainer
369 66222813 Thomas Thrainer
  def testIgnoredSecondaryNode(self):
370 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
371 66222813 Thomas Thrainer
                         pnode=self.master.name,
372 66222813 Thomas Thrainer
                         snode=self.node1.name,
373 66222813 Thomas Thrainer
                         disk_template=constants.DT_PLAIN)
374 66222813 Thomas Thrainer
    try:
375 66222813 Thomas Thrainer
      self.ExecOpCode(op)
376 66222813 Thomas Thrainer
    except Exception:
377 66222813 Thomas Thrainer
      pass
378 66222813 Thomas Thrainer
    self.mcpu.assertLogContainsRegex(
379 66222813 Thomas Thrainer
      "Secondary node will be ignored on non-mirrored disk template")
380 66222813 Thomas Thrainer
381 66222813 Thomas Thrainer
  def testMissingOsType(self):
382 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
383 66222813 Thomas Thrainer
                         os_type=self.REMOVE)
384 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "No guest OS specified")
385 66222813 Thomas Thrainer
386 66222813 Thomas Thrainer
  def testBlacklistedOs(self):
387 66222813 Thomas Thrainer
    self.cluster.blacklisted_os = [self.os_name_variant]
388 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op)
389 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
390 66222813 Thomas Thrainer
      op, "Guest OS .* is not allowed for installation")
391 66222813 Thomas Thrainer
392 66222813 Thomas Thrainer
  def testMissingDiskTemplate(self):
393 66222813 Thomas Thrainer
    self.cluster.enabled_disk_templates = [constants.DT_DISKLESS]
394 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
395 66222813 Thomas Thrainer
                         disk_template=self.REMOVE)
396 66222813 Thomas Thrainer
    self.ExecOpCode(op)
397 66222813 Thomas Thrainer
398 66222813 Thomas Thrainer
  def testExistingInstance(self):
399 66222813 Thomas Thrainer
    inst = self.cfg.AddNewInstance()
400 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
401 66222813 Thomas Thrainer
                         instance_name=inst.name)
402 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
403 66222813 Thomas Thrainer
      op, "Instance .* is already in the cluster")
404 66222813 Thomas Thrainer
405 66222813 Thomas Thrainer
  def testPlainInstance(self):
406 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op)
407 66222813 Thomas Thrainer
    self.ExecOpCode(op)
408 66222813 Thomas Thrainer
409 66222813 Thomas Thrainer
  def testPlainIAllocator(self):
410 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
411 66222813 Thomas Thrainer
                         pnode=self.REMOVE,
412 66222813 Thomas Thrainer
                         iallocator="mock")
413 66222813 Thomas Thrainer
    self.ExecOpCode(op)
414 66222813 Thomas Thrainer
415 66222813 Thomas Thrainer
  def testIAllocatorOpportunisticLocking(self):
416 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
417 66222813 Thomas Thrainer
                         pnode=self.REMOVE,
418 66222813 Thomas Thrainer
                         iallocator="mock",
419 66222813 Thomas Thrainer
                         opportunistic_locking=True)
420 66222813 Thomas Thrainer
    self.ExecOpCode(op)
421 66222813 Thomas Thrainer
422 66222813 Thomas Thrainer
  def testFailingIAllocator(self):
423 66222813 Thomas Thrainer
    self.iallocator_cls.return_value.success = False
424 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
425 66222813 Thomas Thrainer
                         pnode=self.REMOVE,
426 66222813 Thomas Thrainer
                         iallocator="mock")
427 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
428 66222813 Thomas Thrainer
      op, "Can't compute nodes using iallocator")
429 66222813 Thomas Thrainer
430 66222813 Thomas Thrainer
  def testDrbdInstance(self):
431 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.drbd_op)
432 66222813 Thomas Thrainer
    self.ExecOpCode(op)
433 66222813 Thomas Thrainer
434 66222813 Thomas Thrainer
  def testDrbdIAllocator(self):
435 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.drbd_op,
436 66222813 Thomas Thrainer
                         pnode=self.REMOVE,
437 66222813 Thomas Thrainer
                         snode=self.REMOVE,
438 66222813 Thomas Thrainer
                         iallocator="mock")
439 66222813 Thomas Thrainer
    self.ExecOpCode(op)
440 66222813 Thomas Thrainer
441 66222813 Thomas Thrainer
  def testFileInstance(self):
442 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.file_op)
443 66222813 Thomas Thrainer
    self.ExecOpCode(op)
444 66222813 Thomas Thrainer
445 66222813 Thomas Thrainer
  def testFileInstanceNoClusterStorage(self):
446 66222813 Thomas Thrainer
    self.cluster.file_storage_dir = None
447 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.file_op)
448 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
449 ac156ecd Santi Raffa
      op, "Cluster file storage dir for 'file' storage type not defined")
450 66222813 Thomas Thrainer
451 66222813 Thomas Thrainer
  def testFileInstanceAdditionalPath(self):
452 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.file_op,
453 66222813 Thomas Thrainer
                         file_storage_dir="mock_dir")
454 66222813 Thomas Thrainer
    self.ExecOpCode(op)
455 66222813 Thomas Thrainer
456 66222813 Thomas Thrainer
  def testIdentifyDefaults(self):
457 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
458 66222813 Thomas Thrainer
                         hvparams={
459 66222813 Thomas Thrainer
                           constants.HV_BOOT_ORDER: "cd"
460 66222813 Thomas Thrainer
                         },
461 66222813 Thomas Thrainer
                         beparams=constants.BEC_DEFAULTS.copy(),
462 66222813 Thomas Thrainer
                         nics=[{
463 66222813 Thomas Thrainer
                           constants.NIC_MODE: constants.NIC_MODE_BRIDGED
464 66222813 Thomas Thrainer
                         }],
465 66222813 Thomas Thrainer
                         osparams={
466 66222813 Thomas Thrainer
                           self.os_name_variant: {}
467 66222813 Thomas Thrainer
                         },
468 66222813 Thomas Thrainer
                         identify_defaults=True)
469 66222813 Thomas Thrainer
    self.ExecOpCode(op)
470 66222813 Thomas Thrainer
471 66222813 Thomas Thrainer
    inst = self.cfg.GetAllInstancesInfo().values()[0]
472 66222813 Thomas Thrainer
    self.assertEqual(0, len(inst.hvparams))
473 66222813 Thomas Thrainer
    self.assertEqual(0, len(inst.beparams))
474 66222813 Thomas Thrainer
    assert self.os_name_variant not in inst.osparams or \
475 66222813 Thomas Thrainer
            len(inst.osparams[self.os_name_variant]) == 0
476 66222813 Thomas Thrainer
477 66222813 Thomas Thrainer
  def testOfflineNode(self):
478 66222813 Thomas Thrainer
    self.node1.offline = True
479 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
480 66222813 Thomas Thrainer
                         pnode=self.node1.name)
481 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Cannot use offline primary node")
482 66222813 Thomas Thrainer
483 66222813 Thomas Thrainer
  def testDrainedNode(self):
484 66222813 Thomas Thrainer
    self.node1.drained = True
485 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
486 66222813 Thomas Thrainer
                         pnode=self.node1.name)
487 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Cannot use drained primary node")
488 66222813 Thomas Thrainer
489 66222813 Thomas Thrainer
  def testNonVmCapableNode(self):
490 66222813 Thomas Thrainer
    self.node1.vm_capable = False
491 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
492 66222813 Thomas Thrainer
                         pnode=self.node1.name)
493 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
494 66222813 Thomas Thrainer
      op, "Cannot use non-vm_capable primary node")
495 66222813 Thomas Thrainer
496 66222813 Thomas Thrainer
  def testNonEnabledHypervisor(self):
497 66222813 Thomas Thrainer
    self.cluster.enabled_hypervisors = [constants.HT_XEN_HVM]
498 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
499 66222813 Thomas Thrainer
                         hypervisor=constants.HT_FAKE)
500 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
501 66222813 Thomas Thrainer
      op, "Selected hypervisor .* not enabled in the cluster")
502 66222813 Thomas Thrainer
503 66222813 Thomas Thrainer
  def testAddTag(self):
504 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
505 66222813 Thomas Thrainer
                         tags=["tag"])
506 66222813 Thomas Thrainer
    self.ExecOpCode(op)
507 66222813 Thomas Thrainer
508 66222813 Thomas Thrainer
  def testInvalidTag(self):
509 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op,
510 66222813 Thomas Thrainer
                         tags=["too_long" * 20])
511 66222813 Thomas Thrainer
    self.ExecOpCodeExpectException(op, errors.TagError, "Tag too long")
512 66222813 Thomas Thrainer
513 66222813 Thomas Thrainer
  def testPingableInstanceName(self):
514 66222813 Thomas Thrainer
    self.netutils_mod.TcpPing.return_value = True
515 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.diskless_op)
516 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
517 66222813 Thomas Thrainer
      op, "IP .* of instance diskless.test.com already in use")
518 66222813 Thomas Thrainer
519 66222813 Thomas Thrainer
  def testPrimaryIsSecondaryNode(self):
520 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.drbd_op,
521 66222813 Thomas Thrainer
                         snode=self.drbd_op.pnode)
522 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
523 66222813 Thomas Thrainer
      op, "The secondary node cannot be the primary node")
524 66222813 Thomas Thrainer
525 66222813 Thomas Thrainer
  def testPrimarySecondaryDifferentNodeGroups(self):
526 66222813 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
527 66222813 Thomas Thrainer
    self.node2.group = group.uuid
528 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.drbd_op)
529 66222813 Thomas Thrainer
    self.ExecOpCode(op)
530 66222813 Thomas Thrainer
    self.mcpu.assertLogContainsRegex(
531 66222813 Thomas Thrainer
      "The primary and secondary nodes are in two different node groups")
532 66222813 Thomas Thrainer
533 66222813 Thomas Thrainer
  def testExclusiveStorageUnsupportedDiskTemplate(self):
534 66222813 Thomas Thrainer
    self.node1.ndparams[constants.ND_EXCLUSIVE_STORAGE] = True
535 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.drbd_op)
536 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
537 66222813 Thomas Thrainer
      op, "Disk template drbd not supported with exclusive storage")
538 66222813 Thomas Thrainer
539 66222813 Thomas Thrainer
  def testAdoptPlain(self):
540 66222813 Thomas Thrainer
    self.rpc.call_lv_list.return_value = \
541 66222813 Thomas Thrainer
      self.RpcResultsBuilder() \
542 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.master, {
543 66222813 Thomas Thrainer
          "xenvg/mock_disk_1": (10000, None, False)
544 66222813 Thomas Thrainer
        }) \
545 66222813 Thomas Thrainer
        .Build()
546 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op)
547 66222813 Thomas Thrainer
    op.disks[0].update({constants.IDISK_ADOPT: "mock_disk_1"})
548 66222813 Thomas Thrainer
    self.ExecOpCode(op)
549 66222813 Thomas Thrainer
550 66222813 Thomas Thrainer
  def testAdoptPlainMissingLv(self):
551 66222813 Thomas Thrainer
    self.rpc.call_lv_list.return_value = \
552 66222813 Thomas Thrainer
      self.RpcResultsBuilder() \
553 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.master, {}) \
554 66222813 Thomas Thrainer
        .Build()
555 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op)
556 66222813 Thomas Thrainer
    op.disks[0].update({constants.IDISK_ADOPT: "mock_disk_1"})
557 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Missing logical volume")
558 66222813 Thomas Thrainer
559 66222813 Thomas Thrainer
  def testAdoptPlainOnlineLv(self):
560 66222813 Thomas Thrainer
    self.rpc.call_lv_list.return_value = \
561 66222813 Thomas Thrainer
      self.RpcResultsBuilder() \
562 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.master, {
563 66222813 Thomas Thrainer
          "xenvg/mock_disk_1": (10000, None, True)
564 66222813 Thomas Thrainer
        }) \
565 66222813 Thomas Thrainer
        .Build()
566 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op)
567 66222813 Thomas Thrainer
    op.disks[0].update({constants.IDISK_ADOPT: "mock_disk_1"})
568 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
569 66222813 Thomas Thrainer
      op, "Online logical volumes found, cannot adopt")
570 66222813 Thomas Thrainer
571 66222813 Thomas Thrainer
  def testAdoptBlock(self):
572 66222813 Thomas Thrainer
    self.rpc.call_bdev_sizes.return_value = \
573 66222813 Thomas Thrainer
      self.RpcResultsBuilder() \
574 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.master, {
575 66222813 Thomas Thrainer
          "/dev/disk/block0": 10000
576 66222813 Thomas Thrainer
        }) \
577 66222813 Thomas Thrainer
        .Build()
578 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.block_op)
579 66222813 Thomas Thrainer
    self.ExecOpCode(op)
580 66222813 Thomas Thrainer
581 66222813 Thomas Thrainer
  def testAdoptBlockDuplicateNames(self):
582 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.block_op,
583 66222813 Thomas Thrainer
                         disks=[{
584 66222813 Thomas Thrainer
                           constants.IDISK_SIZE: 0,
585 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "/dev/disk/block0"
586 66222813 Thomas Thrainer
                         }, {
587 66222813 Thomas Thrainer
                           constants.IDISK_SIZE: 0,
588 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "/dev/disk/block0"
589 66222813 Thomas Thrainer
                         }])
590 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
591 66222813 Thomas Thrainer
      op, "Duplicate disk names given for adoption")
592 66222813 Thomas Thrainer
593 66222813 Thomas Thrainer
  def testAdoptBlockInvalidNames(self):
594 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.block_op,
595 66222813 Thomas Thrainer
                         disks=[{
596 66222813 Thomas Thrainer
                           constants.IDISK_SIZE: 0,
597 66222813 Thomas Thrainer
                           constants.IDISK_ADOPT: "/invalid/block0"
598 66222813 Thomas Thrainer
                         }])
599 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
600 66222813 Thomas Thrainer
      op, "Device node.* lie outside .* and cannot be adopted")
601 66222813 Thomas Thrainer
602 66222813 Thomas Thrainer
  def testAdoptBlockMissingDisk(self):
603 66222813 Thomas Thrainer
    self.rpc.call_bdev_sizes.return_value = \
604 66222813 Thomas Thrainer
      self.RpcResultsBuilder() \
605 66222813 Thomas Thrainer
        .AddSuccessfulNode(self.master, {}) \
606 66222813 Thomas Thrainer
        .Build()
607 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.block_op)
608 66222813 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Missing block device")
609 66222813 Thomas Thrainer
610 66222813 Thomas Thrainer
  def testNoWaitForSyncDrbd(self):
611 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.drbd_op,
612 66222813 Thomas Thrainer
                         wait_for_sync=False)
613 66222813 Thomas Thrainer
    self.ExecOpCode(op)
614 66222813 Thomas Thrainer
615 66222813 Thomas Thrainer
  def testNoWaitForSyncPlain(self):
616 66222813 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
617 66222813 Thomas Thrainer
                         wait_for_sync=False)
618 66222813 Thomas Thrainer
    self.ExecOpCode(op)
619 66222813 Thomas Thrainer
620 72bac0c5 Thomas Thrainer
  def testImportPlainFromGivenSrcNode(self):
621 72bac0c5 Thomas Thrainer
    exp_info = """
622 72bac0c5 Thomas Thrainer
[export]
623 72bac0c5 Thomas Thrainer
version=0
624 72bac0c5 Thomas Thrainer
os=mock_os
625 72bac0c5 Thomas Thrainer
[instance]
626 72bac0c5 Thomas Thrainer
name=old_name.example.com
627 72bac0c5 Thomas Thrainer
"""
628 72bac0c5 Thomas Thrainer
629 72bac0c5 Thomas Thrainer
    self.rpc.call_export_info.return_value = \
630 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
631 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, exp_info)
632 72bac0c5 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
633 72bac0c5 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT,
634 72bac0c5 Thomas Thrainer
                         src_node=self.master.name)
635 72bac0c5 Thomas Thrainer
    self.ExecOpCode(op)
636 72bac0c5 Thomas Thrainer
637 72bac0c5 Thomas Thrainer
  def testImportPlainWithoutSrcNodeNotFound(self):
638 72bac0c5 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
639 72bac0c5 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT)
640 72bac0c5 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
641 72bac0c5 Thomas Thrainer
      op, "No export found for relative path")
642 72bac0c5 Thomas Thrainer
643 72bac0c5 Thomas Thrainer
  def testImportPlainWithoutSrcNode(self):
644 72bac0c5 Thomas Thrainer
    exp_info = """
645 72bac0c5 Thomas Thrainer
[export]
646 72bac0c5 Thomas Thrainer
version=0
647 72bac0c5 Thomas Thrainer
os=mock_os
648 72bac0c5 Thomas Thrainer
[instance]
649 72bac0c5 Thomas Thrainer
name=old_name.example.com
650 72bac0c5 Thomas Thrainer
"""
651 72bac0c5 Thomas Thrainer
652 72bac0c5 Thomas Thrainer
    self.rpc.call_export_list.return_value = \
653 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
654 72bac0c5 Thomas Thrainer
        .AddSuccessfulNode(self.master, {"mock_path": {}}) \
655 72bac0c5 Thomas Thrainer
        .Build()
656 72bac0c5 Thomas Thrainer
    self.rpc.call_export_info.return_value = \
657 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
658 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, exp_info)
659 72bac0c5 Thomas Thrainer
660 72bac0c5 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
661 72bac0c5 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT,
662 72bac0c5 Thomas Thrainer
                         src_path="mock_path")
663 72bac0c5 Thomas Thrainer
    self.ExecOpCode(op)
664 72bac0c5 Thomas Thrainer
665 72bac0c5 Thomas Thrainer
  def testImportPlainCorruptExportInfo(self):
666 72bac0c5 Thomas Thrainer
    exp_info = ""
667 72bac0c5 Thomas Thrainer
    self.rpc.call_export_info.return_value = \
668 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
669 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, exp_info)
670 72bac0c5 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
671 72bac0c5 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT,
672 72bac0c5 Thomas Thrainer
                         src_node=self.master.name)
673 72bac0c5 Thomas Thrainer
    self.ExecOpCodeExpectException(op, errors.ProgrammerError,
674 72bac0c5 Thomas Thrainer
                                   "Corrupted export config")
675 72bac0c5 Thomas Thrainer
676 72bac0c5 Thomas Thrainer
  def testImportPlainWrongExportInfoVersion(self):
677 72bac0c5 Thomas Thrainer
    exp_info = """
678 72bac0c5 Thomas Thrainer
[export]
679 72bac0c5 Thomas Thrainer
version=1
680 72bac0c5 Thomas Thrainer
"""
681 72bac0c5 Thomas Thrainer
    self.rpc.call_export_info.return_value = \
682 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
683 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, exp_info)
684 72bac0c5 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
685 72bac0c5 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT,
686 72bac0c5 Thomas Thrainer
                         src_node=self.master.name)
687 72bac0c5 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Wrong export version")
688 72bac0c5 Thomas Thrainer
689 72bac0c5 Thomas Thrainer
  def testImportPlainWithParametersAndImport(self):
690 72bac0c5 Thomas Thrainer
    exp_info = """
691 72bac0c5 Thomas Thrainer
[export]
692 72bac0c5 Thomas Thrainer
version=0
693 72bac0c5 Thomas Thrainer
os=mock_os
694 72bac0c5 Thomas Thrainer
[instance]
695 72bac0c5 Thomas Thrainer
name=old_name.example.com
696 72bac0c5 Thomas Thrainer
disk0_size=1024
697 72bac0c5 Thomas Thrainer
disk1_size=1500
698 72bac0c5 Thomas Thrainer
disk1_dump=mock_path
699 72bac0c5 Thomas Thrainer
nic0_mode=bridged
700 72bac0c5 Thomas Thrainer
nic0_link=br_mock
701 72bac0c5 Thomas Thrainer
nic0_mac=f6:ab:f4:45:d1:af
702 4256f8fe Sebastian Gebhard
nic0_ip=192.0.2.1
703 72bac0c5 Thomas Thrainer
tags=tag1 tag2
704 72bac0c5 Thomas Thrainer
hypervisor=xen-hvm
705 72bac0c5 Thomas Thrainer
[hypervisor]
706 72bac0c5 Thomas Thrainer
boot_order=cd
707 72bac0c5 Thomas Thrainer
[backend]
708 72bac0c5 Thomas Thrainer
memory=1024
709 72bac0c5 Thomas Thrainer
vcpus=8
710 72bac0c5 Thomas Thrainer
[os]
711 72bac0c5 Thomas Thrainer
param1=val1
712 72bac0c5 Thomas Thrainer
"""
713 72bac0c5 Thomas Thrainer
714 72bac0c5 Thomas Thrainer
    self.rpc.call_export_info.return_value = \
715 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
716 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, exp_info)
717 72bac0c5 Thomas Thrainer
    self.rpc.call_import_start.return_value = \
718 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
719 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, "daemon_name")
720 72bac0c5 Thomas Thrainer
    self.rpc.call_impexp_status.return_value = \
721 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
722 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master,
723 72bac0c5 Thomas Thrainer
                                    [
724 72bac0c5 Thomas Thrainer
                                      objects.ImportExportStatus(exit_status=0)
725 72bac0c5 Thomas Thrainer
                                    ])
726 72bac0c5 Thomas Thrainer
    self.rpc.call_impexp_cleanup.return_value = \
727 72bac0c5 Thomas Thrainer
      self.RpcResultsBuilder() \
728 72bac0c5 Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, True)
729 72bac0c5 Thomas Thrainer
730 72bac0c5 Thomas Thrainer
    op = self.CopyOpCode(self.plain_op,
731 72bac0c5 Thomas Thrainer
                         disks=[],
732 72bac0c5 Thomas Thrainer
                         nics=[],
733 72bac0c5 Thomas Thrainer
                         tags=[],
734 72bac0c5 Thomas Thrainer
                         hypervisor=None,
735 72bac0c5 Thomas Thrainer
                         hvparams={},
736 72bac0c5 Thomas Thrainer
                         mode=constants.INSTANCE_IMPORT,
737 72bac0c5 Thomas Thrainer
                         src_node=self.master.name)
738 72bac0c5 Thomas Thrainer
    self.ExecOpCode(op)
739 72bac0c5 Thomas Thrainer
740 72bac0c5 Thomas Thrainer
741 66222813 Thomas Thrainer
class TestCheckOSVariant(CmdlibTestCase):
742 66222813 Thomas Thrainer
  def testNoVariantsSupported(self):
743 66222813 Thomas Thrainer
    os = self.cfg.CreateOs(supported_variants=[])
744 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, instance._CheckOSVariant,
745 66222813 Thomas Thrainer
                      os, "os+variant")
746 66222813 Thomas Thrainer
747 66222813 Thomas Thrainer
  def testNoVariantGiven(self):
748 66222813 Thomas Thrainer
    os = self.cfg.CreateOs(supported_variants=["default"])
749 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, instance._CheckOSVariant,
750 66222813 Thomas Thrainer
                      os, "os")
751 66222813 Thomas Thrainer
752 66222813 Thomas Thrainer
  def testWrongVariantGiven(self):
753 66222813 Thomas Thrainer
    os = self.cfg.CreateOs(supported_variants=["default"])
754 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, instance._CheckOSVariant,
755 66222813 Thomas Thrainer
                      os, "os+wrong_variant")
756 66222813 Thomas Thrainer
757 66222813 Thomas Thrainer
  def testOkWithVariant(self):
758 66222813 Thomas Thrainer
    os = self.cfg.CreateOs(supported_variants=["default"])
759 66222813 Thomas Thrainer
    instance._CheckOSVariant(os, "os+default")
760 66222813 Thomas Thrainer
761 66222813 Thomas Thrainer
  def testOkWithoutVariant(self):
762 66222813 Thomas Thrainer
    os = self.cfg.CreateOs(supported_variants=[])
763 66222813 Thomas Thrainer
    instance._CheckOSVariant(os, "os")
764 66222813 Thomas Thrainer
765 66222813 Thomas Thrainer
766 66222813 Thomas Thrainer
class TestCheckTargetNodeIPolicy(TestLUInstanceCreate):
767 66222813 Thomas Thrainer
  def setUp(self):
768 66222813 Thomas Thrainer
    super(TestCheckTargetNodeIPolicy, self).setUp()
769 66222813 Thomas Thrainer
770 66222813 Thomas Thrainer
    self.op = self.diskless_op
771 66222813 Thomas Thrainer
772 66222813 Thomas Thrainer
    self.instance = self.cfg.AddNewInstance()
773 66222813 Thomas Thrainer
    self.target_group = self.cfg.AddNewNodeGroup()
774 66222813 Thomas Thrainer
    self.target_node = self.cfg.AddNewNode(group=self.target_group)
775 66222813 Thomas Thrainer
776 66222813 Thomas Thrainer
  @withLockedLU
777 66222813 Thomas Thrainer
  def testNoViolation(self, lu):
778 66222813 Thomas Thrainer
    compute_recoder = mock.Mock(return_value=[])
779 66222813 Thomas Thrainer
    instance.CheckTargetNodeIPolicy(lu, NotImplemented, self.instance,
780 66222813 Thomas Thrainer
                                    self.target_node, NotImplemented,
781 66222813 Thomas Thrainer
                                    _compute_fn=compute_recoder)
782 66222813 Thomas Thrainer
    self.assertTrue(compute_recoder.called)
783 66222813 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
784 66222813 Thomas Thrainer
785 66222813 Thomas Thrainer
  @withLockedLU
786 66222813 Thomas Thrainer
  def testNoIgnore(self, lu):
787 66222813 Thomas Thrainer
    compute_recoder = mock.Mock(return_value=["mem_size not in range"])
788 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, instance.CheckTargetNodeIPolicy,
789 66222813 Thomas Thrainer
                      lu, NotImplemented, self.instance,
790 66222813 Thomas Thrainer
                      self.target_node, NotImplemented,
791 66222813 Thomas Thrainer
                      _compute_fn=compute_recoder)
792 66222813 Thomas Thrainer
    self.assertTrue(compute_recoder.called)
793 66222813 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
794 66222813 Thomas Thrainer
795 66222813 Thomas Thrainer
  @withLockedLU
796 66222813 Thomas Thrainer
  def testIgnoreViolation(self, lu):
797 66222813 Thomas Thrainer
    compute_recoder = mock.Mock(return_value=["mem_size not in range"])
798 66222813 Thomas Thrainer
    instance.CheckTargetNodeIPolicy(lu, NotImplemented, self.instance,
799 66222813 Thomas Thrainer
                                    self.target_node, NotImplemented,
800 66222813 Thomas Thrainer
                                    ignore=True, _compute_fn=compute_recoder)
801 66222813 Thomas Thrainer
    self.assertTrue(compute_recoder.called)
802 66222813 Thomas Thrainer
    msg = ("Instance does not meet target node group's .* instance policy:"
803 66222813 Thomas Thrainer
           " mem_size not in range")
804 66222813 Thomas Thrainer
    self.mcpu.assertLogContainsRegex(msg)
805 66222813 Thomas Thrainer
806 66222813 Thomas Thrainer
807 66222813 Thomas Thrainer
class TestApplyContainerMods(unittest.TestCase):
808 66222813 Thomas Thrainer
  def testEmptyContainer(self):
809 66222813 Thomas Thrainer
    container = []
810 66222813 Thomas Thrainer
    chgdesc = []
811 66222813 Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, [], None, None,
812 66222813 Thomas Thrainer
                                 None)
813 66222813 Thomas Thrainer
    self.assertEqual(container, [])
814 66222813 Thomas Thrainer
    self.assertEqual(chgdesc, [])
815 66222813 Thomas Thrainer
816 66222813 Thomas Thrainer
  def testAdd(self):
817 66222813 Thomas Thrainer
    container = []
818 66222813 Thomas Thrainer
    chgdesc = []
819 66222813 Thomas Thrainer
    mods = instance._PrepareContainerMods([
820 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "Hello"),
821 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "World"),
822 66222813 Thomas Thrainer
      (constants.DDM_ADD, 0, "Start"),
823 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "End"),
824 66222813 Thomas Thrainer
      ], None)
825 66222813 Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
826 66222813 Thomas Thrainer
                                 None, None, None)
827 66222813 Thomas Thrainer
    self.assertEqual(container, ["Start", "Hello", "World", "End"])
828 66222813 Thomas Thrainer
    self.assertEqual(chgdesc, [])
829 66222813 Thomas Thrainer
830 66222813 Thomas Thrainer
    mods = instance._PrepareContainerMods([
831 66222813 Thomas Thrainer
      (constants.DDM_ADD, 0, "zero"),
832 66222813 Thomas Thrainer
      (constants.DDM_ADD, 3, "Added"),
833 66222813 Thomas Thrainer
      (constants.DDM_ADD, 5, "four"),
834 66222813 Thomas Thrainer
      (constants.DDM_ADD, 7, "xyz"),
835 66222813 Thomas Thrainer
      ], None)
836 66222813 Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
837 66222813 Thomas Thrainer
                                 None, None, None)
838 66222813 Thomas Thrainer
    self.assertEqual(container,
839 66222813 Thomas Thrainer
                     ["zero", "Start", "Hello", "Added", "World", "four",
840 66222813 Thomas Thrainer
                      "End", "xyz"])
841 66222813 Thomas Thrainer
    self.assertEqual(chgdesc, [])
842 66222813 Thomas Thrainer
843 66222813 Thomas Thrainer
    for idx in [-2, len(container) + 1]:
844 66222813 Thomas Thrainer
      mods = instance._PrepareContainerMods([
845 66222813 Thomas Thrainer
        (constants.DDM_ADD, idx, "error"),
846 66222813 Thomas Thrainer
        ], None)
847 66222813 Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
848 66222813 Thomas Thrainer
                        "test", container, None, mods, None, None, None)
849 66222813 Thomas Thrainer
850 66222813 Thomas Thrainer
  def testRemoveError(self):
851 66222813 Thomas Thrainer
    for idx in [0, 1, 2, 100, -1, -4]:
852 66222813 Thomas Thrainer
      mods = instance._PrepareContainerMods([
853 66222813 Thomas Thrainer
        (constants.DDM_REMOVE, idx, None),
854 66222813 Thomas Thrainer
        ], None)
855 66222813 Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
856 66222813 Thomas Thrainer
                        "test", [], None, mods, None, None, None)
857 66222813 Thomas Thrainer
858 66222813 Thomas Thrainer
    mods = instance._PrepareContainerMods([
859 66222813 Thomas Thrainer
      (constants.DDM_REMOVE, 0, object()),
860 66222813 Thomas Thrainer
      ], None)
861 66222813 Thomas Thrainer
    self.assertRaises(AssertionError, instance._ApplyContainerMods,
862 66222813 Thomas Thrainer
                      "test", [""], None, mods, None, None, None)
863 66222813 Thomas Thrainer
864 66222813 Thomas Thrainer
  def testAddError(self):
865 66222813 Thomas Thrainer
    for idx in range(-100, -1) + [100]:
866 66222813 Thomas Thrainer
      mods = instance._PrepareContainerMods([
867 66222813 Thomas Thrainer
        (constants.DDM_ADD, idx, None),
868 66222813 Thomas Thrainer
        ], None)
869 66222813 Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
870 66222813 Thomas Thrainer
                        "test", [], None, mods, None, None, None)
871 66222813 Thomas Thrainer
872 66222813 Thomas Thrainer
  def testRemove(self):
873 66222813 Thomas Thrainer
    container = ["item 1", "item 2"]
874 66222813 Thomas Thrainer
    mods = instance._PrepareContainerMods([
875 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "aaa"),
876 66222813 Thomas Thrainer
      (constants.DDM_REMOVE, -1, None),
877 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "bbb"),
878 66222813 Thomas Thrainer
      ], None)
879 66222813 Thomas Thrainer
    chgdesc = []
880 66222813 Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
881 66222813 Thomas Thrainer
                                 None, None, None)
882 66222813 Thomas Thrainer
    self.assertEqual(container, ["item 1", "item 2", "bbb"])
883 66222813 Thomas Thrainer
    self.assertEqual(chgdesc, [
884 66222813 Thomas Thrainer
      ("test/2", "remove"),
885 66222813 Thomas Thrainer
      ])
886 66222813 Thomas Thrainer
887 66222813 Thomas Thrainer
  def testModify(self):
888 66222813 Thomas Thrainer
    container = ["item 1", "item 2"]
889 66222813 Thomas Thrainer
    mods = instance._PrepareContainerMods([
890 66222813 Thomas Thrainer
      (constants.DDM_MODIFY, -1, "a"),
891 66222813 Thomas Thrainer
      (constants.DDM_MODIFY, 0, "b"),
892 66222813 Thomas Thrainer
      (constants.DDM_MODIFY, 1, "c"),
893 66222813 Thomas Thrainer
      ], None)
894 66222813 Thomas Thrainer
    chgdesc = []
895 66222813 Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
896 66222813 Thomas Thrainer
                                 None, None, None)
897 66222813 Thomas Thrainer
    self.assertEqual(container, ["item 1", "item 2"])
898 66222813 Thomas Thrainer
    self.assertEqual(chgdesc, [])
899 66222813 Thomas Thrainer
900 66222813 Thomas Thrainer
    for idx in [-2, len(container) + 1]:
901 66222813 Thomas Thrainer
      mods = instance._PrepareContainerMods([
902 66222813 Thomas Thrainer
        (constants.DDM_MODIFY, idx, "error"),
903 66222813 Thomas Thrainer
        ], None)
904 66222813 Thomas Thrainer
      self.assertRaises(IndexError, instance._ApplyContainerMods,
905 66222813 Thomas Thrainer
                        "test", container, None, mods, None, None, None)
906 66222813 Thomas Thrainer
907 66222813 Thomas Thrainer
  @staticmethod
908 66222813 Thomas Thrainer
  def _CreateTestFn(idx, params, private):
909 66222813 Thomas Thrainer
    private.data = ("add", idx, params)
910 66222813 Thomas Thrainer
    return ((100 * idx, params), [
911 66222813 Thomas Thrainer
      ("test/%s" % idx, hex(idx)),
912 66222813 Thomas Thrainer
      ])
913 66222813 Thomas Thrainer
914 66222813 Thomas Thrainer
  @staticmethod
915 66222813 Thomas Thrainer
  def _ModifyTestFn(idx, item, params, private):
916 66222813 Thomas Thrainer
    private.data = ("modify", idx, params)
917 66222813 Thomas Thrainer
    return [
918 66222813 Thomas Thrainer
      ("test/%s" % idx, "modify %s" % params),
919 66222813 Thomas Thrainer
      ]
920 66222813 Thomas Thrainer
921 66222813 Thomas Thrainer
  @staticmethod
922 66222813 Thomas Thrainer
  def _RemoveTestFn(idx, item, private):
923 66222813 Thomas Thrainer
    private.data = ("remove", idx, item)
924 66222813 Thomas Thrainer
925 66222813 Thomas Thrainer
  def testAddWithCreateFunction(self):
926 66222813 Thomas Thrainer
    container = []
927 66222813 Thomas Thrainer
    chgdesc = []
928 66222813 Thomas Thrainer
    mods = instance._PrepareContainerMods([
929 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "Hello"),
930 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "World"),
931 66222813 Thomas Thrainer
      (constants.DDM_ADD, 0, "Start"),
932 66222813 Thomas Thrainer
      (constants.DDM_ADD, -1, "End"),
933 66222813 Thomas Thrainer
      (constants.DDM_REMOVE, 2, None),
934 66222813 Thomas Thrainer
      (constants.DDM_MODIFY, -1, "foobar"),
935 66222813 Thomas Thrainer
      (constants.DDM_REMOVE, 2, None),
936 66222813 Thomas Thrainer
      (constants.DDM_ADD, 1, "More"),
937 66222813 Thomas Thrainer
      ], mock.Mock)
938 66222813 Thomas Thrainer
    instance._ApplyContainerMods("test", container, chgdesc, mods,
939 66222813 Thomas Thrainer
                                 self._CreateTestFn, self._ModifyTestFn,
940 66222813 Thomas Thrainer
                                 self._RemoveTestFn)
941 66222813 Thomas Thrainer
    self.assertEqual(container, [
942 66222813 Thomas Thrainer
      (000, "Start"),
943 66222813 Thomas Thrainer
      (100, "More"),
944 66222813 Thomas Thrainer
      (000, "Hello"),
945 66222813 Thomas Thrainer
      ])
946 66222813 Thomas Thrainer
    self.assertEqual(chgdesc, [
947 66222813 Thomas Thrainer
      ("test/0", "0x0"),
948 66222813 Thomas Thrainer
      ("test/1", "0x1"),
949 66222813 Thomas Thrainer
      ("test/0", "0x0"),
950 66222813 Thomas Thrainer
      ("test/3", "0x3"),
951 66222813 Thomas Thrainer
      ("test/2", "remove"),
952 66222813 Thomas Thrainer
      ("test/2", "modify foobar"),
953 66222813 Thomas Thrainer
      ("test/2", "remove"),
954 66222813 Thomas Thrainer
      ("test/1", "0x1")
955 66222813 Thomas Thrainer
      ])
956 66222813 Thomas Thrainer
    self.assertTrue(compat.all(op == private.data[0]
957 66222813 Thomas Thrainer
                               for (op, _, _, private) in mods))
958 66222813 Thomas Thrainer
    self.assertEqual([private.data for (op, _, _, private) in mods], [
959 66222813 Thomas Thrainer
      ("add", 0, "Hello"),
960 66222813 Thomas Thrainer
      ("add", 1, "World"),
961 66222813 Thomas Thrainer
      ("add", 0, "Start"),
962 66222813 Thomas Thrainer
      ("add", 3, "End"),
963 66222813 Thomas Thrainer
      ("remove", 2, (100, "World")),
964 66222813 Thomas Thrainer
      ("modify", 2, "foobar"),
965 66222813 Thomas Thrainer
      ("remove", 2, (300, "End")),
966 66222813 Thomas Thrainer
      ("add", 1, "More"),
967 66222813 Thomas Thrainer
      ])
968 66222813 Thomas Thrainer
969 66222813 Thomas Thrainer
970 66222813 Thomas Thrainer
class _FakeConfigForGenDiskTemplate(ConfigMock):
971 66222813 Thomas Thrainer
  def __init__(self):
972 66222813 Thomas Thrainer
    super(_FakeConfigForGenDiskTemplate, self).__init__()
973 66222813 Thomas Thrainer
974 66222813 Thomas Thrainer
    self._unique_id = itertools.count()
975 66222813 Thomas Thrainer
    self._drbd_minor = itertools.count(20)
976 66222813 Thomas Thrainer
    self._port = itertools.count(constants.FIRST_DRBD_PORT)
977 66222813 Thomas Thrainer
    self._secret = itertools.count()
978 66222813 Thomas Thrainer
979 66222813 Thomas Thrainer
  def GenerateUniqueID(self, ec_id):
980 66222813 Thomas Thrainer
    return "ec%s-uq%s" % (ec_id, self._unique_id.next())
981 66222813 Thomas Thrainer
982 66222813 Thomas Thrainer
  def AllocateDRBDMinor(self, nodes, instance):
983 66222813 Thomas Thrainer
    return [self._drbd_minor.next()
984 66222813 Thomas Thrainer
            for _ in nodes]
985 66222813 Thomas Thrainer
986 66222813 Thomas Thrainer
  def AllocatePort(self):
987 66222813 Thomas Thrainer
    return self._port.next()
988 66222813 Thomas Thrainer
989 66222813 Thomas Thrainer
  def GenerateDRBDSecret(self, ec_id):
990 66222813 Thomas Thrainer
    return "ec%s-secret%s" % (ec_id, self._secret.next())
991 66222813 Thomas Thrainer
992 66222813 Thomas Thrainer
993 66222813 Thomas Thrainer
class TestGenerateDiskTemplate(CmdlibTestCase):
994 66222813 Thomas Thrainer
  def setUp(self):
995 66222813 Thomas Thrainer
    super(TestGenerateDiskTemplate, self).setUp()
996 66222813 Thomas Thrainer
997 66222813 Thomas Thrainer
    self.cfg = _FakeConfigForGenDiskTemplate()
998 66222813 Thomas Thrainer
    self.cluster.enabled_disk_templates = list(constants.DISK_TEMPLATES)
999 66222813 Thomas Thrainer
1000 66222813 Thomas Thrainer
    self.nodegroup = self.cfg.AddNewNodeGroup(name="ng")
1001 66222813 Thomas Thrainer
1002 57da0458 Thomas Thrainer
    self.lu = self.GetMockLU()
1003 66222813 Thomas Thrainer
1004 66222813 Thomas Thrainer
  @staticmethod
1005 66222813 Thomas Thrainer
  def GetDiskParams():
1006 66222813 Thomas Thrainer
    return copy.deepcopy(constants.DISK_DT_DEFAULTS)
1007 66222813 Thomas Thrainer
1008 66222813 Thomas Thrainer
  def testWrongDiskTemplate(self):
1009 66222813 Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1010 66222813 Thomas Thrainer
    disk_template = "##unknown##"
1011 66222813 Thomas Thrainer
1012 66222813 Thomas Thrainer
    assert disk_template not in constants.DISK_TEMPLATES
1013 66222813 Thomas Thrainer
1014 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, gdt, self.lu, disk_template,
1015 66222813 Thomas Thrainer
                      "inst26831.example.com", "node30113.example.com", [], [],
1016 66222813 Thomas Thrainer
                      NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1017 66222813 Thomas Thrainer
                      self.GetDiskParams())
1018 66222813 Thomas Thrainer
1019 66222813 Thomas Thrainer
  def testDiskless(self):
1020 66222813 Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1021 66222813 Thomas Thrainer
1022 66222813 Thomas Thrainer
    result = gdt(self.lu, constants.DT_DISKLESS, "inst27734.example.com",
1023 66222813 Thomas Thrainer
                 "node30113.example.com", [], [],
1024 66222813 Thomas Thrainer
                 NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1025 66222813 Thomas Thrainer
                 self.GetDiskParams())
1026 66222813 Thomas Thrainer
    self.assertEqual(result, [])
1027 66222813 Thomas Thrainer
1028 66222813 Thomas Thrainer
  def _TestTrivialDisk(self, template, disk_info, base_index, exp_dev_type,
1029 66222813 Thomas Thrainer
                       file_storage_dir=NotImplemented,
1030 66222813 Thomas Thrainer
                       file_driver=NotImplemented):
1031 66222813 Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1032 66222813 Thomas Thrainer
1033 66222813 Thomas Thrainer
    map(lambda params: utils.ForceDictType(params,
1034 66222813 Thomas Thrainer
                                           constants.IDISK_PARAMS_TYPES),
1035 66222813 Thomas Thrainer
        disk_info)
1036 66222813 Thomas Thrainer
1037 66222813 Thomas Thrainer
    # Check if non-empty list of secondaries is rejected
1038 66222813 Thomas Thrainer
    self.assertRaises(errors.ProgrammerError, gdt, self.lu,
1039 66222813 Thomas Thrainer
                      template, "inst25088.example.com",
1040 66222813 Thomas Thrainer
                      "node185.example.com", ["node323.example.com"], [],
1041 66222813 Thomas Thrainer
                      NotImplemented, NotImplemented, base_index,
1042 66222813 Thomas Thrainer
                      self.lu.LogInfo, self.GetDiskParams())
1043 66222813 Thomas Thrainer
1044 66222813 Thomas Thrainer
    result = gdt(self.lu, template, "inst21662.example.com",
1045 66222813 Thomas Thrainer
                 "node21741.example.com", [],
1046 66222813 Thomas Thrainer
                 disk_info, file_storage_dir, file_driver, base_index,
1047 66222813 Thomas Thrainer
                 self.lu.LogInfo, self.GetDiskParams())
1048 66222813 Thomas Thrainer
1049 66222813 Thomas Thrainer
    for (idx, disk) in enumerate(result):
1050 66222813 Thomas Thrainer
      self.assertTrue(isinstance(disk, objects.Disk))
1051 66222813 Thomas Thrainer
      self.assertEqual(disk.dev_type, exp_dev_type)
1052 66222813 Thomas Thrainer
      self.assertEqual(disk.size, disk_info[idx][constants.IDISK_SIZE])
1053 66222813 Thomas Thrainer
      self.assertEqual(disk.mode, disk_info[idx][constants.IDISK_MODE])
1054 66222813 Thomas Thrainer
      self.assertTrue(disk.children is None)
1055 66222813 Thomas Thrainer
1056 66222813 Thomas Thrainer
    self._CheckIvNames(result, base_index, base_index + len(disk_info))
1057 66222813 Thomas Thrainer
    instance._UpdateIvNames(base_index, result)
1058 66222813 Thomas Thrainer
    self._CheckIvNames(result, base_index, base_index + len(disk_info))
1059 66222813 Thomas Thrainer
1060 66222813 Thomas Thrainer
    return result
1061 66222813 Thomas Thrainer
1062 66222813 Thomas Thrainer
  def _CheckIvNames(self, disks, base_index, end_index):
1063 66222813 Thomas Thrainer
    self.assertEqual(map(operator.attrgetter("iv_name"), disks),
1064 66222813 Thomas Thrainer
                     ["disk/%s" % i for i in range(base_index, end_index)])
1065 66222813 Thomas Thrainer
1066 66222813 Thomas Thrainer
  def testPlain(self):
1067 66222813 Thomas Thrainer
    disk_info = [{
1068 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 1024,
1069 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDWR,
1070 66222813 Thomas Thrainer
      }, {
1071 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 4096,
1072 66222813 Thomas Thrainer
      constants.IDISK_VG: "othervg",
1073 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDWR,
1074 66222813 Thomas Thrainer
      }]
1075 66222813 Thomas Thrainer
1076 66222813 Thomas Thrainer
    result = self._TestTrivialDisk(constants.DT_PLAIN, disk_info, 3,
1077 0c5f1b13 Thomas Thrainer
                                   constants.DT_PLAIN)
1078 66222813 Thomas Thrainer
1079 66222813 Thomas Thrainer
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1080 66222813 Thomas Thrainer
      ("xenvg", "ec1-uq0.disk3"),
1081 66222813 Thomas Thrainer
      ("othervg", "ec1-uq1.disk4"),
1082 66222813 Thomas Thrainer
      ])
1083 66222813 Thomas Thrainer
1084 66222813 Thomas Thrainer
  def testFile(self):
1085 66222813 Thomas Thrainer
    # anything != DT_FILE would do here
1086 66222813 Thomas Thrainer
    self.cluster.enabled_disk_templates = [constants.DT_PLAIN]
1087 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, self._TestTrivialDisk,
1088 66222813 Thomas Thrainer
                      constants.DT_FILE, [], 0, NotImplemented)
1089 66222813 Thomas Thrainer
    self.assertRaises(errors.OpPrereqError, self._TestTrivialDisk,
1090 66222813 Thomas Thrainer
                      constants.DT_SHARED_FILE, [], 0, NotImplemented)
1091 66222813 Thomas Thrainer
1092 a09639d1 Santi Raffa
    for disk_template in constants.DTS_FILEBASED:
1093 66222813 Thomas Thrainer
      disk_info = [{
1094 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 80 * 1024,
1095 66222813 Thomas Thrainer
        constants.IDISK_MODE: constants.DISK_RDONLY,
1096 66222813 Thomas Thrainer
        }, {
1097 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 4096,
1098 66222813 Thomas Thrainer
        constants.IDISK_MODE: constants.DISK_RDWR,
1099 66222813 Thomas Thrainer
        }, {
1100 66222813 Thomas Thrainer
        constants.IDISK_SIZE: 6 * 1024,
1101 66222813 Thomas Thrainer
        constants.IDISK_MODE: constants.DISK_RDWR,
1102 66222813 Thomas Thrainer
        }]
1103 66222813 Thomas Thrainer
1104 66222813 Thomas Thrainer
      self.cluster.enabled_disk_templates = [disk_template]
1105 66222813 Thomas Thrainer
      result = self._TestTrivialDisk(
1106 0c5f1b13 Thomas Thrainer
        disk_template, disk_info, 2, disk_template,
1107 66222813 Thomas Thrainer
        file_storage_dir="/tmp", file_driver=constants.FD_BLKTAP)
1108 66222813 Thomas Thrainer
1109 66222813 Thomas Thrainer
      self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1110 66222813 Thomas Thrainer
        (constants.FD_BLKTAP, "/tmp/disk2"),
1111 66222813 Thomas Thrainer
        (constants.FD_BLKTAP, "/tmp/disk3"),
1112 66222813 Thomas Thrainer
        (constants.FD_BLKTAP, "/tmp/disk4"),
1113 66222813 Thomas Thrainer
        ])
1114 66222813 Thomas Thrainer
1115 66222813 Thomas Thrainer
  def testBlock(self):
1116 66222813 Thomas Thrainer
    disk_info = [{
1117 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 8 * 1024,
1118 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDWR,
1119 66222813 Thomas Thrainer
      constants.IDISK_ADOPT: "/tmp/some/block/dev",
1120 66222813 Thomas Thrainer
      }]
1121 66222813 Thomas Thrainer
1122 66222813 Thomas Thrainer
    result = self._TestTrivialDisk(constants.DT_BLOCK, disk_info, 10,
1123 0c5f1b13 Thomas Thrainer
                                   constants.DT_BLOCK)
1124 66222813 Thomas Thrainer
1125 66222813 Thomas Thrainer
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1126 66222813 Thomas Thrainer
      (constants.BLOCKDEV_DRIVER_MANUAL, "/tmp/some/block/dev"),
1127 66222813 Thomas Thrainer
      ])
1128 66222813 Thomas Thrainer
1129 66222813 Thomas Thrainer
  def testRbd(self):
1130 66222813 Thomas Thrainer
    disk_info = [{
1131 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 8 * 1024,
1132 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDONLY,
1133 66222813 Thomas Thrainer
      }, {
1134 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 100 * 1024,
1135 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDWR,
1136 66222813 Thomas Thrainer
      }]
1137 66222813 Thomas Thrainer
1138 66222813 Thomas Thrainer
    result = self._TestTrivialDisk(constants.DT_RBD, disk_info, 0,
1139 0c5f1b13 Thomas Thrainer
                                   constants.DT_RBD)
1140 66222813 Thomas Thrainer
1141 66222813 Thomas Thrainer
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1142 66222813 Thomas Thrainer
      ("rbd", "ec1-uq0.rbd.disk0"),
1143 66222813 Thomas Thrainer
      ("rbd", "ec1-uq1.rbd.disk1"),
1144 66222813 Thomas Thrainer
      ])
1145 66222813 Thomas Thrainer
1146 66222813 Thomas Thrainer
  def testDrbd8(self):
1147 66222813 Thomas Thrainer
    gdt = instance.GenerateDiskTemplate
1148 0c5f1b13 Thomas Thrainer
    drbd8_defaults = constants.DISK_LD_DEFAULTS[constants.DT_DRBD8]
1149 66222813 Thomas Thrainer
    drbd8_default_metavg = drbd8_defaults[constants.LDP_DEFAULT_METAVG]
1150 66222813 Thomas Thrainer
1151 66222813 Thomas Thrainer
    disk_info = [{
1152 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 1024,
1153 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDWR,
1154 66222813 Thomas Thrainer
      }, {
1155 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 100 * 1024,
1156 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDONLY,
1157 66222813 Thomas Thrainer
      constants.IDISK_METAVG: "metavg",
1158 66222813 Thomas Thrainer
      }, {
1159 66222813 Thomas Thrainer
      constants.IDISK_SIZE: 4096,
1160 66222813 Thomas Thrainer
      constants.IDISK_MODE: constants.DISK_RDWR,
1161 66222813 Thomas Thrainer
      constants.IDISK_VG: "vgxyz",
1162 66222813 Thomas Thrainer
      },
1163 66222813 Thomas Thrainer
      ]
1164 66222813 Thomas Thrainer
1165 66222813 Thomas Thrainer
    exp_logical_ids = [
1166 66222813 Thomas Thrainer
      [
1167 66222813 Thomas Thrainer
        (self.lu.cfg.GetVGName(), "ec1-uq0.disk0_data"),
1168 66222813 Thomas Thrainer
        (drbd8_default_metavg, "ec1-uq0.disk0_meta"),
1169 66222813 Thomas Thrainer
      ], [
1170 66222813 Thomas Thrainer
        (self.lu.cfg.GetVGName(), "ec1-uq1.disk1_data"),
1171 66222813 Thomas Thrainer
        ("metavg", "ec1-uq1.disk1_meta"),
1172 66222813 Thomas Thrainer
      ], [
1173 66222813 Thomas Thrainer
        ("vgxyz", "ec1-uq2.disk2_data"),
1174 66222813 Thomas Thrainer
        (drbd8_default_metavg, "ec1-uq2.disk2_meta"),
1175 66222813 Thomas Thrainer
      ]]
1176 66222813 Thomas Thrainer
1177 66222813 Thomas Thrainer
    assert len(exp_logical_ids) == len(disk_info)
1178 66222813 Thomas Thrainer
1179 66222813 Thomas Thrainer
    map(lambda params: utils.ForceDictType(params,
1180 66222813 Thomas Thrainer
                                           constants.IDISK_PARAMS_TYPES),
1181 66222813 Thomas Thrainer
        disk_info)
1182 66222813 Thomas Thrainer
1183 66222813 Thomas Thrainer
    # Check if empty list of secondaries is rejected
1184 66222813 Thomas Thrainer
    self.assertRaises(errors.ProgrammerError, gdt, self.lu, constants.DT_DRBD8,
1185 66222813 Thomas Thrainer
                      "inst827.example.com", "node1334.example.com", [],
1186 66222813 Thomas Thrainer
                      disk_info, NotImplemented, NotImplemented, 0,
1187 66222813 Thomas Thrainer
                      self.lu.LogInfo, self.GetDiskParams())
1188 66222813 Thomas Thrainer
1189 66222813 Thomas Thrainer
    result = gdt(self.lu, constants.DT_DRBD8, "inst827.example.com",
1190 66222813 Thomas Thrainer
                 "node1334.example.com", ["node12272.example.com"],
1191 66222813 Thomas Thrainer
                 disk_info, NotImplemented, NotImplemented, 0, self.lu.LogInfo,
1192 66222813 Thomas Thrainer
                 self.GetDiskParams())
1193 66222813 Thomas Thrainer
1194 66222813 Thomas Thrainer
    for (idx, disk) in enumerate(result):
1195 66222813 Thomas Thrainer
      self.assertTrue(isinstance(disk, objects.Disk))
1196 0c5f1b13 Thomas Thrainer
      self.assertEqual(disk.dev_type, constants.DT_DRBD8)
1197 66222813 Thomas Thrainer
      self.assertEqual(disk.size, disk_info[idx][constants.IDISK_SIZE])
1198 66222813 Thomas Thrainer
      self.assertEqual(disk.mode, disk_info[idx][constants.IDISK_MODE])
1199 66222813 Thomas Thrainer
1200 66222813 Thomas Thrainer
      for child in disk.children:
1201 66222813 Thomas Thrainer
        self.assertTrue(isinstance(disk, objects.Disk))
1202 0c5f1b13 Thomas Thrainer
        self.assertEqual(child.dev_type, constants.DT_PLAIN)
1203 66222813 Thomas Thrainer
        self.assertTrue(child.children is None)
1204 66222813 Thomas Thrainer
1205 66222813 Thomas Thrainer
      self.assertEqual(map(operator.attrgetter("logical_id"), disk.children),
1206 66222813 Thomas Thrainer
                       exp_logical_ids[idx])
1207 66222813 Thomas Thrainer
1208 66222813 Thomas Thrainer
      self.assertEqual(len(disk.children), 2)
1209 66222813 Thomas Thrainer
      self.assertEqual(disk.children[0].size, disk.size)
1210 66222813 Thomas Thrainer
      self.assertEqual(disk.children[1].size, constants.DRBD_META_SIZE)
1211 66222813 Thomas Thrainer
1212 66222813 Thomas Thrainer
    self._CheckIvNames(result, 0, len(disk_info))
1213 66222813 Thomas Thrainer
    instance._UpdateIvNames(0, result)
1214 66222813 Thomas Thrainer
    self._CheckIvNames(result, 0, len(disk_info))
1215 66222813 Thomas Thrainer
1216 66222813 Thomas Thrainer
    self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1217 66222813 Thomas Thrainer
      ("node1334.example.com", "node12272.example.com",
1218 66222813 Thomas Thrainer
       constants.FIRST_DRBD_PORT, 20, 21, "ec1-secret0"),
1219 66222813 Thomas Thrainer
      ("node1334.example.com", "node12272.example.com",
1220 66222813 Thomas Thrainer
       constants.FIRST_DRBD_PORT + 1, 22, 23, "ec1-secret1"),
1221 66222813 Thomas Thrainer
      ("node1334.example.com", "node12272.example.com",
1222 66222813 Thomas Thrainer
       constants.FIRST_DRBD_PORT + 2, 24, 25, "ec1-secret2"),
1223 66222813 Thomas Thrainer
      ])
1224 66222813 Thomas Thrainer
1225 66222813 Thomas Thrainer
1226 66222813 Thomas Thrainer
class _DiskPauseTracker:
1227 66222813 Thomas Thrainer
  def __init__(self):
1228 66222813 Thomas Thrainer
    self.history = []
1229 66222813 Thomas Thrainer
1230 66222813 Thomas Thrainer
  def __call__(self, (disks, instance), pause):
1231 66222813 Thomas Thrainer
    assert not (set(disks) - set(instance.disks))
1232 66222813 Thomas Thrainer
1233 66222813 Thomas Thrainer
    self.history.extend((i.logical_id, i.size, pause)
1234 66222813 Thomas Thrainer
                        for i in disks)
1235 66222813 Thomas Thrainer
1236 66222813 Thomas Thrainer
    return (True, [True] * len(disks))
1237 66222813 Thomas Thrainer
1238 66222813 Thomas Thrainer
1239 66222813 Thomas Thrainer
class _ConfigForDiskWipe:
1240 66222813 Thomas Thrainer
  def __init__(self, exp_node_uuid):
1241 66222813 Thomas Thrainer
    self._exp_node_uuid = exp_node_uuid
1242 66222813 Thomas Thrainer
1243 66222813 Thomas Thrainer
  def GetNodeName(self, node_uuid):
1244 66222813 Thomas Thrainer
    assert node_uuid == self._exp_node_uuid
1245 66222813 Thomas Thrainer
    return "name.of.expected.node"
1246 66222813 Thomas Thrainer
1247 66222813 Thomas Thrainer
1248 66222813 Thomas Thrainer
class _RpcForDiskWipe:
1249 66222813 Thomas Thrainer
  def __init__(self, exp_node, pause_cb, wipe_cb):
1250 66222813 Thomas Thrainer
    self._exp_node = exp_node
1251 66222813 Thomas Thrainer
    self._pause_cb = pause_cb
1252 66222813 Thomas Thrainer
    self._wipe_cb = wipe_cb
1253 66222813 Thomas Thrainer
1254 66222813 Thomas Thrainer
  def call_blockdev_pause_resume_sync(self, node, disks, pause):
1255 66222813 Thomas Thrainer
    assert node == self._exp_node
1256 66222813 Thomas Thrainer
    return rpc.RpcResult(data=self._pause_cb(disks, pause))
1257 66222813 Thomas Thrainer
1258 66222813 Thomas Thrainer
  def call_blockdev_wipe(self, node, bdev, offset, size):
1259 66222813 Thomas Thrainer
    assert node == self._exp_node
1260 66222813 Thomas Thrainer
    return rpc.RpcResult(data=self._wipe_cb(bdev, offset, size))
1261 66222813 Thomas Thrainer
1262 66222813 Thomas Thrainer
1263 66222813 Thomas Thrainer
class _DiskWipeProgressTracker:
1264 66222813 Thomas Thrainer
  def __init__(self, start_offset):
1265 66222813 Thomas Thrainer
    self._start_offset = start_offset
1266 66222813 Thomas Thrainer
    self.progress = {}
1267 66222813 Thomas Thrainer
1268 66222813 Thomas Thrainer
  def __call__(self, (disk, _), offset, size):
1269 66222813 Thomas Thrainer
    assert isinstance(offset, (long, int))
1270 66222813 Thomas Thrainer
    assert isinstance(size, (long, int))
1271 66222813 Thomas Thrainer
1272 66222813 Thomas Thrainer
    max_chunk_size = (disk.size / 100.0 * constants.MIN_WIPE_CHUNK_PERCENT)
1273 66222813 Thomas Thrainer
1274 66222813 Thomas Thrainer
    assert offset >= self._start_offset
1275 66222813 Thomas Thrainer
    assert (offset + size) <= disk.size
1276 66222813 Thomas Thrainer
1277 66222813 Thomas Thrainer
    assert size > 0
1278 66222813 Thomas Thrainer
    assert size <= constants.MAX_WIPE_CHUNK
1279 66222813 Thomas Thrainer
    assert size <= max_chunk_size
1280 66222813 Thomas Thrainer
1281 66222813 Thomas Thrainer
    assert offset == self._start_offset or disk.logical_id in self.progress
1282 66222813 Thomas Thrainer
1283 66222813 Thomas Thrainer
    # Keep track of progress
1284 66222813 Thomas Thrainer
    cur_progress = self.progress.setdefault(disk.logical_id, self._start_offset)
1285 66222813 Thomas Thrainer
1286 66222813 Thomas Thrainer
    assert cur_progress == offset
1287 66222813 Thomas Thrainer
1288 66222813 Thomas Thrainer
    # Record progress
1289 66222813 Thomas Thrainer
    self.progress[disk.logical_id] += size
1290 66222813 Thomas Thrainer
1291 66222813 Thomas Thrainer
    return (True, None)
1292 66222813 Thomas Thrainer
1293 66222813 Thomas Thrainer
1294 66222813 Thomas Thrainer
class TestWipeDisks(unittest.TestCase):
1295 66222813 Thomas Thrainer
  def _FailingPauseCb(self, (disks, _), pause):
1296 66222813 Thomas Thrainer
    self.assertEqual(len(disks), 3)
1297 66222813 Thomas Thrainer
    self.assertTrue(pause)
1298 66222813 Thomas Thrainer
    # Simulate an RPC error
1299 66222813 Thomas Thrainer
    return (False, "error")
1300 66222813 Thomas Thrainer
1301 66222813 Thomas Thrainer
  def testPauseFailure(self):
1302 66222813 Thomas Thrainer
    node_name = "node1372.example.com"
1303 66222813 Thomas Thrainer
1304 66222813 Thomas Thrainer
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, self._FailingPauseCb,
1305 66222813 Thomas Thrainer
                                     NotImplemented),
1306 66222813 Thomas Thrainer
                 cfg=_ConfigForDiskWipe(node_name))
1307 66222813 Thomas Thrainer
1308 66222813 Thomas Thrainer
    disks = [
1309 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN),
1310 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN),
1311 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN),
1312 66222813 Thomas Thrainer
      ]
1313 66222813 Thomas Thrainer
1314 66222813 Thomas Thrainer
    inst = objects.Instance(name="inst21201",
1315 66222813 Thomas Thrainer
                            primary_node=node_name,
1316 66222813 Thomas Thrainer
                            disk_template=constants.DT_PLAIN,
1317 66222813 Thomas Thrainer
                            disks=disks)
1318 66222813 Thomas Thrainer
1319 66222813 Thomas Thrainer
    self.assertRaises(errors.OpExecError, instance.WipeDisks, lu, inst)
1320 66222813 Thomas Thrainer
1321 66222813 Thomas Thrainer
  def _FailingWipeCb(self, (disk, _), offset, size):
1322 66222813 Thomas Thrainer
    # This should only ever be called for the first disk
1323 66222813 Thomas Thrainer
    self.assertEqual(disk.logical_id, "disk0")
1324 66222813 Thomas Thrainer
    return (False, None)
1325 66222813 Thomas Thrainer
1326 66222813 Thomas Thrainer
  def testFailingWipe(self):
1327 66222813 Thomas Thrainer
    node_uuid = "node13445-uuid"
1328 66222813 Thomas Thrainer
    pt = _DiskPauseTracker()
1329 66222813 Thomas Thrainer
1330 66222813 Thomas Thrainer
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_uuid, pt, self._FailingWipeCb),
1331 66222813 Thomas Thrainer
                 cfg=_ConfigForDiskWipe(node_uuid))
1332 66222813 Thomas Thrainer
1333 66222813 Thomas Thrainer
    disks = [
1334 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk0",
1335 66222813 Thomas Thrainer
                   size=100 * 1024),
1336 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk1",
1337 66222813 Thomas Thrainer
                   size=500 * 1024),
1338 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk2", size=256),
1339 66222813 Thomas Thrainer
      ]
1340 66222813 Thomas Thrainer
1341 66222813 Thomas Thrainer
    inst = objects.Instance(name="inst562",
1342 66222813 Thomas Thrainer
                            primary_node=node_uuid,
1343 66222813 Thomas Thrainer
                            disk_template=constants.DT_PLAIN,
1344 66222813 Thomas Thrainer
                            disks=disks)
1345 66222813 Thomas Thrainer
1346 66222813 Thomas Thrainer
    try:
1347 66222813 Thomas Thrainer
      instance.WipeDisks(lu, inst)
1348 66222813 Thomas Thrainer
    except errors.OpExecError, err:
1349 66222813 Thomas Thrainer
      self.assertTrue(str(err), "Could not wipe disk 0 at offset 0 ")
1350 66222813 Thomas Thrainer
    else:
1351 66222813 Thomas Thrainer
      self.fail("Did not raise exception")
1352 66222813 Thomas Thrainer
1353 66222813 Thomas Thrainer
    # Check if all disks were paused and resumed
1354 66222813 Thomas Thrainer
    self.assertEqual(pt.history, [
1355 66222813 Thomas Thrainer
      ("disk0", 100 * 1024, True),
1356 66222813 Thomas Thrainer
      ("disk1", 500 * 1024, True),
1357 66222813 Thomas Thrainer
      ("disk2", 256, True),
1358 66222813 Thomas Thrainer
      ("disk0", 100 * 1024, False),
1359 66222813 Thomas Thrainer
      ("disk1", 500 * 1024, False),
1360 66222813 Thomas Thrainer
      ("disk2", 256, False),
1361 66222813 Thomas Thrainer
      ])
1362 66222813 Thomas Thrainer
1363 66222813 Thomas Thrainer
  def _PrepareWipeTest(self, start_offset, disks):
1364 66222813 Thomas Thrainer
    node_name = "node-with-offset%s.example.com" % start_offset
1365 66222813 Thomas Thrainer
    pauset = _DiskPauseTracker()
1366 66222813 Thomas Thrainer
    progresst = _DiskWipeProgressTracker(start_offset)
1367 66222813 Thomas Thrainer
1368 66222813 Thomas Thrainer
    lu = _FakeLU(rpc=_RpcForDiskWipe(node_name, pauset, progresst),
1369 66222813 Thomas Thrainer
                 cfg=_ConfigForDiskWipe(node_name))
1370 66222813 Thomas Thrainer
1371 66222813 Thomas Thrainer
    instance = objects.Instance(name="inst3560",
1372 66222813 Thomas Thrainer
                                primary_node=node_name,
1373 66222813 Thomas Thrainer
                                disk_template=constants.DT_PLAIN,
1374 66222813 Thomas Thrainer
                                disks=disks)
1375 66222813 Thomas Thrainer
1376 66222813 Thomas Thrainer
    return (lu, instance, pauset, progresst)
1377 66222813 Thomas Thrainer
1378 66222813 Thomas Thrainer
  def testNormalWipe(self):
1379 66222813 Thomas Thrainer
    disks = [
1380 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk0", size=1024),
1381 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk1",
1382 66222813 Thomas Thrainer
                   size=500 * 1024),
1383 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk2", size=128),
1384 0c5f1b13 Thomas Thrainer
      objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk3",
1385 66222813 Thomas Thrainer
                   size=constants.MAX_WIPE_CHUNK),
1386 66222813 Thomas Thrainer
      ]
1387 66222813 Thomas Thrainer
1388 66222813 Thomas Thrainer
    (lu, inst, pauset, progresst) = self._PrepareWipeTest(0, disks)
1389 66222813 Thomas Thrainer
1390 66222813 Thomas Thrainer
    instance.WipeDisks(lu, inst)
1391 66222813 Thomas Thrainer
1392 66222813 Thomas Thrainer
    self.assertEqual(pauset.history, [
1393 66222813 Thomas Thrainer
      ("disk0", 1024, True),
1394 66222813 Thomas Thrainer
      ("disk1", 500 * 1024, True),
1395 66222813 Thomas Thrainer
      ("disk2", 128, True),
1396 66222813 Thomas Thrainer
      ("disk3", constants.MAX_WIPE_CHUNK, True),
1397 66222813 Thomas Thrainer
      ("disk0", 1024, False),
1398 66222813 Thomas Thrainer
      ("disk1", 500 * 1024, False),
1399 66222813 Thomas Thrainer
      ("disk2", 128, False),
1400 66222813 Thomas Thrainer
      ("disk3", constants.MAX_WIPE_CHUNK, False),
1401 66222813 Thomas Thrainer
      ])
1402 66222813 Thomas Thrainer
1403 66222813 Thomas Thrainer
    # Ensure the complete disk has been wiped
1404 66222813 Thomas Thrainer
    self.assertEqual(progresst.progress,
1405 66222813 Thomas Thrainer
                     dict((i.logical_id, i.size) for i in disks))
1406 66222813 Thomas Thrainer
1407 66222813 Thomas Thrainer
  def testWipeWithStartOffset(self):
1408 66222813 Thomas Thrainer
    for start_offset in [0, 280, 8895, 1563204]:
1409 66222813 Thomas Thrainer
      disks = [
1410 0c5f1b13 Thomas Thrainer
        objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk0",
1411 66222813 Thomas Thrainer
                     size=128),
1412 0c5f1b13 Thomas Thrainer
        objects.Disk(dev_type=constants.DT_PLAIN, logical_id="disk1",
1413 66222813 Thomas Thrainer
                     size=start_offset + (100 * 1024)),
1414 66222813 Thomas Thrainer
        ]
1415 66222813 Thomas Thrainer
1416 66222813 Thomas Thrainer
      (lu, inst, pauset, progresst) = \
1417 66222813 Thomas Thrainer
        self._PrepareWipeTest(start_offset, disks)
1418 66222813 Thomas Thrainer
1419 66222813 Thomas Thrainer
      # Test start offset with only one disk
1420 66222813 Thomas Thrainer
      instance.WipeDisks(lu, inst,
1421 66222813 Thomas Thrainer
                         disks=[(1, disks[1], start_offset)])
1422 66222813 Thomas Thrainer
1423 66222813 Thomas Thrainer
      # Only the second disk may have been paused and wiped
1424 66222813 Thomas Thrainer
      self.assertEqual(pauset.history, [
1425 66222813 Thomas Thrainer
        ("disk1", start_offset + (100 * 1024), True),
1426 66222813 Thomas Thrainer
        ("disk1", start_offset + (100 * 1024), False),
1427 66222813 Thomas Thrainer
        ])
1428 66222813 Thomas Thrainer
      self.assertEqual(progresst.progress, {
1429 66222813 Thomas Thrainer
        "disk1": disks[1].size,
1430 66222813 Thomas Thrainer
        })
1431 66222813 Thomas Thrainer
1432 66222813 Thomas Thrainer
1433 66222813 Thomas Thrainer
class TestCheckOpportunisticLocking(unittest.TestCase):
1434 66222813 Thomas Thrainer
  class OpTest(opcodes.OpCode):
1435 66222813 Thomas Thrainer
    OP_PARAMS = [
1436 66222813 Thomas Thrainer
      ("opportunistic_locking", False, ht.TBool, None),
1437 66222813 Thomas Thrainer
      ("iallocator", None, ht.TMaybe(ht.TNonEmptyString), "")
1438 66222813 Thomas Thrainer
      ]
1439 66222813 Thomas Thrainer
1440 66222813 Thomas Thrainer
  @classmethod
1441 66222813 Thomas Thrainer
  def _MakeOp(cls, **kwargs):
1442 66222813 Thomas Thrainer
    op = cls.OpTest(**kwargs)
1443 66222813 Thomas Thrainer
    op.Validate(True)
1444 66222813 Thomas Thrainer
    return op
1445 66222813 Thomas Thrainer
1446 66222813 Thomas Thrainer
  def testMissingAttributes(self):
1447 66222813 Thomas Thrainer
    self.assertRaises(AttributeError, instance._CheckOpportunisticLocking,
1448 66222813 Thomas Thrainer
                      object())
1449 66222813 Thomas Thrainer
1450 66222813 Thomas Thrainer
  def testDefaults(self):
1451 66222813 Thomas Thrainer
    op = self._MakeOp()
1452 66222813 Thomas Thrainer
    instance._CheckOpportunisticLocking(op)
1453 66222813 Thomas Thrainer
1454 66222813 Thomas Thrainer
  def test(self):
1455 66222813 Thomas Thrainer
    for iallocator in [None, "something", "other"]:
1456 66222813 Thomas Thrainer
      for opplock in [False, True]:
1457 66222813 Thomas Thrainer
        op = self._MakeOp(iallocator=iallocator,
1458 66222813 Thomas Thrainer
                          opportunistic_locking=opplock)
1459 66222813 Thomas Thrainer
        if opplock and not iallocator:
1460 66222813 Thomas Thrainer
          self.assertRaises(errors.OpPrereqError,
1461 66222813 Thomas Thrainer
                            instance._CheckOpportunisticLocking, op)
1462 66222813 Thomas Thrainer
        else:
1463 66222813 Thomas Thrainer
          instance._CheckOpportunisticLocking(op)
1464 66222813 Thomas Thrainer
1465 66222813 Thomas Thrainer
1466 e066018b Thomas Thrainer
class TestLUInstanceRemove(CmdlibTestCase):
1467 e066018b Thomas Thrainer
  def testRemoveMissingInstance(self):
1468 e066018b Thomas Thrainer
    op = opcodes.OpInstanceRemove(instance_name="missing.inst")
1469 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Instance 'missing.inst' not known")
1470 e066018b Thomas Thrainer
1471 e066018b Thomas Thrainer
  def testRemoveInst(self):
1472 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance(disks=[])
1473 e066018b Thomas Thrainer
    op = opcodes.OpInstanceRemove(instance_name=inst.name)
1474 e066018b Thomas Thrainer
    self.ExecOpCode(op)
1475 e066018b Thomas Thrainer
1476 e066018b Thomas Thrainer
1477 e066018b Thomas Thrainer
class TestLUInstanceMove(CmdlibTestCase):
1478 e066018b Thomas Thrainer
  def setUp(self):
1479 e066018b Thomas Thrainer
    super(TestLUInstanceMove, self).setUp()
1480 e066018b Thomas Thrainer
1481 e066018b Thomas Thrainer
    self.node = self.cfg.AddNewNode()
1482 e066018b Thomas Thrainer
1483 e066018b Thomas Thrainer
    self.rpc.call_blockdev_assemble.return_value = \
1484 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1485 ff5def9b Dimitris Aragiorgis
        .CreateSuccessfulNodeResult(self.node, ("/dev/mocked_path",
1486 ff5def9b Dimitris Aragiorgis
                                    "/var/run/ganeti/instance-disks/mocked_d"))
1487 e066018b Thomas Thrainer
    self.rpc.call_blockdev_remove.return_value = \
1488 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1489 e066018b Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, "")
1490 e066018b Thomas Thrainer
1491 063613aa Thomas Thrainer
    def ImportStart(node_uuid, opt, inst, component, args):
1492 063613aa Thomas Thrainer
      return self.RpcResultsBuilder() \
1493 063613aa Thomas Thrainer
               .CreateSuccessfulNodeResult(node_uuid,
1494 063613aa Thomas Thrainer
                                           "deamon_on_%s" % node_uuid)
1495 063613aa Thomas Thrainer
    self.rpc.call_import_start.side_effect = ImportStart
1496 063613aa Thomas Thrainer
1497 063613aa Thomas Thrainer
    def ImpExpStatus(node_uuid, name):
1498 063613aa Thomas Thrainer
      return self.RpcResultsBuilder() \
1499 063613aa Thomas Thrainer
               .CreateSuccessfulNodeResult(node_uuid,
1500 063613aa Thomas Thrainer
                                           [objects.ImportExportStatus(
1501 063613aa Thomas Thrainer
                                             exit_status=0
1502 063613aa Thomas Thrainer
                                           )])
1503 063613aa Thomas Thrainer
    self.rpc.call_impexp_status.side_effect = ImpExpStatus
1504 063613aa Thomas Thrainer
1505 063613aa Thomas Thrainer
    def ImpExpCleanup(node_uuid, name):
1506 063613aa Thomas Thrainer
      return self.RpcResultsBuilder() \
1507 063613aa Thomas Thrainer
               .CreateSuccessfulNodeResult(node_uuid)
1508 063613aa Thomas Thrainer
    self.rpc.call_impexp_cleanup.side_effect = ImpExpCleanup
1509 063613aa Thomas Thrainer
1510 e066018b Thomas Thrainer
  def testMissingInstance(self):
1511 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name="missing.inst",
1512 e066018b Thomas Thrainer
                                target_node=self.node.name)
1513 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Instance 'missing.inst' not known")
1514 e066018b Thomas Thrainer
1515 e066018b Thomas Thrainer
  def testUncopyableDiskTemplate(self):
1516 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance(disk_template=constants.DT_SHARED_FILE)
1517 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1518 e066018b Thomas Thrainer
                                target_node=self.node.name)
1519 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1520 e066018b Thomas Thrainer
      op, "Disk template sharedfile not suitable for copying")
1521 e066018b Thomas Thrainer
1522 e066018b Thomas Thrainer
  def testAlreadyOnTargetNode(self):
1523 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance()
1524 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1525 e066018b Thomas Thrainer
                                target_node=self.master.name)
1526 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1527 e066018b Thomas Thrainer
      op, "Instance .* is already on the node .*")
1528 e066018b Thomas Thrainer
1529 e066018b Thomas Thrainer
  def testMoveStoppedInstance(self):
1530 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance()
1531 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1532 e066018b Thomas Thrainer
                                target_node=self.node.name)
1533 e066018b Thomas Thrainer
    self.ExecOpCode(op)
1534 e066018b Thomas Thrainer
1535 e066018b Thomas Thrainer
  def testMoveRunningInstance(self):
1536 e066018b Thomas Thrainer
    self.rpc.call_node_info.return_value = \
1537 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1538 e066018b Thomas Thrainer
        .AddSuccessfulNode(self.node,
1539 e066018b Thomas Thrainer
                           (NotImplemented, NotImplemented,
1540 e066018b Thomas Thrainer
                            ({"memory_free": 10000}, ))) \
1541 e066018b Thomas Thrainer
        .Build()
1542 e066018b Thomas Thrainer
    self.rpc.call_instance_start.return_value = \
1543 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1544 e066018b Thomas Thrainer
        .CreateSuccessfulNodeResult(self.node, "")
1545 e066018b Thomas Thrainer
1546 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
1547 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1548 e066018b Thomas Thrainer
                                target_node=self.node.name)
1549 e066018b Thomas Thrainer
    self.ExecOpCode(op)
1550 e066018b Thomas Thrainer
1551 063613aa Thomas Thrainer
  def testMoveFailingStartInstance(self):
1552 e066018b Thomas Thrainer
    self.rpc.call_node_info.return_value = \
1553 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1554 e066018b Thomas Thrainer
        .AddSuccessfulNode(self.node,
1555 e066018b Thomas Thrainer
                           (NotImplemented, NotImplemented,
1556 e066018b Thomas Thrainer
                            ({"memory_free": 10000}, ))) \
1557 e066018b Thomas Thrainer
        .Build()
1558 e066018b Thomas Thrainer
    self.rpc.call_instance_start.return_value = \
1559 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1560 e066018b Thomas Thrainer
        .CreateFailedNodeResult(self.node)
1561 e066018b Thomas Thrainer
1562 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
1563 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1564 e066018b Thomas Thrainer
                                target_node=self.node.name)
1565 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpExecError(
1566 e066018b Thomas Thrainer
      op, "Could not start instance .* on node .*")
1567 e066018b Thomas Thrainer
1568 063613aa Thomas Thrainer
  def testMoveFailingImpExpDaemonExitCode(self):
1569 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance()
1570 063613aa Thomas Thrainer
    self.rpc.call_impexp_status.side_effect = None
1571 063613aa Thomas Thrainer
    self.rpc.call_impexp_status.return_value = \
1572 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1573 063613aa Thomas Thrainer
        .CreateSuccessfulNodeResult(self.node,
1574 063613aa Thomas Thrainer
                                    [objects.ImportExportStatus(
1575 063613aa Thomas Thrainer
                                      exit_status=1,
1576 063613aa Thomas Thrainer
                                      recent_output=["mock output"]
1577 063613aa Thomas Thrainer
                                    )])
1578 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1579 e066018b Thomas Thrainer
                                target_node=self.node.name)
1580 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpExecError(op, "Errors during disk copy")
1581 e066018b Thomas Thrainer
1582 063613aa Thomas Thrainer
  def testMoveFailingStartImpExpDaemon(self):
1583 e066018b Thomas Thrainer
    inst = self.cfg.AddNewInstance()
1584 063613aa Thomas Thrainer
    self.rpc.call_import_start.side_effect = None
1585 063613aa Thomas Thrainer
    self.rpc.call_import_start.return_value = \
1586 e066018b Thomas Thrainer
      self.RpcResultsBuilder() \
1587 e066018b Thomas Thrainer
        .CreateFailedNodeResult(self.node)
1588 e066018b Thomas Thrainer
    op = opcodes.OpInstanceMove(instance_name=inst.name,
1589 e066018b Thomas Thrainer
                                target_node=self.node.name)
1590 e066018b Thomas Thrainer
    self.ExecOpCodeExpectOpExecError(op, "Errors during disk copy")
1591 e066018b Thomas Thrainer
1592 e066018b Thomas Thrainer
1593 bf2a3eba Thomas Thrainer
class TestLUInstanceRename(CmdlibTestCase):
1594 bf2a3eba Thomas Thrainer
  def setUp(self):
1595 bf2a3eba Thomas Thrainer
    super(TestLUInstanceRename, self).setUp()
1596 bf2a3eba Thomas Thrainer
1597 bf2a3eba Thomas Thrainer
    self.inst = self.cfg.AddNewInstance()
1598 bf2a3eba Thomas Thrainer
1599 bf2a3eba Thomas Thrainer
    self.op = opcodes.OpInstanceRename(instance_name=self.inst.name,
1600 bf2a3eba Thomas Thrainer
                                       new_name="new_name.example.com")
1601 bf2a3eba Thomas Thrainer
1602 bf2a3eba Thomas Thrainer
  def testIpCheckWithoutNameCheck(self):
1603 bf2a3eba Thomas Thrainer
    op = self.CopyOpCode(self.op,
1604 bf2a3eba Thomas Thrainer
                         ip_check=True,
1605 bf2a3eba Thomas Thrainer
                         name_check=False)
1606 bf2a3eba Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1607 bf2a3eba Thomas Thrainer
      op, "IP address check requires a name check")
1608 bf2a3eba Thomas Thrainer
1609 bf2a3eba Thomas Thrainer
  def testIpAlreadyInUse(self):
1610 bf2a3eba Thomas Thrainer
    self.netutils_mod.TcpPing.return_value = True
1611 bf2a3eba Thomas Thrainer
    op = self.CopyOpCode(self.op)
1612 bf2a3eba Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1613 bf2a3eba Thomas Thrainer
      op, "IP .* of instance .* already in use")
1614 bf2a3eba Thomas Thrainer
1615 bf2a3eba Thomas Thrainer
  def testExistingInstanceName(self):
1616 bf2a3eba Thomas Thrainer
    self.cfg.AddNewInstance(name="new_name.example.com")
1617 bf2a3eba Thomas Thrainer
    op = self.CopyOpCode(self.op)
1618 bf2a3eba Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1619 bf2a3eba Thomas Thrainer
      op, "Instance .* is already in the cluster")
1620 bf2a3eba Thomas Thrainer
1621 bf2a3eba Thomas Thrainer
  def testFileInstance(self):
1622 bf2a3eba Thomas Thrainer
    self.rpc.call_blockdev_assemble.return_value = \
1623 bf2a3eba Thomas Thrainer
      self.RpcResultsBuilder() \
1624 ff5def9b Dimitris Aragiorgis
        .CreateSuccessfulNodeResult(self.master, (None, None))
1625 bf2a3eba Thomas Thrainer
    self.rpc.call_blockdev_shutdown.return_value = \
1626 bf2a3eba Thomas Thrainer
      self.RpcResultsBuilder() \
1627 bb133242 Klaus Aehlig
        .CreateSuccessfulNodeResult(self.master, (None, None))
1628 bf2a3eba Thomas Thrainer
1629 bf2a3eba Thomas Thrainer
    inst = self.cfg.AddNewInstance(disk_template=constants.DT_FILE)
1630 bf2a3eba Thomas Thrainer
    op = self.CopyOpCode(self.op,
1631 bf2a3eba Thomas Thrainer
                         instance_name=inst.name)
1632 bf2a3eba Thomas Thrainer
    self.ExecOpCode(op)
1633 bf2a3eba Thomas Thrainer
1634 bf2a3eba Thomas Thrainer
1635 4a8c84f3 Thomas Thrainer
class TestLUInstanceMultiAlloc(CmdlibTestCase):
1636 4a8c84f3 Thomas Thrainer
  def setUp(self):
1637 4a8c84f3 Thomas Thrainer
    super(TestLUInstanceMultiAlloc, self).setUp()
1638 4a8c84f3 Thomas Thrainer
1639 4a8c84f3 Thomas Thrainer
    self.inst_op = opcodes.OpInstanceCreate(instance_name="inst.example.com",
1640 4a8c84f3 Thomas Thrainer
                                            disk_template=constants.DT_DRBD8,
1641 4a8c84f3 Thomas Thrainer
                                            disks=[],
1642 4a8c84f3 Thomas Thrainer
                                            nics=[],
1643 4a8c84f3 Thomas Thrainer
                                            os_type="mock_os",
1644 4a8c84f3 Thomas Thrainer
                                            hypervisor=constants.HT_XEN_HVM,
1645 4a8c84f3 Thomas Thrainer
                                            mode=constants.INSTANCE_CREATE)
1646 4a8c84f3 Thomas Thrainer
1647 4a8c84f3 Thomas Thrainer
  def testInstanceWithIAllocator(self):
1648 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op,
1649 4a8c84f3 Thomas Thrainer
                           iallocator="mock")
1650 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst])
1651 4a8c84f3 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1652 4a8c84f3 Thomas Thrainer
      op, "iallocator are not allowed to be set on instance objects")
1653 4a8c84f3 Thomas Thrainer
1654 4a8c84f3 Thomas Thrainer
  def testOnlySomeNodesGiven(self):
1655 4a8c84f3 Thomas Thrainer
    inst1 = self.CopyOpCode(self.inst_op,
1656 4a8c84f3 Thomas Thrainer
                            pnode=self.master.name)
1657 4a8c84f3 Thomas Thrainer
    inst2 = self.CopyOpCode(self.inst_op)
1658 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst1, inst2])
1659 4a8c84f3 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1660 4a8c84f3 Thomas Thrainer
      op, "There are instance objects providing pnode/snode while others"
1661 4a8c84f3 Thomas Thrainer
          " do not")
1662 4a8c84f3 Thomas Thrainer
1663 4a8c84f3 Thomas Thrainer
  def testMissingIAllocator(self):
1664 4a8c84f3 Thomas Thrainer
    self.cluster.default_iallocator = None
1665 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op)
1666 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst])
1667 4a8c84f3 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1668 4a8c84f3 Thomas Thrainer
      op, "No iallocator or nodes on the instances given and no cluster-wide"
1669 4a8c84f3 Thomas Thrainer
          " default iallocator found")
1670 4a8c84f3 Thomas Thrainer
1671 4a8c84f3 Thomas Thrainer
  def testDuplicateInstanceNames(self):
1672 4a8c84f3 Thomas Thrainer
    inst1 = self.CopyOpCode(self.inst_op)
1673 4a8c84f3 Thomas Thrainer
    inst2 = self.CopyOpCode(self.inst_op)
1674 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst1, inst2])
1675 4a8c84f3 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1676 4a8c84f3 Thomas Thrainer
      op, "There are duplicate instance names")
1677 4a8c84f3 Thomas Thrainer
1678 4a8c84f3 Thomas Thrainer
  def testWithGivenNodes(self):
1679 4a8c84f3 Thomas Thrainer
    snode = self.cfg.AddNewNode()
1680 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op,
1681 4a8c84f3 Thomas Thrainer
                           pnode=self.master.name,
1682 4a8c84f3 Thomas Thrainer
                           snode=snode.name)
1683 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst])
1684 4a8c84f3 Thomas Thrainer
    self.ExecOpCode(op)
1685 4a8c84f3 Thomas Thrainer
1686 4a8c84f3 Thomas Thrainer
  def testDryRun(self):
1687 4a8c84f3 Thomas Thrainer
    snode = self.cfg.AddNewNode()
1688 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op,
1689 4a8c84f3 Thomas Thrainer
                           pnode=self.master.name,
1690 4a8c84f3 Thomas Thrainer
                           snode=snode.name)
1691 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst],
1692 4a8c84f3 Thomas Thrainer
                                      dry_run=True)
1693 4a8c84f3 Thomas Thrainer
    self.ExecOpCode(op)
1694 4a8c84f3 Thomas Thrainer
1695 4a8c84f3 Thomas Thrainer
  def testWithIAllocator(self):
1696 4a8c84f3 Thomas Thrainer
    snode = self.cfg.AddNewNode()
1697 4a8c84f3 Thomas Thrainer
    self.iallocator_cls.return_value.result = \
1698 4a8c84f3 Thomas Thrainer
      ([("inst.example.com", [self.master.name, snode.name])], [])
1699 4a8c84f3 Thomas Thrainer
1700 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op)
1701 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst],
1702 4a8c84f3 Thomas Thrainer
                                      iallocator="mock_ialloc")
1703 4a8c84f3 Thomas Thrainer
    self.ExecOpCode(op)
1704 4a8c84f3 Thomas Thrainer
1705 4a8c84f3 Thomas Thrainer
  def testWithIAllocatorOpportunisticLocking(self):
1706 4a8c84f3 Thomas Thrainer
    snode = self.cfg.AddNewNode()
1707 4a8c84f3 Thomas Thrainer
    self.iallocator_cls.return_value.result = \
1708 4a8c84f3 Thomas Thrainer
      ([("inst.example.com", [self.master.name, snode.name])], [])
1709 4a8c84f3 Thomas Thrainer
1710 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op)
1711 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst],
1712 4a8c84f3 Thomas Thrainer
                                      iallocator="mock_ialloc",
1713 4a8c84f3 Thomas Thrainer
                                      opportunistic_locking=True)
1714 4a8c84f3 Thomas Thrainer
    self.ExecOpCode(op)
1715 4a8c84f3 Thomas Thrainer
1716 4a8c84f3 Thomas Thrainer
  def testFailingIAllocator(self):
1717 4a8c84f3 Thomas Thrainer
    self.iallocator_cls.return_value.success = False
1718 4a8c84f3 Thomas Thrainer
1719 4a8c84f3 Thomas Thrainer
    inst = self.CopyOpCode(self.inst_op)
1720 4a8c84f3 Thomas Thrainer
    op = opcodes.OpInstanceMultiAlloc(instances=[inst],
1721 4a8c84f3 Thomas Thrainer
                                      iallocator="mock_ialloc")
1722 4a8c84f3 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1723 4a8c84f3 Thomas Thrainer
      op, "Can't compute nodes using iallocator")
1724 4a8c84f3 Thomas Thrainer
1725 4a8c84f3 Thomas Thrainer
1726 27619aac Thomas Thrainer
class TestLUInstanceSetParams(CmdlibTestCase):
1727 27619aac Thomas Thrainer
  def setUp(self):
1728 27619aac Thomas Thrainer
    super(TestLUInstanceSetParams, self).setUp()
1729 27619aac Thomas Thrainer
1730 27619aac Thomas Thrainer
    self.inst = self.cfg.AddNewInstance()
1731 27619aac Thomas Thrainer
    self.op = opcodes.OpInstanceSetParams(instance_name=self.inst.name)
1732 27619aac Thomas Thrainer
1733 27619aac Thomas Thrainer
    self.running_inst = \
1734 27619aac Thomas Thrainer
      self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
1735 27619aac Thomas Thrainer
    self.running_op = \
1736 27619aac Thomas Thrainer
      opcodes.OpInstanceSetParams(instance_name=self.running_inst.name)
1737 27619aac Thomas Thrainer
1738 27619aac Thomas Thrainer
    self.snode = self.cfg.AddNewNode()
1739 27619aac Thomas Thrainer
1740 27619aac Thomas Thrainer
    self.mocked_storage_type = constants.ST_LVM_VG
1741 27619aac Thomas Thrainer
    self.mocked_storage_free = 10000
1742 27619aac Thomas Thrainer
    self.mocked_master_cpu_total = 16
1743 27619aac Thomas Thrainer
    self.mocked_master_memory_free = 2048
1744 27619aac Thomas Thrainer
    self.mocked_snode_cpu_total = 16
1745 27619aac Thomas Thrainer
    self.mocked_snode_memory_free = 512
1746 27619aac Thomas Thrainer
1747 27619aac Thomas Thrainer
    self.mocked_running_inst_memory = 1024
1748 27619aac Thomas Thrainer
    self.mocked_running_inst_vcpus = 8
1749 27619aac Thomas Thrainer
    self.mocked_running_inst_state = "running"
1750 27619aac Thomas Thrainer
    self.mocked_running_inst_time = 10938474
1751 27619aac Thomas Thrainer
1752 27619aac Thomas Thrainer
    bootid = "mock_bootid"
1753 27619aac Thomas Thrainer
    storage_info = [
1754 27619aac Thomas Thrainer
      {
1755 27619aac Thomas Thrainer
        "type": self.mocked_storage_type,
1756 27619aac Thomas Thrainer
        "storage_free": self.mocked_storage_free
1757 27619aac Thomas Thrainer
      }
1758 27619aac Thomas Thrainer
    ]
1759 27619aac Thomas Thrainer
    hv_info_master = {
1760 27619aac Thomas Thrainer
      "cpu_total": self.mocked_master_cpu_total,
1761 27619aac Thomas Thrainer
      "memory_free": self.mocked_master_memory_free
1762 27619aac Thomas Thrainer
    }
1763 27619aac Thomas Thrainer
    hv_info_snode = {
1764 27619aac Thomas Thrainer
      "cpu_total": self.mocked_snode_cpu_total,
1765 27619aac Thomas Thrainer
      "memory_free": self.mocked_snode_memory_free
1766 27619aac Thomas Thrainer
    }
1767 27619aac Thomas Thrainer
1768 27619aac Thomas Thrainer
    self.rpc.call_node_info.return_value = \
1769 27619aac Thomas Thrainer
      self.RpcResultsBuilder() \
1770 27619aac Thomas Thrainer
        .AddSuccessfulNode(self.master,
1771 27619aac Thomas Thrainer
                           (bootid, storage_info, (hv_info_master, ))) \
1772 27619aac Thomas Thrainer
        .AddSuccessfulNode(self.snode,
1773 27619aac Thomas Thrainer
                           (bootid, storage_info, (hv_info_snode, ))) \
1774 27619aac Thomas Thrainer
        .Build()
1775 27619aac Thomas Thrainer
1776 27619aac Thomas Thrainer
    def _InstanceInfo(_, instance, __, ___):
1777 27619aac Thomas Thrainer
      if instance == self.inst.name:
1778 27619aac Thomas Thrainer
        return self.RpcResultsBuilder() \
1779 27619aac Thomas Thrainer
          .CreateSuccessfulNodeResult(self.master, None)
1780 27619aac Thomas Thrainer
      elif instance == self.running_inst.name:
1781 27619aac Thomas Thrainer
        return self.RpcResultsBuilder() \
1782 27619aac Thomas Thrainer
          .CreateSuccessfulNodeResult(
1783 27619aac Thomas Thrainer
            self.master, {
1784 27619aac Thomas Thrainer
              "memory": self.mocked_running_inst_memory,
1785 27619aac Thomas Thrainer
              "vcpus": self.mocked_running_inst_vcpus,
1786 27619aac Thomas Thrainer
              "state": self.mocked_running_inst_state,
1787 27619aac Thomas Thrainer
              "time": self.mocked_running_inst_time
1788 27619aac Thomas Thrainer
            })
1789 27619aac Thomas Thrainer
      else:
1790 27619aac Thomas Thrainer
        raise AssertionError()
1791 27619aac Thomas Thrainer
    self.rpc.call_instance_info.side_effect = _InstanceInfo
1792 27619aac Thomas Thrainer
1793 27619aac Thomas Thrainer
    self.rpc.call_bridges_exist.return_value = \
1794 27619aac Thomas Thrainer
      self.RpcResultsBuilder() \
1795 27619aac Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, True)
1796 27619aac Thomas Thrainer
1797 922a9e65 Thomas Thrainer
    self.rpc.call_blockdev_getmirrorstatus.side_effect = \
1798 922a9e65 Thomas Thrainer
      lambda node, _: self.RpcResultsBuilder() \
1799 922a9e65 Thomas Thrainer
                        .CreateSuccessfulNodeResult(node, [])
1800 922a9e65 Thomas Thrainer
1801 3c260845 Thomas Thrainer
    self.rpc.call_blockdev_shutdown.side_effect = \
1802 3c260845 Thomas Thrainer
      lambda node, _: self.RpcResultsBuilder() \
1803 3c260845 Thomas Thrainer
                        .CreateSuccessfulNodeResult(node, [])
1804 3c260845 Thomas Thrainer
1805 27619aac Thomas Thrainer
  def testNoChanges(self):
1806 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op)
1807 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "No changes submitted")
1808 27619aac Thomas Thrainer
1809 27619aac Thomas Thrainer
  def testGlobalHvparams(self):
1810 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1811 27619aac Thomas Thrainer
                         hvparams={constants.HV_MIGRATION_PORT: 1234})
1812 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1813 27619aac Thomas Thrainer
      op, "hypervisor parameters are global and cannot be customized")
1814 27619aac Thomas Thrainer
1815 27619aac Thomas Thrainer
  def testHvparams(self):
1816 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1817 27619aac Thomas Thrainer
                         hvparams={constants.HV_BOOT_ORDER: "cd"})
1818 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1819 27619aac Thomas Thrainer
1820 27619aac Thomas Thrainer
  def testDisksAndDiskTemplate(self):
1821 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1822 27619aac Thomas Thrainer
                         disk_template=constants.DT_PLAIN,
1823 27619aac Thomas Thrainer
                         disks=[[constants.DDM_ADD, -1, {}]])
1824 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1825 27619aac Thomas Thrainer
      op, "Disk template conversion and other disk changes not supported at"
1826 27619aac Thomas Thrainer
          " the same time")
1827 27619aac Thomas Thrainer
1828 27619aac Thomas Thrainer
  def testDiskTemplateToMirroredNoRemoteNode(self):
1829 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1830 27619aac Thomas Thrainer
                         disk_template=constants.DT_DRBD8)
1831 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1832 27619aac Thomas Thrainer
      op, "Changing the disk template to a mirrored one requires specifying"
1833 27619aac Thomas Thrainer
          " a secondary node")
1834 27619aac Thomas Thrainer
1835 27619aac Thomas Thrainer
  def testPrimaryNodeToOldPrimaryNode(self):
1836 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1837 27619aac Thomas Thrainer
                         pnode=self.master.name)
1838 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1839 27619aac Thomas Thrainer
1840 27619aac Thomas Thrainer
  def testPrimaryNodeChange(self):
1841 27619aac Thomas Thrainer
    node = self.cfg.AddNewNode()
1842 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1843 27619aac Thomas Thrainer
                         pnode=node.name)
1844 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1845 27619aac Thomas Thrainer
1846 27619aac Thomas Thrainer
  def testPrimaryNodeChangeRunningInstance(self):
1847 27619aac Thomas Thrainer
    node = self.cfg.AddNewNode()
1848 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.running_op,
1849 27619aac Thomas Thrainer
                         pnode=node.name)
1850 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Instance is still running")
1851 27619aac Thomas Thrainer
1852 27619aac Thomas Thrainer
  def testOsChange(self):
1853 27619aac Thomas Thrainer
    os = self.cfg.CreateOs(supported_variants=[])
1854 27619aac Thomas Thrainer
    self.rpc.call_os_get.return_value = \
1855 27619aac Thomas Thrainer
      self.RpcResultsBuilder() \
1856 27619aac Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master, os)
1857 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1858 27619aac Thomas Thrainer
                         os_name=os.name)
1859 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1860 27619aac Thomas Thrainer
1861 27619aac Thomas Thrainer
  def testVCpuChange(self):
1862 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1863 27619aac Thomas Thrainer
                         beparams={
1864 27619aac Thomas Thrainer
                           constants.BE_VCPUS: 4
1865 27619aac Thomas Thrainer
                         })
1866 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1867 27619aac Thomas Thrainer
1868 27619aac Thomas Thrainer
  def testWrongCpuMask(self):
1869 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1870 27619aac Thomas Thrainer
                         beparams={
1871 27619aac Thomas Thrainer
                           constants.BE_VCPUS: 4
1872 27619aac Thomas Thrainer
                         },
1873 27619aac Thomas Thrainer
                         hvparams={
1874 27619aac Thomas Thrainer
                           constants.HV_CPU_MASK: "1,2:3,4"
1875 27619aac Thomas Thrainer
                         })
1876 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1877 27619aac Thomas Thrainer
      op, "Number of vCPUs .* does not match the CPU mask .*")
1878 27619aac Thomas Thrainer
1879 27619aac Thomas Thrainer
  def testCorrectCpuMask(self):
1880 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1881 27619aac Thomas Thrainer
                         beparams={
1882 27619aac Thomas Thrainer
                           constants.BE_VCPUS: 4
1883 27619aac Thomas Thrainer
                         },
1884 27619aac Thomas Thrainer
                         hvparams={
1885 27619aac Thomas Thrainer
                           constants.HV_CPU_MASK: "1,2:3,4:all:1,4"
1886 27619aac Thomas Thrainer
                         })
1887 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1888 27619aac Thomas Thrainer
1889 27619aac Thomas Thrainer
  def testOsParams(self):
1890 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1891 27619aac Thomas Thrainer
                         osparams={
1892 27619aac Thomas Thrainer
                           self.os.supported_parameters[0]: "test_param_val"
1893 27619aac Thomas Thrainer
                         })
1894 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1895 27619aac Thomas Thrainer
1896 27619aac Thomas Thrainer
  def testIncreaseMemoryTooMuch(self):
1897 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.running_op,
1898 27619aac Thomas Thrainer
                         beparams={
1899 27619aac Thomas Thrainer
                           constants.BE_MAXMEM:
1900 27619aac Thomas Thrainer
                             self.mocked_master_memory_free * 2
1901 27619aac Thomas Thrainer
                         })
1902 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1903 27619aac Thomas Thrainer
      op, "This change will prevent the instance from starting")
1904 27619aac Thomas Thrainer
1905 27619aac Thomas Thrainer
  def testIncreaseMemory(self):
1906 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.running_op,
1907 27619aac Thomas Thrainer
                         beparams={
1908 27619aac Thomas Thrainer
                           constants.BE_MAXMEM: self.mocked_master_memory_free
1909 27619aac Thomas Thrainer
                         })
1910 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1911 27619aac Thomas Thrainer
1912 27619aac Thomas Thrainer
  def testIncreaseMemoryTooMuchForSecondary(self):
1913 27619aac Thomas Thrainer
    inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP,
1914 27619aac Thomas Thrainer
                                   disk_template=constants.DT_DRBD8,
1915 27619aac Thomas Thrainer
                                   secondary_node=self.snode)
1916 27619aac Thomas Thrainer
    self.rpc.call_instance_info.side_effect = [
1917 27619aac Thomas Thrainer
      self.RpcResultsBuilder()
1918 27619aac Thomas Thrainer
        .CreateSuccessfulNodeResult(self.master,
1919 27619aac Thomas Thrainer
                                    {
1920 27619aac Thomas Thrainer
                                      "memory":
1921 27619aac Thomas Thrainer
                                        self.mocked_snode_memory_free * 2,
1922 27619aac Thomas Thrainer
                                      "vcpus": self.mocked_running_inst_vcpus,
1923 27619aac Thomas Thrainer
                                      "state": self.mocked_running_inst_state,
1924 27619aac Thomas Thrainer
                                      "time": self.mocked_running_inst_time
1925 27619aac Thomas Thrainer
                                    })]
1926 27619aac Thomas Thrainer
1927 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1928 27619aac Thomas Thrainer
                         instance_name=inst.name,
1929 27619aac Thomas Thrainer
                         beparams={
1930 27619aac Thomas Thrainer
                           constants.BE_MAXMEM:
1931 27619aac Thomas Thrainer
                             self.mocked_snode_memory_free * 2,
1932 27619aac Thomas Thrainer
                           constants.BE_AUTO_BALANCE: True
1933 27619aac Thomas Thrainer
                         })
1934 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1935 27619aac Thomas Thrainer
      op, "This change will prevent the instance from failover to its"
1936 27619aac Thomas Thrainer
          " secondary node")
1937 27619aac Thomas Thrainer
1938 27619aac Thomas Thrainer
  def testInvalidRuntimeMemory(self):
1939 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.running_op,
1940 27619aac Thomas Thrainer
                         runtime_mem=self.mocked_master_memory_free * 2)
1941 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1942 27619aac Thomas Thrainer
      op, "Instance .* must have memory between .* and .* of memory")
1943 27619aac Thomas Thrainer
1944 27619aac Thomas Thrainer
  def testIncreaseRuntimeMemory(self):
1945 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.running_op,
1946 27619aac Thomas Thrainer
                         runtime_mem=self.mocked_master_memory_free,
1947 27619aac Thomas Thrainer
                         beparams={
1948 27619aac Thomas Thrainer
                           constants.BE_MAXMEM: self.mocked_master_memory_free
1949 27619aac Thomas Thrainer
                         })
1950 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1951 27619aac Thomas Thrainer
1952 27619aac Thomas Thrainer
  def testAddNicWithPoolIpNoNetwork(self):
1953 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1954 27619aac Thomas Thrainer
                         nics=[(constants.DDM_ADD, -1,
1955 27619aac Thomas Thrainer
                                {
1956 27619aac Thomas Thrainer
                                  constants.INIC_IP: constants.NIC_IP_POOL
1957 27619aac Thomas Thrainer
                                })])
1958 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1959 27619aac Thomas Thrainer
      op, "If ip=pool, parameter network cannot be none")
1960 27619aac Thomas Thrainer
1961 27619aac Thomas Thrainer
  def testAddNicWithPoolIp(self):
1962 27619aac Thomas Thrainer
    net = self.cfg.AddNewNetwork()
1963 27619aac Thomas Thrainer
    self.cfg.ConnectNetworkToGroup(net, self.group)
1964 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1965 27619aac Thomas Thrainer
                         nics=[(constants.DDM_ADD, -1,
1966 27619aac Thomas Thrainer
                                {
1967 27619aac Thomas Thrainer
                                  constants.INIC_IP: constants.NIC_IP_POOL,
1968 27619aac Thomas Thrainer
                                  constants.INIC_NETWORK: net.name
1969 27619aac Thomas Thrainer
                                })])
1970 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1971 27619aac Thomas Thrainer
1972 27619aac Thomas Thrainer
  def testAddNicWithInvalidIp(self):
1973 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1974 27619aac Thomas Thrainer
                         nics=[(constants.DDM_ADD, -1,
1975 27619aac Thomas Thrainer
                                {
1976 27619aac Thomas Thrainer
                                  constants.INIC_IP: "invalid"
1977 27619aac Thomas Thrainer
                                })])
1978 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
1979 27619aac Thomas Thrainer
      op, "Invalid IP address")
1980 27619aac Thomas Thrainer
1981 27619aac Thomas Thrainer
  def testAddNic(self):
1982 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1983 27619aac Thomas Thrainer
                         nics=[(constants.DDM_ADD, -1, {})])
1984 27619aac Thomas Thrainer
    self.ExecOpCode(op)
1985 27619aac Thomas Thrainer
1986 fda3d987 Dimitris Aragiorgis
  def testHotAddNic(self):
1987 fda3d987 Dimitris Aragiorgis
    op = self.CopyOpCode(self.op,
1988 fda3d987 Dimitris Aragiorgis
                         nics=[(constants.DDM_ADD, -1, {})],
1989 fda3d987 Dimitris Aragiorgis
                         hotplug=True)
1990 fda3d987 Dimitris Aragiorgis
    self.ExecOpCode(op)
1991 24711492 Dimitris Aragiorgis
    self.assertTrue(self.rpc.call_hotplug_supported.called)
1992 fda3d987 Dimitris Aragiorgis
    self.assertTrue(self.rpc.call_hotplug_device.called)
1993 fda3d987 Dimitris Aragiorgis
1994 27619aac Thomas Thrainer
  def testAddNicWithIp(self):
1995 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
1996 27619aac Thomas Thrainer
                         nics=[(constants.DDM_ADD, -1,
1997 27619aac Thomas Thrainer
                                {
1998 27619aac Thomas Thrainer
                                  constants.INIC_IP: "2.3.1.4"
1999 27619aac Thomas Thrainer
                                })])
2000 27619aac Thomas Thrainer
    self.ExecOpCode(op)
2001 27619aac Thomas Thrainer
2002 27619aac Thomas Thrainer
  def testModifyNicRoutedWithoutIp(self):
2003 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2004 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, 0,
2005 27619aac Thomas Thrainer
                                {
2006 27619aac Thomas Thrainer
                                  constants.INIC_MODE: constants.NIC_MODE_ROUTED
2007 27619aac Thomas Thrainer
                                })])
2008 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
2009 27619aac Thomas Thrainer
      op, "Cannot set the NIC IP address to None on a routed NIC")
2010 27619aac Thomas Thrainer
2011 27619aac Thomas Thrainer
  def testModifyNicSetMac(self):
2012 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2013 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, 0,
2014 27619aac Thomas Thrainer
                                {
2015 27619aac Thomas Thrainer
                                  constants.INIC_MAC: "0a:12:95:15:bf:75"
2016 27619aac Thomas Thrainer
                                })])
2017 27619aac Thomas Thrainer
    self.ExecOpCode(op)
2018 27619aac Thomas Thrainer
2019 27619aac Thomas Thrainer
  def testModifyNicWithPoolIpNoNetwork(self):
2020 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2021 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, -1,
2022 27619aac Thomas Thrainer
                                {
2023 27619aac Thomas Thrainer
                                  constants.INIC_IP: constants.NIC_IP_POOL
2024 27619aac Thomas Thrainer
                                })])
2025 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
2026 27619aac Thomas Thrainer
      op, "ip=pool, but no network found")
2027 27619aac Thomas Thrainer
2028 27619aac Thomas Thrainer
  def testModifyNicSetNet(self):
2029 27619aac Thomas Thrainer
    old_net = self.cfg.AddNewNetwork()
2030 27619aac Thomas Thrainer
    self.cfg.ConnectNetworkToGroup(old_net, self.group)
2031 27619aac Thomas Thrainer
    inst = self.cfg.AddNewInstance(nics=[
2032 27619aac Thomas Thrainer
      self.cfg.CreateNic(network=old_net,
2033 4256f8fe Sebastian Gebhard
                         ip="198.51.100.2")])
2034 27619aac Thomas Thrainer
2035 27619aac Thomas Thrainer
    new_net = self.cfg.AddNewNetwork(mac_prefix="be")
2036 27619aac Thomas Thrainer
    self.cfg.ConnectNetworkToGroup(new_net, self.group)
2037 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2038 27619aac Thomas Thrainer
                         instance_name=inst.name,
2039 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, 0,
2040 27619aac Thomas Thrainer
                                {
2041 27619aac Thomas Thrainer
                                  constants.INIC_NETWORK: new_net.name
2042 27619aac Thomas Thrainer
                                })])
2043 27619aac Thomas Thrainer
    self.ExecOpCode(op)
2044 27619aac Thomas Thrainer
2045 27619aac Thomas Thrainer
  def testModifyNicSetLinkWhileConnected(self):
2046 27619aac Thomas Thrainer
    old_net = self.cfg.AddNewNetwork()
2047 27619aac Thomas Thrainer
    self.cfg.ConnectNetworkToGroup(old_net, self.group)
2048 27619aac Thomas Thrainer
    inst = self.cfg.AddNewInstance(nics=[
2049 27619aac Thomas Thrainer
      self.cfg.CreateNic(network=old_net)])
2050 27619aac Thomas Thrainer
2051 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2052 27619aac Thomas Thrainer
                         instance_name=inst.name,
2053 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, 0,
2054 27619aac Thomas Thrainer
                                {
2055 27619aac Thomas Thrainer
                                  constants.INIC_LINK: "mock_link"
2056 27619aac Thomas Thrainer
                                })])
2057 27619aac Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
2058 27619aac Thomas Thrainer
      op, "Not allowed to change link or mode of a NIC that is connected"
2059 27619aac Thomas Thrainer
          " to a network")
2060 27619aac Thomas Thrainer
2061 27619aac Thomas Thrainer
  def testModifyNicSetNetAndIp(self):
2062 27619aac Thomas Thrainer
    net = self.cfg.AddNewNetwork(mac_prefix="be", network="123.123.123.0/24")
2063 27619aac Thomas Thrainer
    self.cfg.ConnectNetworkToGroup(net, self.group)
2064 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2065 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, 0,
2066 27619aac Thomas Thrainer
                                {
2067 27619aac Thomas Thrainer
                                  constants.INIC_NETWORK: net.name,
2068 27619aac Thomas Thrainer
                                  constants.INIC_IP: "123.123.123.1"
2069 27619aac Thomas Thrainer
                                })])
2070 27619aac Thomas Thrainer
    self.ExecOpCode(op)
2071 27619aac Thomas Thrainer
2072 27619aac Thomas Thrainer
  def testModifyNic(self):
2073 27619aac Thomas Thrainer
    op = self.CopyOpCode(self.op,
2074 27619aac Thomas Thrainer
                         nics=[(constants.DDM_MODIFY, 0, {})])
2075 27619aac Thomas Thrainer
    self.ExecOpCode(op)
2076 27619aac Thomas Thrainer
2077 fda3d987 Dimitris Aragiorgis
  def testHotModifyNic(self):
2078 fda3d987 Dimitris Aragiorgis
    op = self.CopyOpCode(self.op,
2079 fda3d987 Dimitris Aragiorgis
                         nics=[(constants.DDM_MODIFY, 0, {})],
2080 fda3d987 Dimitris Aragiorgis
                         hotplug=True)
2081 fda3d987 Dimitris Aragiorgis
    self.ExecOpCode(op)
2082 24711492 Dimitris Aragiorgis
    self.assertTrue(self.rpc.call_hotplug_supported.called)
2083 fda3d987 Dimitris Aragiorgis
    self.assertTrue(self.rpc.call_hotplug_device.called)