Statistics
| Branch: | Tag: | Revision:

root / test / py / cmdlib / node_unittest.py @ 14933c17

History | View | Annotate | Download (9.3 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 47cce79a Sebastian Gebhard
# pylint: disable=W0613
39 47cce79a Sebastian Gebhard
def _TcpPingFailSecondary(cfg, mock_fct, target, port, timeout=None,
40 47cce79a Sebastian Gebhard
                          live_port_needed=None, source=None):
41 47cce79a Sebastian Gebhard
  # This will return True if target is in 192.0.2.0/24 (primary range)
42 47cce79a Sebastian Gebhard
  # and False if not.
43 47cce79a Sebastian Gebhard
  return "192.0.2." in target
44 55ba3ad6 Sebastian Gebhard
45 55ba3ad6 Sebastian Gebhard
class TestLUNodeAdd(CmdlibTestCase):
46 55ba3ad6 Sebastian Gebhard
  def setUp(self):
47 55ba3ad6 Sebastian Gebhard
    super(TestLUNodeAdd, self).setUp()
48 55ba3ad6 Sebastian Gebhard
49 55ba3ad6 Sebastian Gebhard
    # One node for testing readding:
50 55ba3ad6 Sebastian Gebhard
    self.node_readd = self.cfg.AddNewNode()
51 55ba3ad6 Sebastian Gebhard
    self.op_readd = opcodes.OpNodeAdd(node_name=self.node_readd.name,
52 55ba3ad6 Sebastian Gebhard
                                      readd=True,
53 55ba3ad6 Sebastian Gebhard
                                      primary_ip=self.node_readd.primary_ip,
54 55ba3ad6 Sebastian Gebhard
                                      secondary_ip=self.node_readd.secondary_ip)
55 55ba3ad6 Sebastian Gebhard
56 55ba3ad6 Sebastian Gebhard
    # One node for testing adding:
57 55ba3ad6 Sebastian Gebhard
    # don't add to configuration now!
58 55ba3ad6 Sebastian Gebhard
    self.node_add = objects.Node(name="node_add",
59 55ba3ad6 Sebastian Gebhard
                                 primary_ip="192.0.2.200",
60 55ba3ad6 Sebastian Gebhard
                                 secondary_ip="203.0.113.200")
61 55ba3ad6 Sebastian Gebhard
62 55ba3ad6 Sebastian Gebhard
    self.op_add = opcodes.OpNodeAdd(node_name=self.node_add.name,
63 55ba3ad6 Sebastian Gebhard
                                    primary_ip=self.node_add.primary_ip,
64 55ba3ad6 Sebastian Gebhard
                                    secondary_ip=self.node_add.secondary_ip)
65 55ba3ad6 Sebastian Gebhard
66 55ba3ad6 Sebastian Gebhard
    self.netutils_mod.TcpPing.return_value = True
67 55ba3ad6 Sebastian Gebhard
68 55ba3ad6 Sebastian Gebhard
    self.mocked_dns_rpc = self.rpc_mod.DnsOnlyRunner.return_value
69 55ba3ad6 Sebastian Gebhard
70 55ba3ad6 Sebastian Gebhard
    self.mocked_dns_rpc.call_version.return_value = \
71 55ba3ad6 Sebastian Gebhard
      self.RpcResultsBuilder(use_node_names=True) \
72 55ba3ad6 Sebastian Gebhard
        .AddSuccessfulNode(self.node_add, constants.CONFIG_VERSION) \
73 55ba3ad6 Sebastian Gebhard
        .AddSuccessfulNode(self.node_readd, constants.CONFIG_VERSION) \
74 55ba3ad6 Sebastian Gebhard
        .Build()
75 55ba3ad6 Sebastian Gebhard
76 55ba3ad6 Sebastian Gebhard
    node_verify_result = \
77 55ba3ad6 Sebastian Gebhard
      self.RpcResultsBuilder() \
78 55ba3ad6 Sebastian Gebhard
        .CreateSuccessfulNodeResult(self.node_add, {constants.NV_NODELIST: []})
79 55ba3ad6 Sebastian Gebhard
    # we can't know the node's UUID in advance, so use defaultdict here
80 55ba3ad6 Sebastian Gebhard
    self.rpc.call_node_verify.return_value = \
81 55ba3ad6 Sebastian Gebhard
      defaultdict(lambda: node_verify_result, {})
82 55ba3ad6 Sebastian Gebhard
83 55ba3ad6 Sebastian Gebhard
  def testOvsParamsButNotEnabled(self):
84 55ba3ad6 Sebastian Gebhard
    ndparams = {
85 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS: False,
86 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS_NAME: "testswitch",
87 55ba3ad6 Sebastian Gebhard
    }
88 55ba3ad6 Sebastian Gebhard
89 55ba3ad6 Sebastian Gebhard
    op = self.CopyOpCode(self.op_add,
90 55ba3ad6 Sebastian Gebhard
                         ndparams=ndparams)
91 55ba3ad6 Sebastian Gebhard
92 55ba3ad6 Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "OpenvSwitch is not enabled")
93 55ba3ad6 Sebastian Gebhard
94 55ba3ad6 Sebastian Gebhard
  def testOvsNoLink(self):
