Statistics
| Branch: | Tag: | Revision:

root / test / py / cmdlib / group_unittest.py @ fbeb41e6

History | View | Annotate | Download (15.1 kB)

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

24 8129eac1 Thomas Thrainer
"""
25 8129eac1 Thomas Thrainer
26 3c768f88 Thomas Thrainer
import itertools
27 3c768f88 Thomas Thrainer
28 8129eac1 Thomas Thrainer
from ganeti import constants
29 8129eac1 Thomas Thrainer
from ganeti import opcodes
30 ae904a6b Thomas Thrainer
from ganeti import query
31 8129eac1 Thomas Thrainer
32 8129eac1 Thomas Thrainer
from testsupport import *
33 8129eac1 Thomas Thrainer
34 8129eac1 Thomas Thrainer
import testutils
35 8129eac1 Thomas Thrainer
36 8129eac1 Thomas Thrainer
37 9051a390 Thomas Thrainer
class TestLUGroupAdd(CmdlibTestCase):
38 9051a390 Thomas Thrainer
  def testAddExistingGroup(self):
39 9051a390 Thomas Thrainer
    self.cfg.AddNewNodeGroup(name="existing_group")
40 9051a390 Thomas Thrainer
41 9051a390 Thomas Thrainer
    op = opcodes.OpGroupAdd(group_name="existing_group")
42 9051a390 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
43 9051a390 Thomas Thrainer
      op, "Desired group name 'existing_group' already exists")
44 9051a390 Thomas Thrainer
45 9051a390 Thomas Thrainer
  def testAddNewGroup(self):
46 9051a390 Thomas Thrainer
    op = opcodes.OpGroupAdd(group_name="new_group")
47 9051a390 Thomas Thrainer
48 9051a390 Thomas Thrainer
    self.ExecOpCode(op)
49 9051a390 Thomas Thrainer
50 9051a390 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
51 9051a390 Thomas Thrainer
52 9051a390 Thomas Thrainer
  def testAddNewGroupParams(self):
53 9051a390 Thomas Thrainer
    ndparams = {constants.ND_EXCLUSIVE_STORAGE: True}
54 9051a390 Thomas Thrainer
    hv_state = {constants.HT_FAKE: {constants.HVST_CPU_TOTAL: 8}}
55 9051a390 Thomas Thrainer
    disk_state = {
56 0c5f1b13 Thomas Thrainer
      constants.DT_PLAIN: {
57 9051a390 Thomas Thrainer
        "mock_vg": {constants.DS_DISK_TOTAL: 10}
58 9051a390 Thomas Thrainer
      }
59 9051a390 Thomas Thrainer
    }
60 9051a390 Thomas Thrainer
    diskparams = {constants.DT_RBD: {constants.RBD_POOL: "mock_pool"}}
61 9051a390 Thomas Thrainer
    ipolicy = constants.IPOLICY_DEFAULTS
62 9051a390 Thomas Thrainer
    op = opcodes.OpGroupAdd(group_name="new_group",
63 9051a390 Thomas Thrainer
                            ndparams=ndparams,
64 9051a390 Thomas Thrainer
                            hv_state=hv_state,
65 9051a390 Thomas Thrainer
                            disk_state=disk_state,
66 9051a390 Thomas Thrainer
                            diskparams=diskparams,
67 9051a390 Thomas Thrainer
                            ipolicy=ipolicy)
68 9051a390 Thomas Thrainer
69 9051a390 Thomas Thrainer
    self.ExecOpCode(op)
70 9051a390 Thomas Thrainer
71 9051a390 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
72 9051a390 Thomas Thrainer
73 9051a390 Thomas Thrainer
  def testAddNewGroupInvalidDiskparams(self):
74 9051a390 Thomas Thrainer
    diskparams = {constants.DT_RBD: {constants.LV_STRIPES: 1}}
75 9051a390 Thomas Thrainer
    op = opcodes.OpGroupAdd(group_name="new_group",
76 9051a390 Thomas Thrainer
                            diskparams=diskparams)
77 9051a390 Thomas Thrainer
78 9051a390 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
79 9051a390 Thomas Thrainer
      op, "Provided option keys not supported")
80 9051a390 Thomas Thrainer
81 9051a390 Thomas Thrainer
  def testAddNewGroupInvalidIPolic(self):
82 9051a390 Thomas Thrainer
    ipolicy = {"invalid_key": "value"}
83 9051a390 Thomas Thrainer
    op = opcodes.OpGroupAdd(group_name="new_group",
84 9051a390 Thomas Thrainer
                            ipolicy=ipolicy)
85 9051a390 Thomas Thrainer
86 9051a390 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Invalid keys in ipolicy")
87 9051a390 Thomas Thrainer
88 9051a390 Thomas Thrainer
89 8129eac1 Thomas Thrainer
class TestLUGroupAssignNodes(CmdlibTestCase):
90 8129eac1 Thomas Thrainer
  def __init__(self, methodName='runTest'):
91 8129eac1 Thomas Thrainer
    super(TestLUGroupAssignNodes, self).__init__(methodName)
92 8129eac1 Thomas Thrainer
93 8129eac1 Thomas Thrainer
    self.op = opcodes.OpGroupAssignNodes(group_name="default",
94 8129eac1 Thomas Thrainer
                                         nodes=[])
95 8129eac1 Thomas Thrainer
96 d189f139 Thomas Thrainer
  def testAssignSingleNode(self):
97 d189f139 Thomas Thrainer
    node = self.cfg.AddNewNode()
98 d189f139 Thomas Thrainer
    op = self.CopyOpCode(self.op, nodes=[node.name])
99 d189f139 Thomas Thrainer
100 d189f139 Thomas Thrainer
    self.ExecOpCode(op)
101 d189f139 Thomas Thrainer
102 d189f139 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
103 d189f139 Thomas Thrainer
104 d189f139 Thomas Thrainer
  def _BuildSplitInstanceSituation(self):
105 d189f139 Thomas Thrainer
    node = self.cfg.AddNewNode()
106 d189f139 Thomas Thrainer
    self.cfg.AddNewInstance(disk_template=constants.DT_DRBD8,
107 d189f139 Thomas Thrainer
                            primary_node=self.master,
108 d189f139 Thomas Thrainer
                            secondary_node=node)
109 d189f139 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
110 d189f139 Thomas Thrainer
111 d189f139 Thomas Thrainer
    return (node, group)
112 d189f139 Thomas Thrainer
113 d189f139 Thomas Thrainer
  def testSplitInstanceNoForce(self):
114 d189f139 Thomas Thrainer
    (node, group) = self._BuildSplitInstanceSituation()
115 d189f139 Thomas Thrainer
    op = opcodes.OpGroupAssignNodes(group_name=group.name,
116 d189f139 Thomas Thrainer
                                    nodes=[node.name])
117 d189f139 Thomas Thrainer
118 d189f139 Thomas Thrainer
    self.ExecOpCodeExpectOpExecError(
119 d189f139 Thomas Thrainer
      op, "instances get split by this change and --force was not given")
120 d189f139 Thomas Thrainer
121 d189f139 Thomas Thrainer
  def testSplitInstanceForce(self):
122 d189f139 Thomas Thrainer
    (node, group) = self._BuildSplitInstanceSituation()
123 d189f139 Thomas Thrainer
124 d189f139 Thomas Thrainer
    node2 = self.cfg.AddNewNode(group=group)
125 d189f139 Thomas Thrainer
    self.cfg.AddNewInstance(disk_template=constants.DT_DRBD8,
126 d189f139 Thomas Thrainer
                            primary_node=self.master,
127 d189f139 Thomas Thrainer
                            secondary_node=node2)
128 d189f139 Thomas Thrainer
129 d189f139 Thomas Thrainer
    op = opcodes.OpGroupAssignNodes(group_name=group.name,
130 d189f139 Thomas Thrainer
                                    nodes=[node.name],
131 d189f139 Thomas Thrainer
                                    force=True)
132 d189f139 Thomas Thrainer
133 d189f139 Thomas Thrainer
    self.ExecOpCode(op)
134 d189f139 Thomas Thrainer
135 d189f139 Thomas Thrainer
    self.mcpu.assertLogContainsRegex("will split the following instances")
136 d189f139 Thomas Thrainer
    self.mcpu.assertLogContainsRegex(
137 d189f139 Thomas Thrainer
      "instances continue to be split across groups")
138 d189f139 Thomas Thrainer
139 d189f139 Thomas Thrainer
140 8129eac1 Thomas Thrainer
  @withLockedLU
141 8129eac1 Thomas Thrainer
  def testCheckAssignmentForSplitInstances(self, lu):
142 8129eac1 Thomas Thrainer
    g1 = self.cfg.AddNewNodeGroup()
143 8129eac1 Thomas Thrainer
    g2 = self.cfg.AddNewNodeGroup()
144 8129eac1 Thomas Thrainer
    g3 = self.cfg.AddNewNodeGroup()
145 8129eac1 Thomas Thrainer
146 8129eac1 Thomas Thrainer
    for (n, g) in [("n1a", g1), ("n1b", g1), ("n2a", g2), ("n2b", g2),
147 8129eac1 Thomas Thrainer
                   ("n3a", g3), ("n3b", g3), ("n3c", g3)]:
148 8129eac1 Thomas Thrainer
      self.cfg.AddNewNode(uuid=n, group=g.uuid)
149 8129eac1 Thomas Thrainer
150 8129eac1 Thomas Thrainer
    for uuid, pnode, snode in [("inst1a", "n1a", "n1b"),
151 8129eac1 Thomas Thrainer
                               ("inst1b", "n1b", "n1a"),
152 8129eac1 Thomas Thrainer
                               ("inst2a", "n2a", "n2b"),
153 8129eac1 Thomas Thrainer
                               ("inst3a", "n3a", None),
154 8129eac1 Thomas Thrainer
                               ("inst3b", "n3b", "n1b"),
155 8129eac1 Thomas Thrainer
                               ("inst3c", "n3b", "n2b")]:
156 8129eac1 Thomas Thrainer
      dt = constants.DT_DISKLESS if snode is None else constants.DT_DRBD8
157 8129eac1 Thomas Thrainer
      self.cfg.AddNewInstance(uuid=uuid,
158 8129eac1 Thomas Thrainer
                              disk_template=dt,
159 8129eac1 Thomas Thrainer
                              primary_node=pnode,
160 8129eac1 Thomas Thrainer
                              secondary_node=snode)
161 8129eac1 Thomas Thrainer
162 8129eac1 Thomas Thrainer
    # Test first with the existing state.
163 8129eac1 Thomas Thrainer
    (new, prev) = lu.CheckAssignmentForSplitInstances(
164 8129eac1 Thomas Thrainer
      [], self.cfg.GetAllNodesInfo(), self.cfg.GetAllInstancesInfo())
165 8129eac1 Thomas Thrainer
166 8129eac1 Thomas Thrainer
    self.assertEqual([], new)
167 8129eac1 Thomas Thrainer
    self.assertEqual(set(["inst3b", "inst3c"]), set(prev))
168 8129eac1 Thomas Thrainer
169 8129eac1 Thomas Thrainer
    # And now some changes.
170 8129eac1 Thomas Thrainer
    (new, prev) = lu.CheckAssignmentForSplitInstances(
171 9051a390 Thomas Thrainer
      [("n1b", g3.uuid)],
172 9051a390 Thomas Thrainer
      self.cfg.GetAllNodesInfo(),
173 9051a390 Thomas Thrainer
      self.cfg.GetAllInstancesInfo())
174 8129eac1 Thomas Thrainer
175 8129eac1 Thomas Thrainer
    self.assertEqual(set(["inst1a", "inst1b"]), set(new))
176 8129eac1 Thomas Thrainer
    self.assertEqual(set(["inst3c"]), set(prev))
177 8129eac1 Thomas Thrainer
178 8129eac1 Thomas Thrainer
179 ae904a6b Thomas Thrainer
class TestLUGroupQuery(CmdlibTestCase):
180 ae904a6b Thomas Thrainer
  def setUp(self):
181 ae904a6b Thomas Thrainer
    super(TestLUGroupQuery, self).setUp()
182 ae904a6b Thomas Thrainer
    self.fields = query._BuildGroupFields().keys()
183 ae904a6b Thomas Thrainer
184 ae904a6b Thomas Thrainer
  def testInvalidGroupName(self):
185 ae904a6b Thomas Thrainer
    op = opcodes.OpGroupQuery(names=["does_not_exist"],
186 ae904a6b Thomas Thrainer
                              output_fields=self.fields)
187 ae904a6b Thomas Thrainer
188 ae904a6b Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Some groups do not exist")
189 ae904a6b Thomas Thrainer
190 ae904a6b Thomas Thrainer
  def testQueryAllGroups(self):
191 ae904a6b Thomas Thrainer
    op = opcodes.OpGroupQuery(output_fields=self.fields)
192 ae904a6b Thomas Thrainer
193 ae904a6b Thomas Thrainer
    self.ExecOpCode(op)
194 ae904a6b Thomas Thrainer
195 ae904a6b Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
196 ae904a6b Thomas Thrainer
197 ae904a6b Thomas Thrainer
  def testQueryGroupsByNameAndUuid(self):
198 ae904a6b Thomas Thrainer
    group1 = self.cfg.AddNewNodeGroup()
199 ae904a6b Thomas Thrainer
    group2 = self.cfg.AddNewNodeGroup()
200 ae904a6b Thomas Thrainer
201 ae904a6b Thomas Thrainer
    node1 = self.cfg.AddNewNode(group=group1)
202 ae904a6b Thomas Thrainer
    node2 = self.cfg.AddNewNode(group=group1)
203 ae904a6b Thomas Thrainer
    self.cfg.AddNewInstance(disk_template=constants.DT_DRBD8,
204 ae904a6b Thomas Thrainer
                            primary_node=node1,
205 ae904a6b Thomas Thrainer
                            secondary_node=node2)
206 ae904a6b Thomas Thrainer
    self.cfg.AddNewInstance(primary_node=node2)
207 ae904a6b Thomas Thrainer
208 ae904a6b Thomas Thrainer
    op = opcodes.OpGroupQuery(names=[group1.name, group2.uuid],
209 ae904a6b Thomas Thrainer
                              output_fields=self.fields)
210 ae904a6b Thomas Thrainer
211 ae904a6b Thomas Thrainer
    self.ExecOpCode(op)
212 ae904a6b Thomas Thrainer
213 ae904a6b Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
214 ae904a6b Thomas Thrainer
215 ae904a6b Thomas Thrainer
216 67d2f602 Thomas Thrainer
class TestLUGroupSetParams(CmdlibTestCase):
217 67d2f602 Thomas Thrainer
  def testNoModifications(self):
218 67d2f602 Thomas Thrainer
    op = opcodes.OpGroupSetParams(group_name=self.group.name)
219 67d2f602 Thomas Thrainer
220 67d2f602 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op,
221 67d2f602 Thomas Thrainer
                                       "Please pass at least one modification")
222 67d2f602 Thomas Thrainer
223 67d2f602 Thomas Thrainer
  def testModifyingAll(self):
224 67d2f602 Thomas Thrainer
    ndparams = {constants.ND_EXCLUSIVE_STORAGE: True}
225 67d2f602 Thomas Thrainer
    hv_state = {constants.HT_FAKE: {constants.HVST_CPU_TOTAL: 8}}
226 67d2f602 Thomas Thrainer
    disk_state = {
227 0c5f1b13 Thomas Thrainer
      constants.DT_PLAIN: {
228 67d2f602 Thomas Thrainer
        "mock_vg": {constants.DS_DISK_TOTAL: 10}
229 67d2f602 Thomas Thrainer
      }
230 67d2f602 Thomas Thrainer
    }
231 67d2f602 Thomas Thrainer
    diskparams = {constants.DT_RBD: {constants.RBD_POOL: "mock_pool"}}
232 67d2f602 Thomas Thrainer
    ipolicy = {constants.IPOLICY_DTS: [constants.DT_DRBD8]}
233 67d2f602 Thomas Thrainer
    op = opcodes.OpGroupSetParams(group_name=self.group.name,
234 67d2f602 Thomas Thrainer
                                  ndparams=ndparams,
235 67d2f602 Thomas Thrainer
                                  hv_state=hv_state,
236 67d2f602 Thomas Thrainer
                                  disk_state=disk_state,
237 67d2f602 Thomas Thrainer
                                  diskparams=diskparams,
238 67d2f602 Thomas Thrainer
                                  ipolicy=ipolicy)
239 67d2f602 Thomas Thrainer
240 67d2f602 Thomas Thrainer
    self.ExecOpCode(op)
241 67d2f602 Thomas Thrainer
242 67d2f602 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
243 67d2f602 Thomas Thrainer
244 67d2f602 Thomas Thrainer
  def testInvalidDiskparams(self):
245 67d2f602 Thomas Thrainer
    diskparams = {constants.DT_RBD: {constants.LV_STRIPES: 1}}
246 67d2f602 Thomas Thrainer
    op = opcodes.OpGroupSetParams(group_name=self.group.name,
247 67d2f602 Thomas Thrainer
                                  diskparams=diskparams)
248 67d2f602 Thomas Thrainer
249 67d2f602 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
250 67d2f602 Thomas Thrainer
      op, "Provided option keys not supported")
251 67d2f602 Thomas Thrainer
252 67d2f602 Thomas Thrainer
  def testIPolicyNewViolations(self):
253 67d2f602 Thomas Thrainer
    self.cfg.AddNewInstance(beparams={constants.BE_VCPUS: 8})
254 67d2f602 Thomas Thrainer
255 67d2f602 Thomas Thrainer
    min_max = dict(constants.ISPECS_MINMAX_DEFAULTS)
256 67d2f602 Thomas Thrainer
    min_max[constants.ISPECS_MAX].update({constants.ISPEC_CPU_COUNT: 2})
257 67d2f602 Thomas Thrainer
    ipolicy = {constants.ISPECS_MINMAX: [min_max]}
258 67d2f602 Thomas Thrainer
    op = opcodes.OpGroupSetParams(group_name=self.group.name,
259 67d2f602 Thomas Thrainer
                                  ipolicy=ipolicy)
260 67d2f602 Thomas Thrainer
261 67d2f602 Thomas Thrainer
    self.ExecOpCode(op)
262 67d2f602 Thomas Thrainer
263 67d2f602 Thomas Thrainer
    self.assertLogContainsRegex(
264 67d2f602 Thomas Thrainer
      "After the ipolicy change the following instances violate them")
265 67d2f602 Thomas Thrainer
266 67d2f602 Thomas Thrainer
267 8ef0c3eb Thomas Thrainer
class TestLUGroupRemove(CmdlibTestCase):
268 8ef0c3eb Thomas Thrainer
  def testNonEmptyGroup(self):
269 8ef0c3eb Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
270 8ef0c3eb Thomas Thrainer
    self.cfg.AddNewNode(group=group)
271 8ef0c3eb Thomas Thrainer
    op = opcodes.OpGroupRemove(group_name=group.name)
272 8ef0c3eb Thomas Thrainer
273 8ef0c3eb Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(op, "Group .* not empty")
274 8ef0c3eb Thomas Thrainer
275 8ef0c3eb Thomas Thrainer
  def testRemoveLastGroup(self):
276 8ef0c3eb Thomas Thrainer
    self.master.group = "invalid_group"
277 8ef0c3eb Thomas Thrainer
    op = opcodes.OpGroupRemove(group_name=self.group.name)
278 8ef0c3eb Thomas Thrainer
279 8ef0c3eb Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
280 8ef0c3eb Thomas Thrainer
      op, "Group .* is the only group, cannot be removed")
281 8ef0c3eb Thomas Thrainer
282 8ef0c3eb Thomas Thrainer
  def testRemoveGroup(self):
283 8ef0c3eb Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
284 8ef0c3eb Thomas Thrainer
    op = opcodes.OpGroupRemove(group_name=group.name)
285 8ef0c3eb Thomas Thrainer
286 8ef0c3eb Thomas Thrainer
    self.ExecOpCode(op)
287 8ef0c3eb Thomas Thrainer
288 8ef0c3eb Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
289 8ef0c3eb Thomas Thrainer
290 8ef0c3eb Thomas Thrainer
291 7ac3f7b0 Thomas Thrainer
class TestLUGroupRename(CmdlibTestCase):
292 7ac3f7b0 Thomas Thrainer
  def testRenameToExistingName(self):
293 7ac3f7b0 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
294 7ac3f7b0 Thomas Thrainer
    op = opcodes.OpGroupRename(group_name=group.name,
295 7ac3f7b0 Thomas Thrainer
                               new_name=self.group.name)
296 7ac3f7b0 Thomas Thrainer
297 7ac3f7b0 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
298 7ac3f7b0 Thomas Thrainer
      op, "Desired new name .* clashes with existing node group")
299 7ac3f7b0 Thomas Thrainer
300 7ac3f7b0 Thomas Thrainer
  def testRename(self):
301 7ac3f7b0 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
302 7ac3f7b0 Thomas Thrainer
    op = opcodes.OpGroupRename(group_name=group.name,
303 7ac3f7b0 Thomas Thrainer
                               new_name="new_group_name")
304 7ac3f7b0 Thomas Thrainer
305 7ac3f7b0 Thomas Thrainer
    self.ExecOpCode(op)
306 7ac3f7b0 Thomas Thrainer
307 7ac3f7b0 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
308 7ac3f7b0 Thomas Thrainer
309 4b8f9420 Thomas Thrainer
310 4b8f9420 Thomas Thrainer
class TestLUGroupEvacuate(CmdlibTestCase):
311 4b8f9420 Thomas Thrainer
  def testEvacuateEmptyGroup(self):
312 4b8f9420 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
313 4b8f9420 Thomas Thrainer
    op = opcodes.OpGroupEvacuate(group_name=group.name)
314 4b8f9420 Thomas Thrainer
315 4b8f9420 Thomas Thrainer
    self.iallocator_cls.return_value.result = ([], [], [])
316 4b8f9420 Thomas Thrainer
317 4b8f9420 Thomas Thrainer
    self.ExecOpCode(op)
318 4b8f9420 Thomas Thrainer
319 4b8f9420 Thomas Thrainer
  def testEvacuateOnlyGroup(self):
320 4b8f9420 Thomas Thrainer
    op = opcodes.OpGroupEvacuate(group_name=self.group.name)
321 4b8f9420 Thomas Thrainer
322 4b8f9420 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
323 4b8f9420 Thomas Thrainer
      op, "There are no possible target groups")
324 4b8f9420 Thomas Thrainer
325 4b8f9420 Thomas Thrainer
  def testEvacuateWithTargetGroups(self):
326 4b8f9420 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
327 4b8f9420 Thomas Thrainer
    self.cfg.AddNewNode(group=group)
328 4b8f9420 Thomas Thrainer
    self.cfg.AddNewNode(group=group)
329 4b8f9420 Thomas Thrainer
330 4b8f9420 Thomas Thrainer
    target_group1 = self.cfg.AddNewNodeGroup()
331 4b8f9420 Thomas Thrainer
    target_group2 = self.cfg.AddNewNodeGroup()
332 4b8f9420 Thomas Thrainer
    op = opcodes.OpGroupEvacuate(group_name=group.name,
333 4b8f9420 Thomas Thrainer
                                 target_groups=[target_group1.name,
334 4b8f9420 Thomas Thrainer
                                                target_group2.name])
335 4b8f9420 Thomas Thrainer
336 4b8f9420 Thomas Thrainer
    self.iallocator_cls.return_value.result = ([], [], [])
337 4b8f9420 Thomas Thrainer
338 4b8f9420 Thomas Thrainer
    self.ExecOpCode(op)
339 4b8f9420 Thomas Thrainer
340 4b8f9420 Thomas Thrainer
  def testFailingIAllocator(self):
341 4b8f9420 Thomas Thrainer
    group = self.cfg.AddNewNodeGroup()
342 4b8f9420 Thomas Thrainer
    op = opcodes.OpGroupEvacuate(group_name=group.name)
343 4b8f9420 Thomas Thrainer
344 4b8f9420 Thomas Thrainer
    self.iallocator_cls.return_value.success = False
345 4b8f9420 Thomas Thrainer
346 4b8f9420 Thomas Thrainer
    self.ExecOpCodeExpectOpPrereqError(
347 4b8f9420 Thomas Thrainer
      op, "Can't compute group evacuation using iallocator")
348 4b8f9420 Thomas Thrainer
349 4b8f9420 Thomas Thrainer
350 3c768f88 Thomas Thrainer
class TestLUGroupVerifyDisks(CmdlibTestCase):
351 3c768f88 Thomas Thrainer
  def testNoInstances(self):
352 3c768f88 Thomas Thrainer
    op = opcodes.OpGroupVerifyDisks(group_name=self.group.name)
353 3c768f88 Thomas Thrainer
354 3c768f88 Thomas Thrainer
    self.ExecOpCode(op)
355 3c768f88 Thomas Thrainer
356 3c768f88 Thomas Thrainer
    self.mcpu.assertLogIsEmpty()
357 3c768f88 Thomas Thrainer
358 3c768f88 Thomas Thrainer
  def testOfflineAndFailingNode(self):
359 3c768f88 Thomas Thrainer
    node = self.cfg.AddNewNode(offline=True)
360 3c768f88 Thomas Thrainer
    self.cfg.AddNewInstance(primary_node=node,
361 3c768f88 Thomas Thrainer
                            admin_state=constants.ADMINST_UP)
362 3c768f88 Thomas Thrainer
    self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
363 3c768f88 Thomas Thrainer
    self.rpc.call_lv_list.return_value = \
364 3c768f88 Thomas Thrainer
      self.RpcResultsBuilder() \
365 3c768f88 Thomas Thrainer
        .AddFailedNode(self.master) \
366 3c768f88 Thomas Thrainer
        .AddOfflineNode(node) \
367 3c768f88 Thomas Thrainer
        .Build()
368 3c768f88 Thomas Thrainer
369 3c768f88 Thomas Thrainer
    op = opcodes.OpGroupVerifyDisks(group_name=self.group.name)
370 3c768f88 Thomas Thrainer
371 3c768f88 Thomas Thrainer
    (nerrors, offline, missing) = self.ExecOpCode(op)
372 3c768f88 Thomas Thrainer
373 3c768f88 Thomas Thrainer
    self.assertEqual(1, len(nerrors))
374 3c768f88 Thomas Thrainer
    self.assertEqual(0, len(offline))
375 3c768f88 Thomas Thrainer
    self.assertEqual(2, len(missing))
376 3c768f88 Thomas Thrainer
377 3c768f88 Thomas Thrainer
  def testValidNodeResult(self):
378 3c768f88 Thomas Thrainer
    self.cfg.AddNewInstance(
379 0c5f1b13 Thomas Thrainer
      disks=[self.cfg.CreateDisk(dev_type=constants.DT_PLAIN),
380 0c5f1b13 Thomas Thrainer
             self.cfg.CreateDisk(dev_type=constants.DT_PLAIN)
381 3c768f88 Thomas Thrainer
             ],
382 3c768f88 Thomas Thrainer
      admin_state=constants.ADMINST_UP)
383 3c768f88 Thomas Thrainer
    self.rpc.call_lv_list.return_value = \
384 3c768f88 Thomas Thrainer
      self.RpcResultsBuilder() \
385 3c768f88 Thomas Thrainer
        .AddSuccessfulNode(self.master, {
386 3c768f88 Thomas Thrainer
          "mockvg/mock_disk_1": (None, None, True),
387 3c768f88 Thomas Thrainer
          "mockvg/mock_disk_2": (None, None, False)
388 3c768f88 Thomas Thrainer
        }) \
389 3c768f88 Thomas Thrainer
        .Build()
390 3c768f88 Thomas Thrainer
391 3c768f88 Thomas Thrainer
    op = opcodes.OpGroupVerifyDisks(group_name=self.group.name)
392 3c768f88 Thomas Thrainer
393 3c768f88 Thomas Thrainer
    (nerrors, offline, missing) = self.ExecOpCode(op)
394 3c768f88 Thomas Thrainer
395 3c768f88 Thomas Thrainer
    self.assertEqual(0, len(nerrors))
396 3c768f88 Thomas Thrainer
    self.assertEqual(1, len(offline))
397 3c768f88 Thomas Thrainer
    self.assertEqual(0, len(missing))
398 3c768f88 Thomas Thrainer
399 3c768f88 Thomas Thrainer
  def testDrbdDisk(self):
400 3c768f88 Thomas Thrainer
    node1 = self.cfg.AddNewNode()
401 3c768f88 Thomas Thrainer
    node2 = self.cfg.AddNewNode()
402 3c768f88 Thomas Thrainer
    node3 = self.cfg.AddNewNode()
403 3c768f88 Thomas Thrainer
    node4 = self.cfg.AddNewNode()
404 3c768f88 Thomas Thrainer
405 0c5f1b13 Thomas Thrainer
    valid_disk = self.cfg.CreateDisk(dev_type=constants.DT_DRBD8,
406 3c768f88 Thomas Thrainer
                                     primary_node=node1,
407 3c768f88 Thomas Thrainer
                                     secondary_node=node2)
408 0c5f1b13 Thomas Thrainer
    broken_disk = self.cfg.CreateDisk(dev_type=constants.DT_DRBD8,
409 3c768f88 Thomas Thrainer
                                      primary_node=node1,
410 3c768f88 Thomas Thrainer
                                      secondary_node=node2)
411 0c5f1b13 Thomas Thrainer
    failing_node_disk = self.cfg.CreateDisk(dev_type=constants.DT_DRBD8,
412 3c768f88 Thomas Thrainer
                                            primary_node=node3,
413 3c768f88 Thomas Thrainer
                                            secondary_node=node4)
414 3c768f88 Thomas Thrainer
415 3c768f88 Thomas Thrainer
    self.cfg.AddNewInstance(disks=[valid_disk, broken_disk],
416 3c768f88 Thomas Thrainer
                            primary_node=node1,
417 3c768f88 Thomas Thrainer
                            admin_state=constants.ADMINST_UP)
418 3c768f88 Thomas Thrainer
    self.cfg.AddNewInstance(disks=[failing_node_disk],
419 3c768f88 Thomas Thrainer
                            primary_node=node3,
420 3c768f88 Thomas Thrainer
                            admin_state=constants.ADMINST_UP)
421 3c768f88 Thomas Thrainer
422 3c768f88 Thomas Thrainer
    lv_list_result = dict(("/".join(disk.logical_id), (None, None, True))
423 3c768f88 Thomas Thrainer
                          for disk in itertools.chain(valid_disk.children,
424 3c768f88 Thomas Thrainer
                                                      broken_disk.children))
425 3c768f88 Thomas Thrainer
    self.rpc.call_lv_list.return_value = \
426 3c768f88 Thomas Thrainer
      self.RpcResultsBuilder() \
427 3c768f88 Thomas Thrainer
        .AddSuccessfulNode(node1, lv_list_result) \
428 3c768f88 Thomas Thrainer
        .AddSuccessfulNode(node2, lv_list_result) \
429 3c768f88 Thomas Thrainer
        .AddFailedNode(node3) \
430 3c768f88 Thomas Thrainer
        .AddFailedNode(node4) \
431 3c768f88 Thomas Thrainer
        .Build()
432 3c768f88 Thomas Thrainer
433 3c768f88 Thomas Thrainer
    def GetDrbdNeedsActivationResult(node_uuid, *_):
434 3c768f88 Thomas Thrainer
      if node_uuid == node1.uuid:
435 3c768f88 Thomas Thrainer
        return self.RpcResultsBuilder() \
436 3c768f88 Thomas Thrainer
                 .CreateSuccessfulNodeResult(node1, [])
437 3c768f88 Thomas Thrainer
      elif node_uuid == node2.uuid:
438 3c768f88 Thomas Thrainer
        return self.RpcResultsBuilder() \
439 3c768f88 Thomas Thrainer
                 .CreateSuccessfulNodeResult(node2, [broken_disk.uuid])
440 3c768f88 Thomas Thrainer
      elif node_uuid == node3.uuid or node_uuid == node4.uuid:
441 3c768f88 Thomas Thrainer
        return self.RpcResultsBuilder() \
442 3c768f88 Thomas Thrainer
                 .CreateFailedNodeResult(node_uuid)
443 3c768f88 Thomas Thrainer
444 3c768f88 Thomas Thrainer
    self.rpc.call_drbd_needs_activation.side_effect = \
445 3c768f88 Thomas Thrainer
      GetDrbdNeedsActivationResult
446 3c768f88 Thomas Thrainer
447 3c768f88 Thomas Thrainer
    op = opcodes.OpGroupVerifyDisks(group_name=self.group.name)
448 3c768f88 Thomas Thrainer
449 3c768f88 Thomas Thrainer
    (nerrors, offline, missing) = self.ExecOpCode(op)
450 3c768f88 Thomas Thrainer
451 3c768f88 Thomas Thrainer
    self.assertEqual(2, len(nerrors))
452 3c768f88 Thomas Thrainer
    self.assertEqual(1, len(offline))
453 3c768f88 Thomas Thrainer
    self.assertEqual(1, len(missing))
454 3c768f88 Thomas Thrainer
455 3c768f88 Thomas Thrainer
456 8129eac1 Thomas Thrainer
if __name__ == "__main__":
457 8129eac1 Thomas Thrainer
  testutils.GanetiTestProgram()