Merge "Add methods to get an existing stack"
[yardstick.git] / yardstick / tests / unit / benchmark / core / test_task.py
1 ##############################################################################
2 # Copyright (c) 2015 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 copy
11 import os
12
13 import mock
14 import unittest
15
16 from yardstick.benchmark.contexts import dummy
17 from yardstick.benchmark.core import task
18 from yardstick.common import constants as consts
19 from yardstick.common import exceptions
20
21
22 class TaskTestCase(unittest.TestCase):
23
24     @mock.patch.object(task, 'Context')
25     def test_parse_nodes_with_context_same_context(self, mock_context):
26         scenario_cfg = {
27             "nodes": {
28                 "host": "node1.LF",
29                 "target": "node2.LF"
30             }
31         }
32         server_info = {
33             "ip": "10.20.0.3",
34             "user": "root",
35             "key_filename": "/root/.ssh/id_rsa"
36         }
37         mock_context.get_server.return_value = server_info
38
39         context_cfg = task.parse_nodes_with_context(scenario_cfg)
40
41         self.assertEqual(context_cfg["host"], server_info)
42         self.assertEqual(context_cfg["target"], server_info)
43
44     def test_set_dispatchers(self):
45         t = task.Task()
46         output_config = {"DEFAULT": {"dispatcher": "file, http"}}
47         t._set_dispatchers(output_config)
48         self.assertEqual(output_config, output_config)
49
50     @mock.patch.object(task, 'DispatcherBase')
51     def test__do_output(self, mock_dispatcher):
52         t = task.Task()
53         output_config = {"DEFAULT": {"dispatcher": "file, http"}}
54
55         dispatcher1 = mock.MagicMock()
56         dispatcher1.__dispatcher_type__ = 'file'
57
58         dispatcher2 = mock.MagicMock()
59         dispatcher2.__dispatcher_type__ = 'http'
60
61         mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1,
62                                                            dispatcher2])
63         self.assertEqual(None, t._do_output(output_config, {}))
64
65     @mock.patch.object(task, 'Context')
66     def test_parse_networks_from_nodes(self, mock_context):
67         nodes = {
68             'node1': {
69                 'interfaces': {
70                     'mgmt': {
71                         'network_name': 'mgmt',
72                     },
73                     'xe0': {
74                         'network_name': 'uplink_0',
75                     },
76                     'xe1': {
77                         'network_name': 'downlink_0',
78                     },
79                 },
80             },
81             'node2': {
82                 'interfaces': {
83                     'mgmt': {
84                         'network_name': 'mgmt',
85                     },
86                     'uplink_0': {
87                         'network_name': 'uplink_0',
88                     },
89                     'downlink_0': {
90                         'network_name': 'downlink_0',
91                     },
92                 },
93             },
94         }
95
96         mock_context.get_network.side_effect = iter([
97             None,
98             {
99                 'name': 'mgmt',
100                 'network_type': 'flat',
101             },
102             {},
103             {
104                 'name': 'uplink_0',
105                 'subnet_cidr': '10.20.0.0/16',
106             },
107             {
108                 'name': 'downlink_0',
109                 'segmentation_id': '1001',
110             },
111             {
112                 'name': 'uplink_1',
113             },
114         ])
115
116         # one for each interface
117         expected_get_network_calls = 6
118         expected = {
119             'mgmt': {'name': 'mgmt', 'network_type': 'flat'},
120             'uplink_0': {'name': 'uplink_0', 'subnet_cidr': '10.20.0.0/16'},
121             'uplink_1': {'name': 'uplink_1'},
122             'downlink_0': {'name': 'downlink_0', 'segmentation_id': '1001'},
123         }
124
125         networks = task.get_networks_from_nodes(nodes)
126         self.assertEqual(mock_context.get_network.call_count, expected_get_network_calls)
127         self.assertDictEqual(networks, expected)
128
129     @mock.patch.object(task, 'Context')
130     @mock.patch.object(task, 'base_runner')
131     def test_run(self, mock_base_runner, *args):
132         scenario = {
133             'host': 'athena.demo',
134             'target': 'ares.demo',
135             'runner': {
136                 'duration': 60,
137                 'interval': 1,
138                 'type': 'Duration'
139             },
140             'type': 'Ping'
141         }
142
143         t = task.Task()
144         runner = mock.Mock()
145         runner.join.return_value = 0
146         runner.get_output.return_value = {}
147         runner.get_result.return_value = []
148         mock_base_runner.Runner.get.return_value = runner
149         t._run([scenario], False, "yardstick.out")
150         self.assertTrue(runner.run.called)
151
152     @mock.patch.object(os, 'environ')
153     def test_check_precondition(self, mock_os_environ):
154         cfg = {
155             'precondition': {
156                 'installer_type': 'compass',
157                 'deploy_scenarios': 'os-nosdn',
158                 'pod_name': 'huawei-pod1'
159             }
160         }
161
162         t = task.TaskParser('/opt')
163         mock_os_environ.get.side_effect = ['compass',
164                                            'os-nosdn',
165                                            'huawei-pod1']
166         result = t._check_precondition(cfg)
167         self.assertTrue(result)
168
169     def test_parse_suite_no_constraint_no_args(self):
170         SAMPLE_SCENARIO_PATH = "no_constraint_no_args_scenario_sample.yaml"
171         t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
172         with mock.patch.object(os, 'environ',
173                         new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
174             task_files, task_args, task_args_fnames = t.parse_suite()
175
176         self.assertEqual(task_files[0], self.change_to_abspath(
177                          'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
178         self.assertEqual(task_files[1], self.change_to_abspath(
179                          'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
180
181         self.assertIsNone(task_args[0])
182         self.assertIsNone(task_args[1])
183         self.assertIsNone(task_args_fnames[0])
184         self.assertIsNone(task_args_fnames[1])
185
186     def test_parse_suite_no_constraint_with_args(self):
187         SAMPLE_SCENARIO_PATH = "no_constraint_with_args_scenario_sample.yaml"
188         t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
189         with mock.patch.object(os, 'environ',
190                         new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
191             task_files, task_args, task_args_fnames = t.parse_suite()
192
193         self.assertEqual(task_files[0], self.change_to_abspath(
194                          'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
195         self.assertEqual(task_files[1], self.change_to_abspath(
196                          'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
197         self.assertIsNone(task_args[0])
198         self.assertEqual(task_args[1],
199                          '{"host": "node1.LF","target": "node2.LF"}')
200         self.assertIsNone(task_args_fnames[0])
201         self.assertIsNone(task_args_fnames[1])
202
203     def test_parse_suite_with_constraint_no_args(self):
204         SAMPLE_SCENARIO_PATH = "with_constraint_no_args_scenario_sample.yaml"
205         t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
206         with mock.patch.object(os, 'environ',
207                         new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
208             task_files, task_args, task_args_fnames = t.parse_suite()
209         self.assertEqual(task_files[0], self.change_to_abspath(
210                          'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
211         self.assertEqual(task_files[1], self.change_to_abspath(
212                          'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
213         self.assertIsNone(task_args[0])
214         self.assertIsNone(task_args[1])
215         self.assertIsNone(task_args_fnames[0])
216         self.assertIsNone(task_args_fnames[1])
217
218     def test_parse_suite_with_constraint_with_args(self):
219         SAMPLE_SCENARIO_PATH = "with_constraint_with_args_scenario_sample.yaml"
220         t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
221         with mock.patch('os.environ',
222                         new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
223             task_files, task_args, task_args_fnames = t.parse_suite()
224
225         self.assertEqual(task_files[0], self.change_to_abspath(
226                          'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
227         self.assertEqual(task_files[1], self.change_to_abspath(
228                          'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
229         self.assertIsNone(task_args[0])
230         self.assertEqual(task_args[1],
231                          '{"host": "node1.LF","target": "node2.LF"}')
232         self.assertIsNone(task_args_fnames[0])
233         self.assertIsNone(task_args_fnames[1])
234
235     def test_parse_options(self):
236         options = {
237             'openstack': {
238                 'EXTERNAL_NETWORK': '$network'
239             },
240             'nodes': ['node1', '$node'],
241             'host': '$host'
242         }
243
244         t = task.Task()
245         t.outputs = {
246             'network': 'ext-net',
247             'node': 'node2',
248             'host': 'server.yardstick'
249         }
250
251         expected_result = {
252             'openstack': {
253                 'EXTERNAL_NETWORK': 'ext-net'
254             },
255             'nodes': ['node1', 'node2'],
256             'host': 'server.yardstick'
257         }
258
259         actual_result = t._parse_options(options)
260         self.assertEqual(expected_result, actual_result)
261
262     @mock.patch('six.moves.builtins.open', side_effect=mock.mock_open())
263     @mock.patch.object(task, 'utils')
264     @mock.patch('logging.root')
265     def test_set_log(self, mock_logging_root, *args):
266         task_obj = task.Task()
267         task_obj.task_id = 'task_id'
268         task_obj._set_log()
269         mock_logging_root.addHandler.assert_called()
270
271     def _get_file_abspath(self, filename):
272         curr_path = os.path.dirname(os.path.abspath(__file__))
273         file_path = os.path.join(curr_path, filename)
274         return file_path
275
276     def change_to_abspath(self, filepath):
277         return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
278
279
280 class TaskParserTestCase(unittest.TestCase):
281
282     def setUp(self):
283         self.parser = task.TaskParser('fake/path')
284         self.scenario = {
285             'host': 'athena.demo',
286             'target': 'kratos.demo',
287             'targets': [
288                 'ares.demo', 'mars.demo'
289                 ],
290             'options': {
291                 'server_name': {
292                     'host': 'jupiter.demo',
293                     'target': 'saturn.demo',
294                     },
295                 },
296             'nodes': {
297                 'tg__0': 'tg_0.demo',
298                 'vnf__0': 'vnf_0.demo',
299                 }
300             }
301
302     def test__change_node_names(self):
303
304         ctx_attrs = {
305             'name': 'demo',
306             'task_id': '1234567890',
307             'servers': [
308                 'athena', 'kratos',
309                 'ares', 'mars',
310                 'jupiter', 'saturn',
311                 'tg_0', 'vnf_0'
312                 ]
313             }
314
315         my_context = dummy.DummyContext()
316         my_context.init(ctx_attrs)
317
318         expected_scenario = {
319             'host': 'athena.demo-12345678',
320             'target': 'kratos.demo-12345678',
321             'targets': [
322                 'ares.demo-12345678', 'mars.demo-12345678'
323                 ],
324             'options': {
325                 'server_name': {
326                     'host': 'jupiter.demo-12345678',
327                     'target': 'saturn.demo-12345678',
328                     },
329                 },
330             'nodes': {
331                 'tg__0': 'tg_0.demo-12345678',
332                 'vnf__0': 'vnf_0.demo-12345678',
333                 }
334             }
335
336         scenario = copy.deepcopy(self.scenario)
337
338         self.parser._change_node_names(scenario, [my_context])
339         self.assertEqual(scenario, expected_scenario)
340
341     def test__change_node_names_context_not_found(self):
342         scenario = copy.deepcopy(self.scenario)
343         self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
344                           self.parser._change_node_names,
345                           scenario, [])
346
347     def test__change_node_names_context_name_unchanged(self):
348         ctx_attrs = {
349             'name': 'demo',
350             'task_id': '1234567890',
351             'flags': {
352                 'no_setup': True,
353                 'no_teardown': True
354                 }
355             }
356
357         my_context = dummy.DummyContext()
358         my_context.init(ctx_attrs)
359
360         scenario = copy.deepcopy(self.scenario)
361         expected_scenario = copy.deepcopy(self.scenario)
362
363         self.parser._change_node_names(scenario, [my_context])
364         self.assertEqual(scenario, expected_scenario)