95 55ba3ad6 Sebastian Gebhard
    ndparams = {
96 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS: True,
97 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS_NAME: "testswitch",
98 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS_LINK: None,
99 55ba3ad6 Sebastian Gebhard
    }
100 55ba3ad6 Sebastian Gebhard
101 55ba3ad6 Sebastian Gebhard
    op = self.CopyOpCode(self.op_add,
102 55ba3ad6 Sebastian Gebhard
                         ndparams=ndparams)
103 55ba3ad6 Sebastian Gebhard
104 55ba3ad6 Sebastian Gebhard
    self.ExecOpCode(op)
105 55ba3ad6 Sebastian Gebhard
    self.assertLogContainsRegex(
106 55ba3ad6 Sebastian Gebhard
      "No physical interface for OpenvSwitch was given."
107 55ba3ad6 Sebastian Gebhard
      " OpenvSwitch will not have an outside connection."
108 55ba3ad6 Sebastian Gebhard
      " This might not be what you want")
109 55ba3ad6 Sebastian Gebhard
110 55ba3ad6 Sebastian Gebhard
    created_node = self.cfg.GetNodeInfoByName(op.node_name)
111 55ba3ad6 Sebastian Gebhard
    self.assertEqual(ndparams[constants.ND_OVS],
112 55ba3ad6 Sebastian Gebhard
                     created_node.ndparams.get(constants.ND_OVS, None))
113 55ba3ad6 Sebastian Gebhard
    self.assertEqual(ndparams[constants.ND_OVS_NAME],
114 55ba3ad6 Sebastian Gebhard
                     created_node.ndparams.get(constants.ND_OVS_NAME, None))
115 55ba3ad6 Sebastian Gebhard
    self.assertEqual(ndparams[constants.ND_OVS_LINK],
116 55ba3ad6 Sebastian Gebhard
                     created_node.ndparams.get(constants.ND_OVS_LINK, None))
117 55ba3ad6 Sebastian Gebhard
118 55ba3ad6 Sebastian Gebhard
  def testWithoutOVS(self):
119 55ba3ad6 Sebastian Gebhard
    self.ExecOpCode(self.op_add)
120 55ba3ad6 Sebastian Gebhard
121 55ba3ad6 Sebastian Gebhard
    created_node = self.cfg.GetNodeInfoByName(self.op_add.node_name)
122 55ba3ad6 Sebastian Gebhard
    self.assertEqual(None,
123 55ba3ad6 Sebastian Gebhard
                     created_node.ndparams.get(constants.ND_OVS, None))
124 55ba3ad6 Sebastian Gebhard
125 55ba3ad6 Sebastian Gebhard
  def testWithOVS(self):
126 55ba3ad6 Sebastian Gebhard
    ndparams = {
127 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS: True,
128 55ba3ad6 Sebastian Gebhard
      constants.ND_OVS_LINK: "eth2",
129 55ba3ad6 Sebastian Gebhard
    }
130 55ba3ad6 Sebastian Gebhard
131 55ba3ad6 Sebastian Gebhard
    op = self.CopyOpCode(self.op_add,
132 55ba3ad6 Sebastian Gebhard
                         ndparams=ndparams)
133 55ba3ad6 Sebastian Gebhard
134 55ba3ad6 Sebastian Gebhard
    self.ExecOpCode(op)
