Locking related fixes for networks
[ganeti-local] / test / 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.client import gnt_cluster
28 from ganeti import utils
29 from ganeti import compat
30 from ganeti import constants
31
32 import testutils
33
34
35 class TestEpoUtilities(unittest.TestCase):
36   def setUp(self):
37     self.nodes2ip = dict(("node%s" % i, "192.0.2.%s" % i) for i in range(1, 10))
38     self.nodes = set(self.nodes2ip.keys())
39     self.ips2node = dict((v, k) for (k, v) in self.nodes2ip.items())
40
41   def _FakeAction(*args):
42     return True
43
44   def _FakePing(ip, port, live_port_needed=False):
45     self.assert_(live_port_needed)
46     self.assertEqual(port, 0)
47     return True
48
49   def _FakeSleep(secs):
50     self.assert_(secs >= 0 and secs <= 5)
51     return
52
53   def _NoopFeedback(self, text):
54     return
55
56   def testPingFnRemoveHostsUp(self):
57     seen = set()
58     def _FakeSeenPing(ip, *args, **kwargs):
59       node = self.ips2node[ip]
60       self.assertFalse(node in seen)
61       seen.add(node)
62       return True
63
64     helper = gnt_cluster._RunWhenNodesReachableHelper(self.nodes,
65                                                       self._FakeAction,
66                                                       self.nodes2ip, 0,
67                                                       self._NoopFeedback,
68                                                       _ping_fn=_FakeSeenPing,
69                                                       _sleep_fn=self._FakeSleep)
70
71     nodes_len = len(self.nodes)
72     for (num, _) in enumerate(self.nodes):
73       helper.Wait(5)
74       if num < nodes_len - 1:
75         self.assertRaises(utils.RetryAgain, helper)
76       else:
77         helper()
78
79     self.assertEqual(seen, self.nodes)
80     self.assertFalse(helper.down)
81     self.assertEqual(helper.up, self.nodes)
82
83   def testActionReturnFalseSetsHelperFalse(self):
84     called = False
85     def _FalseAction(*args):
86       return called
87
88     helper = gnt_cluster._RunWhenNodesReachableHelper(self.nodes, _FalseAction,
89                                                       self.nodes2ip, 0,
90                                                       self._NoopFeedback,
91                                                       _ping_fn=self._FakePing,
92                                                       _sleep_fn=self._FakeSleep)
93     for _ in self.nodes:
94       try:
95         helper()
96       except utils.RetryAgain:
97         called = True
98
99     self.assertFalse(helper.success)
100
101   def testMaybeInstanceStartup(self):
102     instances_arg = []
103     def _FakeInstanceStart(opts, instances, start):
104       instances_arg.append(set(instances))
105       return None
106
107     inst_map = {
108       "inst1": set(["node1", "node2"]),
109       "inst2": set(["node1", "node3"]),
110       "inst3": set(["node2", "node1"]),
111       "inst4": set(["node2", "node1", "node3"]),
112       "inst5": set(["node4"]),
113       }
114
115     fn = _FakeInstanceStart
116     self.assert_(gnt_cluster._MaybeInstanceStartup(None, inst_map, set(),
117                                                    _instance_start_fn=fn))
118     self.assertFalse(instances_arg)
119     result = gnt_cluster._MaybeInstanceStartup(None, inst_map, set(["node1"]),
120                                                _instance_start_fn=fn)
121     self.assert_(result)
122     self.assertFalse(instances_arg)
123     result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
124                                                set(["node1", "node3"]),
125                                                _instance_start_fn=fn)
126     self.assert_(result is None)
127     self.assertEqual(instances_arg.pop(0), set(["inst2"]))
128     self.assertFalse("inst2" in inst_map)
129     result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
130                                                set(["node1", "node3"]),
131                                                _instance_start_fn=fn)
132     self.assert_(result)
133     self.assertFalse(instances_arg)
134     result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
135                                                set(["node1", "node3", "node2"]),
136                                                _instance_start_fn=fn)
137     self.assertEqual(instances_arg.pop(0), set(["inst1", "inst3", "inst4"]))
138     self.assert_(result is None)
139     result = gnt_cluster._MaybeInstanceStartup(None, inst_map,
140                                                set(["node1", "node3", "node2",
141                                                     "node4"]),
142                                                _instance_start_fn=fn)
143     self.assert_(result is None)
144     self.assertEqual(instances_arg.pop(0), set(["inst5"]))
145     self.assertFalse(inst_map)
146
147
148 class _ClientForEpo:
149   def __init__(self, groups, nodes):
150     self._groups = groups
151     self._nodes = nodes
152
153   def QueryGroups(self, names, fields, use_locking):
154     assert not use_locking
155     assert fields == ["node_list"]
156     return self._groups
157
158   def QueryNodes(self, names, fields, use_locking):
159     assert not use_locking
160     assert fields == ["name", "master", "pinst_list", "sinst_list", "powered",
161                       "offline"]
162     return self._nodes
163
164
165 class TestEpo(unittest.TestCase):
166   _ON_EXITCODE = 253
167   _OFF_EXITCODE = 254
168
169   def _ConfirmForce(self, *args):
170     self.fail("Shouldn't need confirmation")
171
172   def _Confirm(self, exp_names, result, names, ltype, text):
173     self.assertEqual(names, exp_names)
174     self.assertFalse(result is NotImplemented)
175     return result
176
177   def _Off(self, exp_node_list, opts, node_list, inst_map):
178     self.assertEqual(node_list, exp_node_list)
179     self.assertFalse(inst_map)
180     return self._OFF_EXITCODE
181
182   def _Test(self, *args, **kwargs):
183     defaults = dict(cl=NotImplemented, _on_fn=NotImplemented,
184                     _off_fn=NotImplemented,
185                     _stdout_fn=lambda *args: None,
186                     _stderr_fn=lambda *args: None)
187     defaults.update(kwargs)
188     return gnt_cluster.Epo(*args, **defaults)
189
190   def testShowAllWithGroups(self):
191     opts = optparse.Values(dict(groups=True, show_all=True))
192     result = self._Test(opts, NotImplemented)
193     self.assertEqual(result, constants.EXIT_FAILURE)
194
195   def testShowAllWithArgs(self):
196     opts = optparse.Values(dict(groups=False, show_all=True))
197     result = self._Test(opts, ["a", "b", "c"])
198     self.assertEqual(result, constants.EXIT_FAILURE)
199
200   def testNoArgumentsNoParameters(self):
201     for (force, confirm_result) in [(True, NotImplemented), (False, False),
202                                     (False, True)]:
203       opts = optparse.Values(dict(groups=False, show_all=False, force=force,
204                                   on=False))
205       client = _ClientForEpo(NotImplemented, [
206         ("node1.example.com", False, [], [], True, False),
207         ])
208
209       if force:
210         confirm_fn = self._ConfirmForce
211       else:
212         confirm_fn = compat.partial(self._Confirm, ["node1.example.com"],
213                                     confirm_result)
214
215       off_fn = compat.partial(self._Off, ["node1.example.com"])
216
217       result = self._Test(opts, [], cl=client, _off_fn=off_fn,
218                           _confirm_fn=confirm_fn)
219       if force or confirm_result:
220         self.assertEqual(result, self._OFF_EXITCODE)
221       else:
222         self.assertEqual(result, constants.EXIT_FAILURE)
223
224   def testPowerOn(self):
225     for master in [False, True]:
226       opts = optparse.Values(dict(groups=False, show_all=True,
227                                   force=True, on=True))
228       client = _ClientForEpo(NotImplemented, [
229         ("node1.example.com", False, [], [], True, False),
230         ("node2.example.com", False, [], [], False, False),
231         ("node3.example.com", False, [], [], True, True),
232         ("node4.example.com", False, [], [], None, True),
233         ("node5.example.com", master, [], [], False, False),
234         ])
235
236       def _On(_, all_nodes, node_list, inst_map):
237         self.assertEqual(all_nodes,
238                          ["node%s.example.com" % i for i in range(1, 6)])
239         if master:
240           self.assertEqual(node_list, ["node2.example.com"])
241         else:
242           self.assertEqual(node_list, ["node2.example.com",
243                                        "node5.example.com"])
244         self.assertFalse(inst_map)
245         return self._ON_EXITCODE
246
247       result = self._Test(opts, [], cl=client, _on_fn=_On,
248                           _confirm_fn=self._ConfirmForce)
249       self.assertEqual(result, self._ON_EXITCODE)
250
251   def testMasterWithoutShowAll(self):
252     opts = optparse.Values(dict(groups=False, show_all=False,
253                                 force=True, on=False))
254     client = _ClientForEpo(NotImplemented, [
255       ("node1.example.com", True, [], [], True, False),
256       ])
257     result = self._Test(opts, [], cl=client, _confirm_fn=self._ConfirmForce)
258     self.assertEqual(result, constants.EXIT_FAILURE)
259
260
261 if __name__ == "__main__":
262   testutils.GanetiTestProgram()