root / test / py / cmdlib / node_unittest.py @ ac156ecd
History | View | Annotate | Download (9 kB)
1 | 55ba3ad6 | Sebastian Gebhard | #!/usr/bin/python
|
---|---|---|---|
2 | 55ba3ad6 | Sebastian Gebhard | #
|
3 | 55ba3ad6 | Sebastian Gebhard | |
4 | 55ba3ad6 | Sebastian Gebhard | # Copyright (C) 2013 Google Inc.
|
5 | 55ba3ad6 | Sebastian Gebhard | #
|
6 | 55ba3ad6 | Sebastian Gebhard | # This program is free software; you can redistribute it and/or modify
|
7 | 55ba3ad6 | Sebastian Gebhard | # it under the terms of the GNU General Public License as published by
|
8 | 55ba3ad6 | Sebastian Gebhard | # the Free Software Foundation; either version 2 of the License, or
|
9 | 55ba3ad6 | Sebastian Gebhard | # (at your option) any later version.
|
10 | 55ba3ad6 | Sebastian Gebhard | #
|
11 | 55ba3ad6 | Sebastian Gebhard | # This program is distributed in the hope that it will be useful, but
|
12 | 55ba3ad6 | Sebastian Gebhard | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 55ba3ad6 | Sebastian Gebhard | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 55ba3ad6 | Sebastian Gebhard | # General Public License for more details.
|
15 | 55ba3ad6 | Sebastian Gebhard | #
|
16 | 55ba3ad6 | Sebastian Gebhard | # You should have received a copy of the GNU General Public License
|
17 | 55ba3ad6 | Sebastian Gebhard | # along with this program; if not, write to the Free Software
|
18 | 55ba3ad6 | Sebastian Gebhard | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | 55ba3ad6 | Sebastian Gebhard | # 02110-1301, USA.
|
20 | 55ba3ad6 | Sebastian Gebhard | |
21 | 55ba3ad6 | Sebastian Gebhard | |
22 | 55ba3ad6 | Sebastian Gebhard | """Tests for LUNode*
|
23 | 55ba3ad6 | Sebastian Gebhard |
|
24 | 55ba3ad6 | Sebastian Gebhard | """
|
25 | 55ba3ad6 | Sebastian Gebhard | |
26 | 55ba3ad6 | Sebastian Gebhard | from collections import defaultdict |
27 | 55ba3ad6 | Sebastian Gebhard | |
28 | 47cce79a | Sebastian Gebhard | from ganeti import compat |
29 | 55ba3ad6 | Sebastian Gebhard | from ganeti import constants |
30 | 55ba3ad6 | Sebastian Gebhard | from ganeti import objects |
31 | 55ba3ad6 | Sebastian Gebhard | from ganeti import opcodes |
32 | 47cce79a | Sebastian Gebhard | from ganeti import errors |
33 | 55ba3ad6 | Sebastian Gebhard | |
34 | 55ba3ad6 | Sebastian Gebhard | from testsupport import * |
35 | 55ba3ad6 | Sebastian Gebhard | |
36 | 55ba3ad6 | Sebastian Gebhard | import testutils |
37 | 55ba3ad6 | Sebastian Gebhard | |
38 | 07e68848 | Thomas Thrainer | |
39 | 47cce79a | Sebastian Gebhard | # pylint: disable=W0613
|
40 | 47cce79a | Sebastian Gebhard | def _TcpPingFailSecondary(cfg, mock_fct, target, port, timeout=None, |
41 | 47cce79a | Sebastian Gebhard | live_port_needed=None, source=None): |
42 | 47cce79a | Sebastian Gebhard | # This will return True if target is in 192.0.2.0/24 (primary range)
|
43 | 47cce79a | Sebastian Gebhard | # and False if not.
|
44 | 47cce79a | Sebastian Gebhard | return "192.0.2." in target |
45 | 55ba3ad6 | Sebastian Gebhard | |
46 | 07e68848 | Thomas Thrainer | |
47 | 55ba3ad6 | Sebastian Gebhard | class TestLUNodeAdd(CmdlibTestCase): |
48 | 55ba3ad6 | Sebastian Gebhard | def setUp(self): |
49 | 55ba3ad6 | Sebastian Gebhard | super(TestLUNodeAdd, self).setUp() |
50 | 55ba3ad6 | Sebastian Gebhard | |
51 | 55ba3ad6 | Sebastian Gebhard | # One node for testing readding:
|
52 | 55ba3ad6 | Sebastian Gebhard | self.node_readd = self.cfg.AddNewNode() |
53 | 55ba3ad6 | Sebastian Gebhard | self.op_readd = opcodes.OpNodeAdd(node_name=self.node_readd.name, |
54 | 55ba3ad6 | Sebastian Gebhard | readd=True,
|
55 | 55ba3ad6 | Sebastian Gebhard | primary_ip=self.node_readd.primary_ip,
|
56 | 55ba3ad6 | Sebastian Gebhard | secondary_ip=self.node_readd.secondary_ip)
|
57 | 55ba3ad6 | Sebastian Gebhard | |
58 | 55ba3ad6 | Sebastian Gebhard | # One node for testing adding:
|
59 | 55ba3ad6 | Sebastian Gebhard | # don't add to configuration now!
|
60 | 55ba3ad6 | Sebastian Gebhard | self.node_add = objects.Node(name="node_add", |
61 | 55ba3ad6 | Sebastian Gebhard | primary_ip="192.0.2.200",
|
62 | 55ba3ad6 | Sebastian Gebhard | secondary_ip="203.0.113.200")
|
63 | 55ba3ad6 | Sebastian Gebhard | |
64 | 55ba3ad6 | Sebastian Gebhard | self.op_add = opcodes.OpNodeAdd(node_name=self.node_add.name, |
65 | 55ba3ad6 | Sebastian Gebhard | primary_ip=self.node_add.primary_ip,
|
66 | 55ba3ad6 | Sebastian Gebhard | secondary_ip=self.node_add.secondary_ip)
|
67 | 55ba3ad6 | Sebastian Gebhard | |
68 | 55ba3ad6 | Sebastian Gebhard | self.netutils_mod.TcpPing.return_value = True |
69 | 55ba3ad6 | Sebastian Gebhard | |
70 | 55ba3ad6 | Sebastian Gebhard | self.mocked_dns_rpc = self.rpc_mod.DnsOnlyRunner.return_value |
71 | 55ba3ad6 | Sebastian Gebhard | |
72 | 55ba3ad6 | Sebastian Gebhard | self.mocked_dns_rpc.call_version.return_value = \
|
73 | 55ba3ad6 | Sebastian Gebhard | self.RpcResultsBuilder(use_node_names=True) \ |
74 | 55ba3ad6 | Sebastian Gebhard | .AddSuccessfulNode(self.node_add, constants.CONFIG_VERSION) \
|
75 | 55ba3ad6 | Sebastian Gebhard | .AddSuccessfulNode(self.node_readd, constants.CONFIG_VERSION) \
|
76 | 55ba3ad6 | Sebastian Gebhard | .Build() |
77 | 55ba3ad6 | Sebastian Gebhard | |
78 | 55ba3ad6 | Sebastian Gebhard | node_verify_result = \ |
79 | 55ba3ad6 | Sebastian Gebhard | self.RpcResultsBuilder() \
|
80 | 55ba3ad6 | Sebastian Gebhard | .CreateSuccessfulNodeResult(self.node_add, {constants.NV_NODELIST: []})
|
81 | 55ba3ad6 | Sebastian Gebhard | # we can't know the node's UUID in advance, so use defaultdict here
|
82 | 55ba3ad6 | Sebastian Gebhard | self.rpc.call_node_verify.return_value = \
|
83 | 55ba3ad6 | Sebastian Gebhard | defaultdict(lambda: node_verify_result, {})
|
84 | 55ba3ad6 | Sebastian Gebhard | |
85 | 55ba3ad6 | Sebastian Gebhard | def testOvsNoLink(self): |
86 | 55ba3ad6 | Sebastian Gebhard | ndparams = { |
87 | 55ba3ad6 | Sebastian Gebhard | constants.ND_OVS: True,
|
88 | 55ba3ad6 | Sebastian Gebhard | constants.ND_OVS_NAME: "testswitch",
|
89 | 55ba3ad6 | Sebastian Gebhard | constants.ND_OVS_LINK: None,
|
90 | 55ba3ad6 | Sebastian Gebhard | } |
91 | 55ba3ad6 | Sebastian Gebhard | |
92 | 55ba3ad6 | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, |
93 | 55ba3ad6 | Sebastian Gebhard | ndparams=ndparams) |
94 | 55ba3ad6 | Sebastian Gebhard | |
95 | 55ba3ad6 | Sebastian Gebhard | self.ExecOpCode(op)
|
96 | 55ba3ad6 | Sebastian Gebhard | self.assertLogContainsRegex(
|
97 | 55ba3ad6 | Sebastian Gebhard | "No physical interface for OpenvSwitch was given."
|
98 | 55ba3ad6 | Sebastian Gebhard | " OpenvSwitch will not have an outside connection."
|
99 | 55ba3ad6 | Sebastian Gebhard | " This might not be what you want")
|
100 | 55ba3ad6 | Sebastian Gebhard | |
101 | 55ba3ad6 | Sebastian Gebhard | created_node = self.cfg.GetNodeInfoByName(op.node_name)
|
102 | 55ba3ad6 | Sebastian Gebhard | self.assertEqual(ndparams[constants.ND_OVS],
|
103 | 55ba3ad6 | Sebastian Gebhard | created_node.ndparams.get(constants.ND_OVS, None))
|
104 | 55ba3ad6 | Sebastian Gebhard | self.assertEqual(ndparams[constants.ND_OVS_NAME],
|
105 | 55ba3ad6 | Sebastian Gebhard | created_node.ndparams.get(constants.ND_OVS_NAME, None))
|
106 | 55ba3ad6 | Sebastian Gebhard | self.assertEqual(ndparams[constants.ND_OVS_LINK],
|
107 | 55ba3ad6 | Sebastian Gebhard | created_node.ndparams.get(constants.ND_OVS_LINK, None))
|
108 | 55ba3ad6 | Sebastian Gebhard | |
109 | 55ba3ad6 | Sebastian Gebhard | def testWithoutOVS(self): |
110 | 55ba3ad6 | Sebastian Gebhard | self.ExecOpCode(self.op_add) |
111 | 55ba3ad6 | Sebastian Gebhard | |
112 | 55ba3ad6 | Sebastian Gebhard | created_node = self.cfg.GetNodeInfoByName(self.op_add.node_name) |
113 | 55ba3ad6 | Sebastian Gebhard | self.assertEqual(None, |
114 | 55ba3ad6 | Sebastian Gebhard | created_node.ndparams.get(constants.ND_OVS, None))
|
115 | 55ba3ad6 | Sebastian Gebhard | |
116 | 55ba3ad6 | Sebastian Gebhard | def testWithOVS(self): |
117 | 55ba3ad6 | Sebastian Gebhard | ndparams = { |
118 | 55ba3ad6 | Sebastian Gebhard | constants.ND_OVS: True,
|
119 | 55ba3ad6 | Sebastian Gebhard | constants.ND_OVS_LINK: "eth2",
|
120 | 55ba3ad6 | Sebastian Gebhard | } |
121 | 55ba3ad6 | Sebastian Gebhard | |
122 | 55ba3ad6 | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, |
123 | 55ba3ad6 | Sebastian Gebhard | ndparams=ndparams) |
124 | 55ba3ad6 | Sebastian Gebhard | |
125 | 55ba3ad6 | Sebastian Gebhard | self.ExecOpCode(op)
|
126 | 55ba3ad6 | Sebastian Gebhard | |
127 | 55ba3ad6 | Sebastian Gebhard | created_node = self.cfg.GetNodeInfoByName(op.node_name)
|
128 | 55ba3ad6 | Sebastian Gebhard | self.assertEqual(ndparams[constants.ND_OVS],
|
129 | 55ba3ad6 | Sebastian Gebhard | created_node.ndparams.get(constants.ND_OVS, None))
|
130 | 55ba3ad6 | Sebastian Gebhard | self.assertEqual(ndparams[constants.ND_OVS_LINK],
|
131 | 55ba3ad6 | Sebastian Gebhard | created_node.ndparams.get(constants.ND_OVS_LINK, None))
|
132 | 55ba3ad6 | Sebastian Gebhard | |
133 | 47cce79a | Sebastian Gebhard | def testReaddingMaster(self): |
134 | 47cce79a | Sebastian Gebhard | op = opcodes.OpNodeAdd(node_name=self.cfg.GetMasterNodeName(),
|
135 | 47cce79a | Sebastian Gebhard | readd=True)
|
136 | 47cce79a | Sebastian Gebhard | |
137 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Cannot readd the master node") |
138 | 47cce79a | Sebastian Gebhard | |
139 | 47cce79a | Sebastian Gebhard | def testReaddNotVmCapableNode(self): |
140 | 47cce79a | Sebastian Gebhard | self.cfg.AddNewInstance(primary_node=self.node_readd) |
141 | 47cce79a | Sebastian Gebhard | self.netutils_mod.GetHostname.return_value = \
|
142 | 47cce79a | Sebastian Gebhard | HostnameMock(self.node_readd.name, self.node_readd.primary_ip) |
143 | 47cce79a | Sebastian Gebhard | |
144 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_readd, vm_capable=False) |
145 | 47cce79a | Sebastian Gebhard | |
146 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Node .* being re-added with" |
147 | 47cce79a | Sebastian Gebhard | " vm_capable flag set to false, but it"
|
148 | 47cce79a | Sebastian Gebhard | " already holds instances")
|
149 | 47cce79a | Sebastian Gebhard | |
150 | 47cce79a | Sebastian Gebhard | def testReaddAndPassNodeGroup(self): |
151 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_readd,group="groupname") |
152 | 47cce79a | Sebastian Gebhard | |
153 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Cannot pass a node group when a" |
154 | 47cce79a | Sebastian Gebhard | " node is being readded")
|
155 | 47cce79a | Sebastian Gebhard | |
156 | 47cce79a | Sebastian Gebhard | def testPrimaryIPv6(self): |
157 | 47cce79a | Sebastian Gebhard | self.master.secondary_ip = self.master.primary_ip |
158 | 47cce79a | Sebastian Gebhard | |
159 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, primary_ip="2001:DB8::1", |
160 | 47cce79a | Sebastian Gebhard | secondary_ip=self.REMOVE)
|
161 | 47cce79a | Sebastian Gebhard | |
162 | 47cce79a | Sebastian Gebhard | self.ExecOpCode(op)
|
163 | 47cce79a | Sebastian Gebhard | |
164 | 47cce79a | Sebastian Gebhard | def testInvalidSecondaryIP(self): |
165 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, secondary_ip="333.444.555.777") |
166 | 47cce79a | Sebastian Gebhard | |
167 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Secondary IP .* needs to be a valid" |
168 | 47cce79a | Sebastian Gebhard | " IPv4 address")
|
169 | 47cce79a | Sebastian Gebhard | |
170 | 47cce79a | Sebastian Gebhard | def testNodeAlreadyInCluster(self): |
171 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_readd, readd=False) |
172 | 47cce79a | Sebastian Gebhard | |
173 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Node %s is already in the" |
174 | 47cce79a | Sebastian Gebhard | " configuration" % self.node_readd.name) |
175 | 47cce79a | Sebastian Gebhard | |
176 | 47cce79a | Sebastian Gebhard | def testReaddNodeNotInConfiguration(self): |
177 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, readd=True) |
178 | 47cce79a | Sebastian Gebhard | |
179 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Node %s is not in the" |
180 | 47cce79a | Sebastian Gebhard | " configuration" % self.node_add.name) |
181 | 47cce79a | Sebastian Gebhard | |
182 | 47cce79a | Sebastian Gebhard | def testPrimaryIpConflict(self): |
183 | 47cce79a | Sebastian Gebhard | # In LUNodeAdd, DNS will resolve the node name to an IP address, that is
|
184 | 47cce79a | Sebastian Gebhard | # used to overwrite any given primary_ip value!
|
185 | 47cce79a | Sebastian Gebhard | # Thus we need to mock this DNS resolver here!
|
186 | 47cce79a | Sebastian Gebhard | self.netutils_mod.GetHostname.return_value = \
|
187 | 47cce79a | Sebastian Gebhard | HostnameMock(self.node_add.name, self.node_readd.primary_ip) |
188 | 47cce79a | Sebastian Gebhard | |
189 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add) |
190 | 47cce79a | Sebastian Gebhard | |
191 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "New node ip address.* conflict with" |
192 | 47cce79a | Sebastian Gebhard | " existing node")
|
193 | 47cce79a | Sebastian Gebhard | |
194 | 47cce79a | Sebastian Gebhard | def testSecondaryIpConflict(self): |
195 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, secondary_ip=self.node_readd.secondary_ip) |
196 | 47cce79a | Sebastian Gebhard | |
197 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "New node ip address.* conflict with" |
198 | 47cce79a | Sebastian Gebhard | " existing node")
|
199 | 47cce79a | Sebastian Gebhard | |
200 | 47cce79a | Sebastian Gebhard | def testReaddWithDifferentIP(self): |
201 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_readd, primary_ip="192.0.2.100", |
202 | 47cce79a | Sebastian Gebhard | secondary_ip="230.0.113.100")
|
203 | 47cce79a | Sebastian Gebhard | |
204 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Readded node doesn't have the same" |
205 | 47cce79a | Sebastian Gebhard | " IP address configuration as before")
|
206 | 47cce79a | Sebastian Gebhard | |
207 | 47cce79a | Sebastian Gebhard | |
208 | 47cce79a | Sebastian Gebhard | def testNodeHasSecondaryIpButNotMaster(self): |
209 | 47cce79a | Sebastian Gebhard | self.master.secondary_ip = self.master.primary_ip |
210 | 47cce79a | Sebastian Gebhard | |
211 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(self.op_add, "The master has no" |
212 | 47cce79a | Sebastian Gebhard | " secondary ip but the new node has one")
|
213 | 47cce79a | Sebastian Gebhard | |
214 | 47cce79a | Sebastian Gebhard | def testMasterHasSecondaryIpButNotNode(self): |
215 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add, secondary_ip=None) |
216 | 47cce79a | Sebastian Gebhard | |
217 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "The master has a secondary ip but" |
218 | 47cce79a | Sebastian Gebhard | " the new node doesn't have one")
|
219 | 47cce79a | Sebastian Gebhard | |
220 | 47cce79a | Sebastian Gebhard | def testNodeNotReachableByPing(self): |
221 | 47cce79a | Sebastian Gebhard | self.netutils_mod.TcpPing.return_value = False |
222 | 47cce79a | Sebastian Gebhard | |
223 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add) |
224 | 47cce79a | Sebastian Gebhard | |
225 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Node not reachable by ping") |
226 | 47cce79a | Sebastian Gebhard | |
227 | 47cce79a | Sebastian Gebhard | def testNodeNotReachableByPingOnSecondary(self): |
228 | 47cce79a | Sebastian Gebhard | self.netutils_mod.GetHostname.return_value = \
|
229 | 47cce79a | Sebastian Gebhard | HostnameMock(self.node_add.name, self.node_add.primary_ip) |
230 | 47cce79a | Sebastian Gebhard | self.netutils_mod.TcpPing.side_effect = \
|
231 | 47cce79a | Sebastian Gebhard | compat.partial(_TcpPingFailSecondary, self.cfg, self.netutils_mod.TcpPing) |
232 | 47cce79a | Sebastian Gebhard | |
233 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add) |
234 | 47cce79a | Sebastian Gebhard | |
235 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpPrereqError(op, "Node secondary ip not reachable by" |
236 | 47cce79a | Sebastian Gebhard | " TCP based ping to node daemon port")
|
237 | 47cce79a | Sebastian Gebhard | |
238 | 47cce79a | Sebastian Gebhard | def testCantGetVersion(self): |
239 | 47cce79a | Sebastian Gebhard | self.mocked_dns_rpc.call_version.return_value = \
|
240 | 47cce79a | Sebastian Gebhard | self.RpcResultsBuilder(use_node_names=True) \ |
241 | 47cce79a | Sebastian Gebhard | .AddErrorNode(self.node_add) \
|
242 | 47cce79a | Sebastian Gebhard | .Build() |
243 | 47cce79a | Sebastian Gebhard | |
244 | 47cce79a | Sebastian Gebhard | op = self.CopyOpCode(self.op_add) |
245 | 47cce79a | Sebastian Gebhard | self.ExecOpCodeExpectOpExecError(op, "Can't get version information from" |
246 | 47cce79a | Sebastian Gebhard | " node %s" % self.node_add.name) |
247 | 47cce79a | Sebastian Gebhard | |
248 | 55ba3ad6 | Sebastian Gebhard | if __name__ == "__main__": |
249 | 55ba3ad6 | Sebastian Gebhard | testutils.GanetiTestProgram() |