135 55ba3ad6 Sebastian Gebhard
136 55ba3ad6 Sebastian Gebhard
    created_node = self.cfg.GetNodeInfoByName(op.node_name)
137 55ba3ad6 Sebastian Gebhard
    self.assertEqual(ndparams[constants.ND_OVS],
138 55ba3ad6 Sebastian Gebhard
                     created_node.ndparams.get(constants.ND_OVS, None))
139 55ba3ad6 Sebastian Gebhard
    self.assertEqual(ndparams[constants.ND_OVS_LINK],
140 55ba3ad6 Sebastian Gebhard
                     created_node.ndparams.get(constants.ND_OVS_LINK, None))
141 55ba3ad6 Sebastian Gebhard
142 47cce79a Sebastian Gebhard
  def testReaddingMaster(self):
143 47cce79a Sebastian Gebhard
    op = opcodes.OpNodeAdd(node_name=self.cfg.GetMasterNodeName(),
144 47cce79a Sebastian Gebhard
                           readd=True)
145 47cce79a Sebastian Gebhard
146 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Cannot readd the master node")
147 47cce79a Sebastian Gebhard
148 47cce79a Sebastian Gebhard
  def testReaddNotVmCapableNode(self):
149 47cce79a Sebastian Gebhard
    self.cfg.AddNewInstance(primary_node=self.node_readd)
150 47cce79a Sebastian Gebhard
    self.netutils_mod.GetHostname.return_value = \
151 47cce79a Sebastian Gebhard
      HostnameMock(self.node_readd.name, self.node_readd.primary_ip)
152 47cce79a Sebastian Gebhard
153 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_readd, vm_capable=False)
154 47cce79a Sebastian Gebhard
155 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Node .* being re-added with"
156 47cce79a Sebastian Gebhard
                                       " vm_capable flag set to false, but it"
157 47cce79a Sebastian Gebhard
                                       " already holds instances")
158 47cce79a Sebastian Gebhard
159 47cce79a Sebastian Gebhard
  def testReaddAndPassNodeGroup(self):
160 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_readd,group="groupname")
161 47cce79a Sebastian Gebhard
162 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Cannot pass a node group when a"
163 47cce79a Sebastian Gebhard
                                       " node is being readded")
164 47cce79a Sebastian Gebhard
165 47cce79a Sebastian Gebhard
  def testPrimaryIPv6(self):
166 47cce79a Sebastian Gebhard
    self.master.secondary_ip = self.master.primary_ip
167 47cce79a Sebastian Gebhard
168 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add, primary_ip="2001:DB8::1",
169 47cce79a Sebastian Gebhard
                         secondary_ip=self.REMOVE)
170 47cce79a Sebastian Gebhard
171 47cce79a Sebastian Gebhard
    self.ExecOpCode(op)
172 47cce79a Sebastian Gebhard
173 47cce79a Sebastian Gebhard
  def testInvalidSecondaryIP(self):
174 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add, secondary_ip="333.444.555.777")
175 47cce79a Sebastian Gebhard
176 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Secondary IP .* needs to be a valid"
177 47cce79a Sebastian Gebhard
                                       " IPv4 address")
178 47cce79a Sebastian Gebhard
179 47cce79a Sebastian Gebhard
  def testNodeAlreadyInCluster(self):
180 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_readd, readd=False)
181 47cce79a Sebastian Gebhard
182 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Node %s is already in the"
183 47cce79a Sebastian Gebhard
                                       " configuration" % self.node_readd.name)
184 47cce79a Sebastian Gebhard
185 47cce79a Sebastian Gebhard
  def testReaddNodeNotInConfiguration(self):
186 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add, readd=True)
187 47cce79a Sebastian Gebhard
188 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Node %s is not in the"
189 47cce79a Sebastian Gebhard
                                       " configuration" % self.node_add.name)
190 47cce79a Sebastian Gebhard
191 47cce79a Sebastian Gebhard
  def testPrimaryIpConflict(self):
192 47cce79a Sebastian Gebhard
    # In LUNodeAdd, DNS will resolve the node name to an IP address, that is
193 47cce79a Sebastian Gebhard
    # used to overwrite any given primary_ip value!
194 47cce79a Sebastian Gebhard
    # Thus we need to mock this DNS resolver here!
195 47cce79a Sebastian Gebhard
    self.netutils_mod.GetHostname.return_value = \
