Statistics
| Branch: | Tag: | Revision:

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()