Add unit test for LUGroupQuery
[ganeti-local] / test / py / cmdlib / group_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2008, 2011, 2012, 2013 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Tests for LUGroup*
23
24 """
25
26 from ganeti import constants
27 from ganeti import opcodes
28 from ganeti import query
29
30 from testsupport import *
31
32 import testutils
33
34
35 class TestLUGroupAdd(CmdlibTestCase):
36   def testAddExistingGroup(self):
37     self.cfg.AddNewNodeGroup(name="existing_group")
38
39     op = opcodes.OpGroupAdd(group_name="existing_group")
40     self.ExecOpCodeExpectOpPrereqError(
41       op, "Desired group name 'existing_group' already exists")
42
43   def testAddNewGroup(self):
44     op = opcodes.OpGroupAdd(group_name="new_group")
45
46     self.ExecOpCode(op)
47
48     self.mcpu.assertLogIsEmpty()
49
50   def testAddNewGroupParams(self):
51     ndparams = {constants.ND_EXCLUSIVE_STORAGE: True}
52     hv_state = {constants.HT_FAKE: {constants.HVST_CPU_TOTAL: 8}}
53     disk_state = {
54       constants.LD_LV: {
55         "mock_vg": {constants.DS_DISK_TOTAL: 10}
56       }
57     }
58     diskparams = {constants.DT_RBD: {constants.RBD_POOL: "mock_pool"}}
59     ipolicy = constants.IPOLICY_DEFAULTS
60     op = opcodes.OpGroupAdd(group_name="new_group",
61                             ndparams=ndparams,
62                             hv_state=hv_state,
63                             disk_state=disk_state,
64                             diskparams=diskparams,
65                             ipolicy=ipolicy)
66
67     self.ExecOpCode(op)
68
69     self.mcpu.assertLogIsEmpty()
70
71   def testAddNewGroupInvalidDiskparams(self):
72     diskparams = {constants.DT_RBD: {constants.LV_STRIPES: 1}}
73     op = opcodes.OpGroupAdd(group_name="new_group",
74                             diskparams=diskparams)
75
76     self.ExecOpCodeExpectOpPrereqError(
77       op, "Provided option keys not supported")
78
79   def testAddNewGroupInvalidIPolic(self):
80     ipolicy = {"invalid_key": "value"}
81     op = opcodes.OpGroupAdd(group_name="new_group",
82                             ipolicy=ipolicy)
83
84     self.ExecOpCodeExpectOpPrereqError(op, "Invalid keys in ipolicy")
85
86
87 class TestLUGroupAssignNodes(CmdlibTestCase):
88   def __init__(self, methodName='runTest'):
89     super(TestLUGroupAssignNodes, self).__init__(methodName)
90
91     self.op = opcodes.OpGroupAssignNodes(group_name="default",
92                                          nodes=[])
93
94   def testAssignSingleNode(self):
95     node = self.cfg.AddNewNode()
96     op = self.CopyOpCode(self.op, nodes=[node.name])
97
98     self.ExecOpCode(op)
99
100     self.mcpu.assertLogIsEmpty()
101
102   def _BuildSplitInstanceSituation(self):
103     node = self.cfg.AddNewNode()
104     self.cfg.AddNewInstance(disk_template=constants.DT_DRBD8,
105                             primary_node=self.master,
106                             secondary_node=node)
107     group = self.cfg.AddNewNodeGroup()
108
109     return (node, group)
110
111   def testSplitInstanceNoForce(self):
112     (node, group) = self._BuildSplitInstanceSituation()
113     op = opcodes.OpGroupAssignNodes(group_name=group.name,
114                                     nodes=[node.name])
115
116     self.ExecOpCodeExpectOpExecError(
117       op, "instances get split by this change and --force was not given")
118
119   def testSplitInstanceForce(self):
120     (node, group) = self._BuildSplitInstanceSituation()
121
122     node2 = self.cfg.AddNewNode(group=group)
123     self.cfg.AddNewInstance(disk_template=constants.DT_DRBD8,
124                             primary_node=self.master,
125                             secondary_node=node2)
126
127     op = opcodes.OpGroupAssignNodes(group_name=group.name,
128                                     nodes=[node.name],
129                                     force=True)
130
131     self.ExecOpCode(op)
132
133     self.mcpu.assertLogContainsRegex("will split the following instances")
134     self.mcpu.assertLogContainsRegex(
135       "instances continue to be split across groups")
136
137
138   @withLockedLU
139   def testCheckAssignmentForSplitInstances(self, lu):
140     g1 = self.cfg.AddNewNodeGroup()
141     g2 = self.cfg.AddNewNodeGroup()
142     g3 = self.cfg.AddNewNodeGroup()
143
144     for (n, g) in [("n1a", g1), ("n1b", g1), ("n2a", g2), ("n2b", g2),
145                    ("n3a", g3), ("n3b", g3), ("n3c", g3)]:
146       self.cfg.AddNewNode(uuid=n, group=g.uuid)
147
148     for uuid, pnode, snode in [("inst1a", "n1a", "n1b"),
149                                ("inst1b", "n1b", "n1a"),
150                                ("inst2a", "n2a", "n2b"),
151                                ("inst3a", "n3a", None),
152                                ("inst3b", "n3b", "n1b"),
153                                ("inst3c", "n3b", "n2b")]:
154       dt = constants.DT_DISKLESS if snode is None else constants.DT_DRBD8
155       self.cfg.AddNewInstance(uuid=uuid,
156                               disk_template=dt,
157                               primary_node=pnode,
158                               secondary_node=snode)
159
160     # Test first with the existing state.
161     (new, prev) = lu.CheckAssignmentForSplitInstances(
162       [], self.cfg.GetAllNodesInfo(), self.cfg.GetAllInstancesInfo())
163
164     self.assertEqual([], new)
165     self.assertEqual(set(["inst3b", "inst3c"]), set(prev))
166
167     # And now some changes.
168     (new, prev) = lu.CheckAssignmentForSplitInstances(
169       [("n1b", g3.uuid)],
170       self.cfg.GetAllNodesInfo(),
171       self.cfg.GetAllInstancesInfo())
172
173     self.assertEqual(set(["inst1a", "inst1b"]), set(new))
174     self.assertEqual(set(["inst3c"]), set(prev))
175
176
177 class TestLUGroupQuery(CmdlibTestCase):
178   def setUp(self):
179     super(TestLUGroupQuery, self).setUp()
180     self.fields = query._BuildGroupFields().keys()
181
182   def testInvalidGroupName(self):
183     op = opcodes.OpGroupQuery(names=["does_not_exist"],
184                               output_fields=self.fields)
185
186     self.ExecOpCodeExpectOpPrereqError(op, "Some groups do not exist")
187
188   def testQueryAllGroups(self):
189     op = opcodes.OpGroupQuery(output_fields=self.fields)
190
191     self.ExecOpCode(op)
192
193     self.mcpu.assertLogIsEmpty()
194
195   def testQueryGroupsByNameAndUuid(self):
196     group1 = self.cfg.AddNewNodeGroup()
197     group2 = self.cfg.AddNewNodeGroup()
198
199     node1 = self.cfg.AddNewNode(group=group1)
200     node2 = self.cfg.AddNewNode(group=group1)
201     self.cfg.AddNewInstance(disk_template=constants.DT_DRBD8,
202                             primary_node=node1,
203                             secondary_node=node2)
204     self.cfg.AddNewInstance(primary_node=node2)
205
206     op = opcodes.OpGroupQuery(names=[group1.name, group2.uuid],
207                               output_fields=self.fields)
208
209     self.ExecOpCode(op)
210
211     self.mcpu.assertLogIsEmpty()
212
213
214 if __name__ == "__main__":
215   testutils.GanetiTestProgram()