196 47cce79a Sebastian Gebhard
      HostnameMock(self.node_add.name, self.node_readd.primary_ip)
197 47cce79a Sebastian Gebhard
198 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add)
199 47cce79a Sebastian Gebhard
200 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "New node ip address.* conflict with"
201 47cce79a Sebastian Gebhard
                                       " existing node")
202 47cce79a Sebastian Gebhard
203 47cce79a Sebastian Gebhard
  def testSecondaryIpConflict(self):
204 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add, secondary_ip=self.node_readd.secondary_ip)
205 47cce79a Sebastian Gebhard
206 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "New node ip address.* conflict with"
207 47cce79a Sebastian Gebhard
                                       " existing node")
208 47cce79a Sebastian Gebhard
209 47cce79a Sebastian Gebhard
  def testReaddWithDifferentIP(self):
210 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_readd, primary_ip="192.0.2.100",
211 47cce79a Sebastian Gebhard
                         secondary_ip="230.0.113.100")
212 47cce79a Sebastian Gebhard
213 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Readded node doesn't have the same"
214 47cce79a Sebastian Gebhard
                                       " IP address configuration as before")
215 47cce79a Sebastian Gebhard
216 47cce79a Sebastian Gebhard
217 47cce79a Sebastian Gebhard
  def testNodeHasSecondaryIpButNotMaster(self):
218 47cce79a Sebastian Gebhard
    self.master.secondary_ip = self.master.primary_ip
219 47cce79a Sebastian Gebhard
220 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(self.op_add, "The master has no"
221 47cce79a Sebastian Gebhard
                                       " secondary ip but the new node has one")
222 47cce79a Sebastian Gebhard
223 47cce79a Sebastian Gebhard
  def testMasterHasSecondaryIpButNotNode(self):
224 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add, secondary_ip=None)
225 47cce79a Sebastian Gebhard
226 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "The master has a secondary ip but"
227 47cce79a Sebastian Gebhard
                                       " the new node doesn't have one")
228 47cce79a Sebastian Gebhard
229 47cce79a Sebastian Gebhard
  def testNodeNotReachableByPing(self):
230 47cce79a Sebastian Gebhard
    self.netutils_mod.TcpPing.return_value = False
231 47cce79a Sebastian Gebhard
232 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add)
233 47cce79a Sebastian Gebhard
234 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Node not reachable by ping")
235 47cce79a Sebastian Gebhard
236 47cce79a Sebastian Gebhard
  def testNodeNotReachableByPingOnSecondary(self):
237 47cce79a Sebastian Gebhard
    self.netutils_mod.GetHostname.return_value = \
238 47cce79a Sebastian Gebhard
      HostnameMock(self.node_add.name, self.node_add.primary_ip)
239 47cce79a Sebastian Gebhard
    self.netutils_mod.TcpPing.side_effect = \
240 47cce79a Sebastian Gebhard
      compat.partial(_TcpPingFailSecondary, self.cfg, self.netutils_mod.TcpPing)
241 47cce79a Sebastian Gebhard
242 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add)
243 47cce79a Sebastian Gebhard
244 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpPrereqError(op, "Node secondary ip not reachable by"
245 47cce79a Sebastian Gebhard
                                       " TCP based ping to node daemon port")
246 47cce79a Sebastian Gebhard
247 47cce79a Sebastian Gebhard
  def testCantGetVersion(self):
248 47cce79a Sebastian Gebhard
    self.mocked_dns_rpc.call_version.return_value = \
249 47cce79a Sebastian Gebhard
      self.RpcResultsBuilder(use_node_names=True) \
250 47cce79a Sebastian Gebhard
        .AddErrorNode(self.node_add) \
251 47cce79a Sebastian Gebhard
        .Build()
252 47cce79a Sebastian Gebhard
253 47cce79a Sebastian Gebhard
    op = self.CopyOpCode(self.op_add)
254 47cce79a Sebastian Gebhard
    self.ExecOpCodeExpectOpExecError(op, "Can't get version information from"
255 47cce79a Sebastian Gebhard
                                     " node %s" % self.node_add.name)
256 47cce79a Sebastian Gebhard
257 55ba3ad6 Sebastian Gebhard
if __name__ == "__main__":
258 55ba3ad6 Sebastian Gebhard
  testutils.GanetiTestProgram()