Merge "Add Flags class to base.Context"
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / test_node.py
1 #!/usr/bin/env python
2
3 ##############################################################################
4 # Copyright (c) 2015-2017 Huawei Technologies Co.,Ltd and others.
5 #
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 ##############################################################################
11
12 # Unittest for yardstick.benchmark.contexts.node
13
14 from __future__ import absolute_import
15 import os
16 import unittest
17 import errno
18 import mock
19
20 from yardstick.common import constants as consts
21 from yardstick.benchmark.contexts import node
22
23
24 # pylint: disable=unused-argument
25 # disable this for now because I keep forgetting mock patch arg ordering
26
27
28 class NodeContextTestCase(unittest.TestCase):
29
30     PREFIX = 'yardstick.benchmark.contexts.node'
31
32     NODES_SAMPLE = "nodes_sample.yaml"
33     NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
34
35     def setUp(self):
36         self.test_context = node.NodeContext()
37         self.os_path_join = os.path.join
38
39     def _get_file_abspath(self, filename):
40         curr_path = os.path.dirname(os.path.abspath(__file__))
41         file_path = self.os_path_join(curr_path, filename)
42         return file_path
43
44     def test___init__(self):
45         self.assertIsNone(self.test_context.name)
46         self.assertIsNone(self.test_context.file_path)
47         self.assertEqual(self.test_context.nodes, [])
48         self.assertEqual(self.test_context.controllers, [])
49         self.assertEqual(self.test_context.computes, [])
50         self.assertEqual(self.test_context.baremetals, [])
51         self.assertEqual(self.test_context.env, {})
52         self.assertEqual(self.test_context.attrs, {})
53
54     @mock.patch('{}.os.path.join'.format(PREFIX))
55     def test_init_negative(self, mock_path_join):
56         special_path = '/foo/bar/error_file'
57         error_path = self._get_file_abspath("error_file")
58
59         def path_join(*args):
60             if args == (consts.YARDSTICK_ROOT_PATH, error_path):
61                 return special_path
62             return self.os_path_join(*args)
63
64         # we can't count mock_path_join calls because
65         # it can catch join calls for .pyc files.
66         mock_path_join.side_effect = path_join
67         self.test_context.read_config_file = read_mock = mock.Mock()
68         read_calls = 0
69
70         with self.assertRaises(KeyError):
71             self.test_context.init({})
72
73         self.assertEqual(read_mock.call_count, read_calls)
74
75         attrs = {
76             'name': 'foo',
77             'file': error_path,
78         }
79         read_mock.side_effect = IOError(errno.EBUSY, 'busy')
80         with self.assertRaises(IOError) as raised:
81             self.test_context.init(attrs)
82
83         read_calls += 1
84         self.assertEqual(read_mock.called, read_calls)
85         self.assertIn(attrs['file'], self.test_context.file_path)
86         self.assertEqual(raised.exception.errno, errno.EBUSY)
87         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
88
89         read_mock.side_effect = IOError(errno.ENOENT, 'not found')
90         with self.assertRaises(IOError) as raised:
91             self.test_context.init(attrs)
92
93         read_calls += 2
94         self.assertEqual(read_mock.call_count, read_calls)
95         self.assertEqual(self.test_context.file_path, special_path)
96         self.assertEqual(raised.exception.errno, errno.ENOENT)
97         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
98
99     def test_read_config_file(self):
100
101         attrs = {
102             'name': 'foo',
103             'file': self._get_file_abspath(self.NODES_SAMPLE)
104         }
105
106         self.test_context.init(attrs)
107
108         self.assertIsNotNone(self.test_context.read_config_file())
109
110     def test__dispatch_script(self):
111
112         attrs = {
113             'name': 'foo',
114             'file': self._get_file_abspath(self.NODES_SAMPLE)
115         }
116
117         self.test_context.init(attrs)
118
119         self.test_context.env = {'bash': [{'script': 'dummy'}]}
120         self.test_context._execute_script = mock.Mock()
121         self.assertEqual(self.test_context._dispatch_script('bash'), None)
122
123     def test__dispatch_ansible(self):
124
125         attrs = {
126             'name': 'foo',
127             'file': self._get_file_abspath(self.NODES_SAMPLE)
128         }
129
130         self.test_context.init(attrs)
131
132         self.test_context.env = {'ansible': [{'script': 'dummy'}]}
133         self.test_context._do_ansible_job = mock.Mock()
134         self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
135         self.test_context.env = {}
136         self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
137
138     @mock.patch("{}.AnsibleCommon".format(PREFIX))
139     def test__do_ansible_job(self, mock_ansible):
140         self.assertEqual(None, self.test_context._do_ansible_job('dummy'))
141
142     def test_successful_init(self):
143
144         attrs = {
145             'name': 'foo',
146             'file': self._get_file_abspath(self.NODES_SAMPLE)
147         }
148
149         self.test_context.init(attrs)
150
151         self.assertEqual(self.test_context.name, "foo")
152         self.assertEqual(len(self.test_context.nodes), 4)
153         self.assertEqual(len(self.test_context.controllers), 2)
154         self.assertEqual(len(self.test_context.computes), 1)
155         self.assertEqual(self.test_context.computes[0]["name"], "node3")
156         self.assertEqual(len(self.test_context.baremetals), 1)
157         self.assertEqual(self.test_context.baremetals[0]["name"], "node4")
158
159     def test__get_server_with_dic_attr_name(self):
160
161         attrs = {
162             'name': 'foo',
163             'file': self._get_file_abspath(self.NODES_SAMPLE)
164         }
165
166         self.test_context.init(attrs)
167
168         attr_name = {'name': 'foo.bar'}
169         result = self.test_context._get_server(attr_name)
170
171         self.assertEqual(result, None)
172
173     def test__get_server_not_found(self):
174
175         attrs = {
176             'name': 'foo',
177             'file': self._get_file_abspath(self.NODES_SAMPLE)
178         }
179
180         self.test_context.init(attrs)
181
182         attr_name = 'bar.foo'
183         result = self.test_context._get_server(attr_name)
184
185         self.assertEqual(result, None)
186
187     def test__get_server_mismatch(self):
188
189         attrs = {
190             'name': 'foo',
191             'file': self._get_file_abspath(self.NODES_SAMPLE)
192         }
193
194         self.test_context.init(attrs)
195
196         attr_name = 'bar.foo1'
197         result = self.test_context._get_server(attr_name)
198
199         self.assertEqual(result, None)
200
201     def test__get_server_duplicate(self):
202
203         attrs = {
204             'name': 'foo',
205             'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
206         }
207
208         self.test_context.init(attrs)
209
210         attr_name = 'node1.foo'
211         with self.assertRaises(ValueError):
212             self.test_context._get_server(attr_name)
213
214     def test__get_server_found(self):
215
216         attrs = {
217             'name': 'foo',
218             'file': self._get_file_abspath(self.NODES_SAMPLE)
219         }
220
221         self.test_context.init(attrs)
222
223         attr_name = 'node1.foo'
224         result = self.test_context._get_server(attr_name)
225
226         self.assertEqual(result['ip'], '10.229.47.137')
227         self.assertEqual(result['name'], 'node1.foo')
228         self.assertEqual(result['user'], 'root')
229         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
230
231     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
232     def test_deploy(self, dispatch_script_mock):
233         obj = node.NodeContext()
234         obj.env = {
235             'type': 'script'
236         }
237         obj.deploy()
238         self.assertTrue(dispatch_script_mock.called)
239
240     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
241     def test_deploy_anisible(self, dispatch_ansible_mock):
242         obj = node.NodeContext()
243         obj.env = {
244             'type': 'ansible'
245         }
246         obj.deploy()
247         self.assertTrue(dispatch_ansible_mock.called)
248
249     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
250     def test_undeploy(self, dispatch_script_mock):
251         obj = node.NodeContext()
252         obj.env = {
253             'type': 'script'
254         }
255         obj.undeploy()
256         self.assertTrue(dispatch_script_mock.called)
257
258     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
259     def test_undeploy_anisble(self, dispatch_ansible_mock):
260         obj = node.NodeContext()
261         obj.env = {
262             'type': 'ansible'
263         }
264         obj.undeploy()
265         self.assertTrue(dispatch_ansible_mock.called)
266
267     @mock.patch('{}.ssh.SSH._put_file_shell'.format(PREFIX))
268     @mock.patch('{}.ssh.SSH.execute'.format(PREFIX))
269     def test_execute_remote_script(self, execute_mock, put_file_mock):
270         obj = node.NodeContext()
271         obj.env = {'prefix': 'yardstick.benchmark.scenarios.compute'}
272         node_name_args = 'node5'
273         obj.nodes = [{
274             'name': node_name_args,
275             'user': 'ubuntu',
276             'ip': '10.10.10.10',
277             'pwd': 'ubuntu',
278         }]
279
280         info = {'script': 'computecapacity.bash'}
281         execute_mock.return_value = (0, '', '')
282         obj._execute_remote_script('node5', info)
283
284         self.assertTrue(put_file_mock.called)
285         self.assertTrue(execute_mock.called)
286
287     @mock.patch('{}.NodeContext._execute_local_script'.format(PREFIX))
288     def test_execute_script_local(self, local_execute_mock):
289         node_name = 'local'
290         info = {}
291         node.NodeContext()._execute_script(node_name, info)
292         self.assertTrue(local_execute_mock.called)
293
294     @mock.patch('{}.NodeContext._execute_remote_script'.format(PREFIX))
295     def test_execute_script_remote(self, remote_execute_mock):
296         node_name = 'node5'
297         info = {}
298         node.NodeContext()._execute_script(node_name, info)
299         self.assertTrue(remote_execute_mock.called)
300
301     def test_get_script(self):
302         script_args = 'hello.bash'
303         info_args = {
304             'script': script_args
305         }
306         script, options = node.NodeContext()._get_script(info_args)
307         self.assertEqual(script_args, script)
308         self.assertEqual('', options)
309
310     def test_node_info(self):
311         node_name_args = 'node5'
312         obj = node.NodeContext()
313         obj.nodes = [{'name': node_name_args, 'check': node_name_args}]
314         node_info = obj._get_node_info(node_name_args)
315         self.assertEqual(node_info.get('check'), node_name_args)
316
317     @mock.patch('{}.ssh.SSH.wait'.format(PREFIX))
318     def test_get_client(self, wait_mock):
319         node_name_args = 'node5'
320         obj = node.NodeContext()
321         obj.nodes = [{
322             'name': node_name_args,
323             'user': 'ubuntu',
324             'ip': '10.10.10.10',
325             'pwd': 'ubuntu',
326         }]
327         obj._get_client(node_name_args)
328         self.assertTrue(wait_mock.called)
329
330     def test_get_server(self):
331         self.test_context.name = 'vnf1'
332         self.test_context.nodes = [{'name': 'my', 'value': 100}]
333
334         with self.assertRaises(ValueError):
335             self.test_context.get_server('my.vnf2')
336
337         expected = {'name': 'my.vnf1', 'value': 100, 'interfaces': {}}
338         result = self.test_context.get_server('my.vnf1')
339         self.assertDictEqual(result, expected)
340
341     def test_get_context_from_server(self):
342         self.test_context.name = 'vnf1'
343         self.test_context.nodes = [{'name': 'my', 'value': 100}]
344         self.test_context.attrs = {'attr1': 200}
345
346         with self.assertRaises(ValueError):
347             self.test_context.get_context_from_server('my.vnf2')
348
349         result = self.test_context.get_context_from_server('my.vnf1')
350         self.assertIs(result, self.test_context)
351
352     # TODO: Split this into more granular tests
353     def test__get_network(self):
354         network1 = {
355             'name': 'net_1',
356             'vld_id': 'vld111',
357             'segmentation_id': 'seg54',
358             'network_type': 'type_a',
359             'physical_network': 'phys',
360         }
361         network2 = {
362             'name': 'net_2',
363             'vld_id': 'vld999',
364         }
365         self.test_context.networks = {
366             'a': network1,
367             'b': network2,
368         }
369
370         attr_name = {}
371         self.assertIsNone(self.test_context._get_network(attr_name))
372
373         attr_name = {'vld_id': 'vld777'}
374         self.assertIsNone(self.test_context._get_network(attr_name))
375
376         self.assertIsNone(self.test_context._get_network(None))
377
378         attr_name = 'vld777'
379         self.assertIsNone(self.test_context._get_network(attr_name))
380
381         attr_name = {'vld_id': 'vld999'}
382         expected = {
383             "name": 'net_2',
384             "vld_id": 'vld999',
385             "segmentation_id": None,
386             "network_type": None,
387             "physical_network": None,
388         }
389         result = self.test_context._get_network(attr_name)
390         self.assertDictEqual(result, expected)
391
392         attr_name = 'a'
393         expected = network1
394         result = self.test_context._get_network(attr_name)
395         self.assertDictEqual(result, expected)
396
397
398 def main():
399     unittest.main()
400
401
402 if __name__ == '__main__':
403     main()