Use a query client for node queries where necessary
[ganeti-github.git] / test / py / ganeti.client.gnt_cluster_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2011 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 """Script for testing ganeti.client.gnt_cluster"""
23
24 import unittest
25 import optparse
26
27 from ganeti import errors
28 from ganeti.client import gnt_cluster
29 from ganeti import utils
30 from ganeti import compat
31 from ganeti import constants
32
33 import mock
34 import testutils
35
36
37 class TestEpoUtilities(unittest.TestCase):
38 def setUp(self):
39 self.nodes2ip = dict(("node%s" % i, "192.0.2.%s" % i) for i in range(1, 10))
40 self.nodes = set(self.nodes2ip.keys())
41 self.ips2node = dict((v, k) for (k, v) in self.nodes2ip.items())
42
43 def _FakeAction(*args):
44 return True
45
46 def _FakePing(ip, port, live_port_needed=False):
47 self.assert_(live_port_needed)
48 self.assertEqual(port, 0)
49 return True
50
51 def _FakeSleep(secs):
52 self.assert_(secs >= 0 and secs <= 5)
53 return
54
55 def _NoopFeedback(self, text):
56 return
57
58 def testPingFnRemoveHostsUp(self):
59 seen = set()
60 def _FakeSeenPing(ip, *args, **kwargs):
61 node = self.ips2node[ip]
62 self.assertFalse(node in seen)
63 seen.add(node)
64 return True
65
66 helper = gnt_cluster._RunWhenNodesReachableHelper(self.nodes,
67 self._FakeAction,
68 self.nodes2ip, 0,
69 self._NoopFeedback,
70 _ping_fn=_FakeSeenPing,
71 _sleep_fn=self._FakeSleep)
72
73 nodes_len = len(self.nodes)
74 for (num, _) in enumerate(self.nodes):
75 helper.Wait(5)
76 if num < nodes_len - 1:
77 self.assertRaises(utils.RetryAgain, helper)
78 else:
79 helper()
80
81 self.assertEqual(seen, self.nodes)
82 self.assertFalse(helper.down)
83 self.assertEqual(helper.up, self.nodes)
84
85 def testActionReturnFalseSetsHelperFalse(self):
86 called = False
87 def _FalseAction(*args):
88 return called
89
90 helper = gnt_cluster._RunWhenNodesReachableHelper(self.nodes, _FalseAction,
91 self.nodes2ip, 0,
92 self._NoopFeedback,
93 _ping_fn=self._FakePing,
94 _sleep_fn=self._FakeSleep)
95 for _ in self.nodes:
96 try:
97 helper()
98 except utils.RetryAgain:
99 called = True
100
101 self.assertFalse(helper.success)
102
103 def testMaybeInstanceStartup(self):
104 instances_arg = []
105 def _FakeInstanceStart(opts, instances, start):
106 instances_arg.append(set(instances))
107 return None
108
109 inst_map = {
110 "inst1": set(["node1", "node2"]),
111 "inst2": set(["node1", "node3"]),
112 "inst3": set(["node2", "node1"]),
113 "inst4": set(["node2", "node1", "node3"]),
114 "inst5": set(["node4"]),
115 }
116
117 fn = _FakeInstanceStart
118 self.assert_(gnt_cluster._MaybeInstanceStartup(None, inst_map, set(),
119 _instance_start_fn=fn))
120 self.assertFalse(instances_arg)
121 result = gnt_cluster._MaybeInstanceStartup(None, inst_map, set(["node1"]),
122 _instance_start_fn=fn)
123 self.assert_(result)
124 self.assertFalse(instances_arg)
125 result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
126 set(["node1", "node3"]),
127 _instance_start_fn=fn)
128 self.assert_(result is None)
129 self.assertEqual(instances_arg.pop(0), set(["inst2"]))
130 self.assertFalse("inst2" in inst_map)
131 result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
132 set(["node1", "node3"]),
133 _instance_start_fn=fn)
134 self.assert_(result)
135 self.assertFalse(instances_arg)
136 result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
137 set(["node1", "node3", "node2"]),
138 _instance_start_fn=fn)
139 self.assertEqual(instances_arg.pop(0), set(["inst1", "inst3", "inst4"]))
140 self.assert_(result is None)
141 result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
142 set(["node1", "node3", "node2",
143 "node4"]),
144 _instance_start_fn=fn)
145 self.assert_(result is None)
146 self.assertEqual(instances_arg.pop(0), set(["inst5"]))
147 self.assertFalse(inst_map)
148
149
150 class _ClientForEpo:
151 def __init__(self, groups, nodes):
152 self._groups = groups
153 self._nodes = nodes
154
155 def QueryGroups(self, names, fields, use_locking):
156 assert not use_locking
157 assert fields == ["node_list"]
158 return self._groups
159
160 def QueryNodes(self, names, fields, use_locking):
161 assert not use_locking
162 assert fields == ["name", "master", "pinst_list", "sinst_list", "powered",
163 "offline"]
164 return self._nodes
165
166
167 class TestEpo(unittest.TestCase):
168 _ON_EXITCODE = 253
169 _OFF_EXITCODE = 254
170
171 def _ConfirmForce(self, *args):
172 self.fail("Shouldn't need confirmation")
173
174 def _Confirm(self, exp_names, result, names, ltype, text):
175 self.assertEqual(names, exp_names)
176 self.assertFalse(result is NotImplemented)
177 return result
178
179 def _Off(self, exp_node_list, opts, node_list, inst_map):
180 self.assertEqual(node_list, exp_node_list)
181 self.assertFalse(inst_map)
182 return self._OFF_EXITCODE
183
184 def _Test(self, *args, **kwargs):
185 defaults = dict(cl=NotImplemented, _on_fn=NotImplemented,
186 _off_fn=NotImplemented,
187 _stdout_fn=lambda *args: None,
188 _stderr_fn=lambda *args: None)
189 defaults.update(kwargs)
190 return gnt_cluster.Epo(*args, **defaults)
191
192 def testShowAllWithGroups(self):
193 opts = optparse.Values(dict(groups=True, show_all=True))
194 result = self._Test(opts, NotImplemented)
195 self.assertEqual(result, constants.EXIT_FAILURE)
196
197 def testShowAllWithArgs(self):
198 opts = optparse.Values(dict(groups=False, show_all=True))
199 result = self._Test(opts, ["a", "b", "c"])
200 self.assertEqual(result, constants.EXIT_FAILURE)
201
202 def testNoArgumentsNoParameters(self):
203 for (force, confirm_result) in [(True, NotImplemented), (False, False),
204 (False, True)]:
205 opts = optparse.Values(dict(groups=False, show_all=False, force=force,
206 on=False))
207 client = _ClientForEpo(NotImplemented, [
208 ("node1.example.com", False, [], [], True, False),
209 ])
210
211 if force:
212 confirm_fn = self._ConfirmForce
213 else:
214 confirm_fn = compat.partial(self._Confirm, ["node1.example.com"],
215 confirm_result)
216
217 off_fn = compat.partial(self._Off, ["node1.example.com"])
218
219 result = self._Test(opts, [], cl=client, qcl=client, _off_fn=off_fn,
220 _confirm_fn=confirm_fn)
221 if force or confirm_result:
222 self.assertEqual(result, self._OFF_EXITCODE)
223 else:
224 self.assertEqual(result, constants.EXIT_FAILURE)
225
226 def testPowerOn(self):
227 for master in [False, True]:
228 opts = optparse.Values(dict(groups=False, show_all=True,
229 force=True, on=True))
230 client = _ClientForEpo(NotImplemented, [
231 ("node1.example.com", False, [], [], True, False),
232 ("node2.example.com", False, [], [], False, False),
233 ("node3.example.com", False, [], [], True, True),
234 ("node4.example.com", False, [], [], None, True),
235 ("node5.example.com", master, [], [], False, False),
236 ])
237
238 def _On(_, all_nodes, node_list, inst_map):
239 self.assertEqual(all_nodes,
240 ["node%s.example.com" % i for i in range(1, 6)])
241 if master:
242 self.assertEqual(node_list, ["node2.example.com"])
243 else:
244 self.assertEqual(node_list, ["node2.example.com",
245 "node5.example.com"])
246 self.assertFalse(inst_map)
247 return self._ON_EXITCODE
248
249 result = self._Test(opts, [], cl=client, qcl=client, _on_fn=_On,
250 _confirm_fn=self._ConfirmForce)
251 self.assertEqual(result, self._ON_EXITCODE)
252
253 def testMasterWithoutShowAll(self):
254 opts = optparse.Values(dict(groups=False, show_all=False,
255 force=True, on=False))
256 client = _ClientForEpo(NotImplemented, [
257 ("node1.example.com", True, [], [], True, False),
258 ])
259 result = self._Test(opts, [], cl=client, qcl=client,
260 _confirm_fn=self._ConfirmForce)
261 self.assertEqual(result, constants.EXIT_FAILURE)
262
263
264 class DrbdHelperTestCase(unittest.TestCase):
265
266 def setUp(self):
267 unittest.TestCase.setUp(self)
268 self.enabled_disk_templates = []
269
270 def enableDrbd(self):
271 self.enabled_disk_templates = [constants.DT_DRBD8]
272
273 def disableDrbd(self):
274 self.enabled_disk_templates = [constants.DT_DISKLESS]
275
276
277 class InitDrbdHelper(DrbdHelperTestCase):
278
279 def testNoDrbdNoHelper(self):
280 opts = mock.Mock()
281 opts.drbd_helper = None
282 self.disableDrbd()
283 helper = gnt_cluster._InitDrbdHelper(opts, self.enabled_disk_templates)
284 self.assertEquals(None, helper)
285
286 def testNoDrbdHelper(self):
287 opts = mock.Mock()
288 self.disableDrbd()
289 opts.drbd_helper = "/bin/true"
290 helper = gnt_cluster._InitDrbdHelper(opts, self.enabled_disk_templates)
291 self.assertEquals(opts.drbd_helper, helper)
292
293 def testDrbdHelperNone(self):
294 opts = mock.Mock()
295 self.enableDrbd()
296 opts.drbd_helper = None
297 helper = gnt_cluster._InitDrbdHelper(opts, self.enabled_disk_templates)
298 self.assertEquals(constants.DEFAULT_DRBD_HELPER, helper)
299
300 def testDrbdHelperEmpty(self):
301 opts = mock.Mock()
302 self.enableDrbd()
303 opts.drbd_helper = ''
304 self.assertRaises(errors.OpPrereqError, gnt_cluster._InitDrbdHelper, opts,
305 self.enabled_disk_templates)
306
307 def testDrbdHelper(self):
308 opts = mock.Mock()
309 self.enableDrbd()
310 opts.drbd_helper = "/bin/true"
311 helper = gnt_cluster._InitDrbdHelper(opts, self.enabled_disk_templates)
312 self.assertEquals(opts.drbd_helper, helper)
313
314
315 class GetDrbdHelper(DrbdHelperTestCase):
316
317 def testNoDrbdNoHelper(self):
318 opts = mock.Mock()
319 self.disableDrbd()
320 opts.drbd_helper = None
321 helper = gnt_cluster._GetDrbdHelper(opts, self.enabled_disk_templates)
322 self.assertEquals(None, helper)
323
324 def testNoTemplateInfoNoHelper(self):
325 opts = mock.Mock()
326 opts.drbd_helper = None
327 helper = gnt_cluster._GetDrbdHelper(opts, None)
328 self.assertEquals(None, helper)
329
330 def testNoTemplateInfoHelper(self):
331 opts = mock.Mock()
332 opts.drbd_helper = "/bin/true"
333 helper = gnt_cluster._GetDrbdHelper(opts, None)
334 self.assertEquals(opts.drbd_helper, helper)
335
336 def testNoDrbdHelper(self):
337 opts = mock.Mock()
338 self.disableDrbd()
339 opts.drbd_helper = "/bin/true"
340 helper = gnt_cluster._GetDrbdHelper(opts, None)
341 self.assertEquals(opts.drbd_helper, helper)
342
343 def testDrbdNoHelper(self):
344 opts = mock.Mock()
345 self.enableDrbd()
346 opts.drbd_helper = None
347 helper = gnt_cluster._GetDrbdHelper(opts, self.enabled_disk_templates)
348 self.assertEquals(None, helper)
349
350 def testDrbdHelper(self):
351 opts = mock.Mock()
352 self.enableDrbd()
353 opts.drbd_helper = "/bin/true"
354 helper = gnt_cluster._GetDrbdHelper(opts, self.enabled_disk_templates)
355 self.assertEquals(opts.drbd_helper, helper)
356
357
358 if __name__ == "__main__":
359 testutils.GanetiTestProgram()