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