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