Merge "Bugfix: HA test case baremetal down ipmi power off failed - dovetail"
[yardstick.git] / yardstick / tests / unit / benchmark / scenarios / networking / test_vnf_generic.py
1 # Copyright (c) 2016-2017 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from copy import deepcopy
16 import os
17 import sys
18
19 import mock
20 import unittest
21
22 from yardstick import tests
23 from yardstick.common import exceptions
24 from yardstick.common import utils
25 from yardstick.network_services.collector.subscriber import Collector
26 from yardstick.network_services.traffic_profile import base
27 from yardstick.network_services.vnf_generic import vnfdgen
28 from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
29 from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
30
31
32 stl_patch = mock.patch.dict(sys.modules, tests.STL_MOCKS)
33 stl_patch.start()
34
35 if stl_patch:
36     from yardstick.benchmark.scenarios.networking import vnf_generic
37
38 # pylint: disable=unused-argument
39 # disable this for now because I keep forgetting mock patch arg ordering
40
41
42 COMPLETE_TREX_VNFD = {
43     'vnfd:vnfd-catalog': {
44         'vnfd': [
45             {
46                 'benchmark': {
47                     'kpi': [
48                         'rx_throughput_fps',
49                         'tx_throughput_fps',
50                         'tx_throughput_mbps',
51                         'rx_throughput_mbps',
52                         'tx_throughput_pc_linerate',
53                         'rx_throughput_pc_linerate',
54                         'min_latency',
55                         'max_latency',
56                         'avg_latency',
57                     ],
58                 },
59                 'connection-point': [
60                     {
61                         'name': 'xe0',
62                         'type': 'VPORT',
63                     },
64                     {
65                         'name': 'xe1',
66                         'type': 'VPORT',
67                     },
68                 ],
69                 'description': 'TRex stateless traffic generator for RFC2544',
70                 'id': 'TrexTrafficGen',
71                 'mgmt-interface': {
72                     'ip': '1.1.1.1',
73                     'password': 'berta',
74                     'user': 'berta',
75                     'vdu-id': 'trexgen-baremetal',
76                 },
77                 'name': 'trexgen',
78                 'short-name': 'trexgen',
79                 'class-name': 'TrexTrafficGen',
80                 'vdu': [
81                     {
82                         'description': 'TRex stateless traffic generator for RFC2544',
83                         'external-interface': [
84                             {
85                                 'name': 'xe0',
86                                 'virtual-interface': {
87                                     'bandwidth': '10 Gbps',
88                                     'dst_ip': '1.1.1.1',
89                                     'dst_mac': '00:01:02:03:04:05',
90                                     'local_ip': '1.1.1.2',
91                                     'local_mac': '00:01:02:03:05:05',
92                                     'type': 'PCI-PASSTHROUGH',
93                                     'netmask': "255.255.255.0",
94                                     'driver': 'i40',
95                                     'vpci': '0000:00:10.2',
96                                 },
97                                 'vnfd-connection-point-ref': 'xe0',
98                             },
99                             {
100                                 'name': 'xe1',
101                                 'virtual-interface': {
102                                     'bandwidth': '10 Gbps',
103                                     'dst_ip': '2.1.1.1',
104                                     'dst_mac': '00:01:02:03:04:06',
105                                     'local_ip': '2.1.1.2',
106                                     'local_mac': '00:01:02:03:05:06',
107                                     'type': 'PCI-PASSTHROUGH',
108                                     'netmask': "255.255.255.0",
109                                     'driver': 'i40',
110                                     'vpci': '0000:00:10.1',
111                                 },
112                                 'vnfd-connection-point-ref': 'xe1',
113                             },
114                         ],
115                         'id': 'trexgen-baremetal',
116                         'name': 'trexgen-baremetal',
117                     },
118                 ],
119             },
120         ],
121     },
122 }
123
124 IP_ADDR_SHOW = """
125 28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
126 group default qlen 1000
127     link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
128     inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
129     inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
130        valid_lft forever preferred_lft forever
131 29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
132 group default qlen 1000
133     link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
134     inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
135     inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
136        valid_lft forever preferred_lft forever
137 """
138
139 SYS_CLASS_NET = """
140 lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> \
141 ../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
142 lrwxrwxrwx 1 root root 0 sie  3 10:37 eth2 -> \
143 ../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
144 """
145
146 TRAFFIC_PROFILE = {
147     "schema": "isb:traffic_profile:0.1",
148     "name": "fixed",
149     "description": "Fixed traffic profile to run UDP traffic",
150     "traffic_profile": {
151         "traffic_type": "FixedTraffic",
152         "frame_rate": 100,  # pps
153         "flow_number": 10,
154         "frame_size": 64,
155     },
156 }
157
158
159 class TestNetworkServiceTestCase(unittest.TestCase):
160
161     def setUp(self):
162         self.tg__1 = {
163             'name': 'trafficgen_1.yardstick',
164             'ip': '10.10.10.11',
165             'role': 'TrafficGen',
166             'user': 'root',
167             'password': 'r00t',
168             'interfaces': {
169                 'xe0': {
170                     'netmask': '255.255.255.0',
171                     'local_ip': '152.16.100.20',
172                     'local_mac': '00:00:00:00:00:01',
173                     'driver': 'i40e',
174                     'vpci': '0000:07:00.0',
175                     'dpdk_port_num': 0,
176                 },
177                 'xe1': {
178                     'netmask': '255.255.255.0',
179                     'local_ip': '152.16.40.20',
180                     'local_mac': '00:00:00:00:00:02',
181                     'driver': 'i40e',
182                     'vpci': '0000:07:00.1',
183                     'dpdk_port_num': 1,
184                 },
185             },
186         }
187
188         self.vnf__1 = {
189             'name': 'vnf.yardstick',
190             'ip': '10.10.10.12',
191             'host': '10.223.197.164',
192             'role': 'vnf',
193             'user': 'root',
194             'password': 'r00t',
195             'interfaces': {
196                 'xe0': {
197                     'netmask': '255.255.255.0',
198                     'local_ip': '152.16.100.19',
199                     'local_mac': '00:00:00:00:00:03',
200                     'driver': 'i40e',
201                     'vpci': '0000:07:00.0',
202                     'dpdk_port_num': 0,
203                 },
204                 'xe1': {
205                     'netmask': '255.255.255.0',
206                     'local_ip': '152.16.40.19',
207                     'local_mac': '00:00:00:00:00:04',
208                     'driver': 'i40e',
209                     'vpci': '0000:07:00.1',
210                     'dpdk_port_num': 1,
211                 },
212             },
213             'routing_table': [
214                 {
215                     'netmask': '255.255.255.0',
216                     'gateway': '152.16.100.20',
217                     'network': '152.16.100.20',
218                     'if': 'xe0',
219                 },
220                 {
221                     'netmask': '255.255.255.0',
222                     'gateway': '152.16.40.20',
223                     'network': '152.16.40.20',
224                     'if': 'xe1',
225                 },
226             ],
227             'nd_route_tbl': [
228                 {
229                     'netmask': '112',
230                     'gateway': '0064:ff9b:0:0:0:0:9810:6414',
231                     'network': '0064:ff9b:0:0:0:0:9810:6414',
232                     'if': 'xe0',
233                 },
234                 {
235                     'netmask': '112',
236                     'gateway': '0064:ff9b:0:0:0:0:9810:2814',
237                     'network': '0064:ff9b:0:0:0:0:9810:2814',
238                     'if': 'xe1',
239                 },
240             ],
241         }
242
243         self.context_cfg = {
244             'nodes': {
245                 'tg__1': self.tg__1,
246                 'vnf__1': self.vnf__1,
247             },
248             'networks': {
249                 GenericVNF.UPLINK: {
250                     'vld_id': GenericVNF.UPLINK,
251                 },
252                 GenericVNF.DOWNLINK: {
253                     'vld_id': GenericVNF.DOWNLINK,
254                 },
255             },
256         }
257
258         self.vld0 = {
259             'vnfd-connection-point-ref': [
260                 {
261                     'vnfd-connection-point-ref': 'xe0',
262                     'member-vnf-index-ref': '1',
263                     'vnfd-id-ref': 'trexgen'
264                 },
265                 {
266                     'vnfd-connection-point-ref': 'xe0',
267                     'member-vnf-index-ref': '2',
268                     'vnfd-id-ref': 'trexgen'
269                 }
270             ],
271             'type': 'ELAN',
272             'id': GenericVNF.UPLINK,
273             'name': 'tg__1 to vnf__1 link 1'
274         }
275
276         self.vld1 = {
277             'vnfd-connection-point-ref': [
278                 {
279                     'vnfd-connection-point-ref': 'xe1',
280                     'member-vnf-index-ref': '1',
281                     'vnfd-id-ref': 'trexgen'
282                 },
283                 {
284                     'vnfd-connection-point-ref': 'xe1',
285                     'member-vnf-index-ref': '2',
286                     'vnfd-id-ref': 'trexgen'
287                 }
288             ],
289             'type': 'ELAN',
290             'id': GenericVNF.DOWNLINK,
291             'name': 'vnf__1 to tg__1 link 2'
292         }
293
294         self.topology = {
295             'id': 'trex-tg-topology',
296             'short-name': 'trex-tg-topology',
297             'name': 'trex-tg-topology',
298             'description': 'trex-tg-topology',
299             'constituent-vnfd': [
300                 {
301                     'member-vnf-index': '1',
302                     'VNF model': 'tg_trex_tpl.yaml',
303                     'vnfd-id-ref': 'tg__1',
304                 },
305                 {
306                     'member-vnf-index': '2',
307                     'VNF model': 'tg_trex_tpl.yaml',
308                     'vnfd-id-ref': 'vnf__1',
309                 },
310             ],
311             'vld': [self.vld0, self.vld1],
312         }
313
314         self.scenario_cfg = {
315             'task_path': "",
316             "topology": self._get_file_abspath("vpe_vnf_topology.yaml"),
317             'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
318             'tc': 'tc_ipv4_1Mflow_64B_packetsize',
319             'traffic_profile': 'ipv4_throughput_vpe.yaml',
320             'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
321             'type': 'ISB',
322             'tc_options': {
323                 'rfc2544': {
324                     'allowed_drop_rate': '0.8 - 1',
325                 },
326             },
327             'options': {
328                 'framesize': {'64B': 100}
329             },
330             'runner': {
331                 'object': 'NetworkServiceTestCase',
332                 'interval': 35,
333                 'output_filename': 'yardstick.out',
334                 'runner_id': 74476,
335                 'duration': 400,
336                 'type': 'Duration',
337             },
338             'traffic_options': {
339                 'flow': 'ipv4_1flow_Packets_vpe.yaml',
340                 'imix': 'imix_voice.yaml'
341             },
342             'nodes': {
343                 'tg__2': 'trafficgen_2.yardstick',
344                 'tg__1': 'trafficgen_1.yardstick',
345                 'vnf__1': 'vnf.yardstick',
346             },
347         }
348
349         self.s = vnf_generic.NetworkServiceTestCase(self.scenario_cfg,
350                                                     self.context_cfg)
351
352     def _get_file_abspath(self, filename):
353         curr_path = os.path.dirname(os.path.abspath(__file__))
354         file_path = os.path.join(curr_path, filename)
355         return file_path
356
357     def test___init__(self):
358         self.assertIsNotNone(self.topology)
359
360     def test__get_ip_flow_range_string(self):
361         result = '152.16.100.2-152.16.100.254'
362         self.assertEqual(result, self.s._get_ip_flow_range(
363             '152.16.100.2-152.16.100.254'))
364
365     def test__get_ip_flow_range_no_nodes(self):
366         self.assertEqual('0.0.0.0', self.s._get_ip_flow_range({}))
367
368     def test__get_ip_flow_range_no_node_data(self):
369         node_data = {'tg__0': 'xe0'}
370         self.s.context_cfg['nodes']['tg__0'] = {}
371         result = self.s._get_ip_flow_range(node_data)
372         self.assertEqual('0.0.0.2-0.0.0.254', result)
373
374     def test__et_ip_flow_range_ipv4(self):
375         node_data = {'tg__0': 'xe0'}
376         self.s.context_cfg['nodes']['tg__0'] = {
377             'interfaces': {
378                 'xe0': {'local_ip': '192.168.1.15',
379                         'netmask': '255.255.255.128'}
380             }
381         }
382         result = self.s._get_ip_flow_range(node_data)
383         self.assertEqual('192.168.1.2-192.168.1.126', result)
384
385     def test__get_ip_flow_range_ipv4_mask_30(self):
386         node_data = {'tg__0': 'xe0'}
387         self.s.context_cfg['nodes']['tg__0'] = {
388             'interfaces': {
389                 'xe0': {'local_ip': '192.168.1.15', 'netmask': 30}
390             }
391         }
392         result = self.s._get_ip_flow_range(node_data)
393         self.assertEqual('192.168.1.15', result)
394
395     def test__get_ip_flow_range_ipv6(self):
396         node_data = {'tg__0': 'xe0'}
397         self.s.context_cfg['nodes']['tg__0'] = {
398             'interfaces': {
399                 'xe0': {'local_ip': '2001::11', 'netmask': 64}
400             }
401         }
402         result = self.s._get_ip_flow_range(node_data)
403         self.assertEqual('2001::2-2001::ffff:ffff:ffff:fffe', result)
404
405     def test___get_traffic_flow(self):
406         self.scenario_cfg["traffic_options"]["flow"] = \
407             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
408         self.scenario_cfg["options"] = {}
409         self.scenario_cfg['options'] = {
410             'flow': {
411                 'src_ip': [
412                     {
413                         'tg__1': 'xe0',
414                     },
415                 ],
416                 'dst_ip': [
417                     {
418                         'tg__1': 'xe1',
419                     },
420                 ],
421                 'public_ip': ['1.1.1.1'],
422             },
423         }
424         # NOTE(ralonsoh): check the expected output. This test could be
425         # incorrect
426         # result = {'flow': {'dst_ip0': '152.16.40.2-152.16.40.254',
427         #                    'src_ip0': '152.16.100.2-152.16.100.254'}}
428         self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
429
430     def test___get_traffic_flow_error(self):
431         self.scenario_cfg["traffic_options"]["flow"] = \
432             "ipv4_1flow_Packets_vpe.yaml1"
433         self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
434
435     def test_get_vnf_imp(self):
436         vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
437         with mock.patch.dict(sys.modules, tests.STL_MOCKS):
438             self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
439
440         with self.assertRaises(exceptions.IncorrectConfig) as raised:
441             self.s.get_vnf_impl('NonExistentClass')
442
443         exc_str = str(raised.exception)
444         print(exc_str)
445         self.assertIn('No implementation', exc_str)
446         self.assertIn('found in', exc_str)
447
448     def test_load_vnf_models_invalid(self):
449         self.context_cfg["nodes"]['tg__1']['VNF model'] = \
450             self._get_file_abspath("tg_trex_tpl.yaml")
451         self.context_cfg["nodes"]['vnf__1']['VNF model'] = \
452             self._get_file_abspath("tg_trex_tpl.yaml")
453         self.context_cfg['task_id'] = 'fake_task_id'
454
455         vnf = mock.Mock(autospec=GenericVNF)
456         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
457
458         self.assertIsNotNone(
459             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
460
461     def test_load_vnf_models_no_model(self):
462         vnf = mock.Mock(autospec=GenericVNF)
463         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
464
465         self.assertIsNotNone(
466             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
467
468     def test_map_topology_to_infrastructure(self):
469         self.s.map_topology_to_infrastructure()
470
471         nodes = self.context_cfg["nodes"]
472         self.assertEqual('../../vnf_descriptors/tg_rfc2544_tpl.yaml',
473                          nodes['tg__1']['VNF model'])
474         self.assertEqual('../../vnf_descriptors/vpe_vnf.yaml',
475                          nodes['vnf__1']['VNF model'])
476
477     def test_map_topology_to_infrastructure_insufficient_nodes(self):
478         cfg = deepcopy(self.context_cfg)
479         del cfg['nodes']['vnf__1']
480
481         cfg_patch = mock.patch.object(self.s, 'context_cfg', cfg)
482         with cfg_patch:
483             with self.assertRaises(exceptions.IncorrectConfig):
484                 self.s.map_topology_to_infrastructure()
485
486     def test_map_topology_to_infrastructure_config_invalid(self):
487         ssh_mock = mock.Mock()
488         ssh_mock.execute.return_value = 0, SYS_CLASS_NET + IP_ADDR_SHOW, ""
489
490         cfg = deepcopy(self.s.context_cfg)
491
492         # delete all, we don't know which will come first
493         del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
494         del cfg['nodes']['vnf__1']['interfaces']['xe1']['local_mac']
495         del cfg['nodes']['tg__1']['interfaces']['xe0']['local_mac']
496         del cfg['nodes']['tg__1']['interfaces']['xe1']['local_mac']
497
498         config_patch = mock.patch.object(self.s, 'context_cfg', cfg)
499         with config_patch:
500             with self.assertRaises(exceptions.IncorrectConfig):
501                 self.s.map_topology_to_infrastructure()
502
503     def test__resolve_topology_invalid_config(self):
504         with mock.patch("yardstick.ssh.SSH") as ssh:
505             ssh_mock = mock.Mock(autospec=ssh.SSH)
506             ssh_mock.execute = \
507                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
508             ssh.from_node.return_value = ssh_mock
509
510             # purge an important key from the data structure
511             for interface in self.tg__1['interfaces'].values():
512                 del interface['local_mac']
513
514             with self.assertRaises(exceptions.IncorrectConfig) as raised:
515                 self.s._resolve_topology()
516
517             self.assertIn('not found', str(raised.exception))
518
519             # restore local_mac
520             for index, interface in enumerate(self.tg__1['interfaces'].values()):
521                 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
522
523             # make a connection point ref with 3 points
524             self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
525                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
526
527             with self.assertRaises(exceptions.IncorrectConfig) as raised:
528                 self.s._resolve_topology()
529
530             self.assertIn('wrong endpoint count', str(raised.exception))
531
532             # make a connection point ref with 1 point
533             self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
534                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
535
536             with self.assertRaises(exceptions.IncorrectConfig) as raised:
537                 self.s._resolve_topology()
538
539             self.assertIn('wrong endpoint count', str(raised.exception))
540
541     def test_run(self):
542         tgen = mock.Mock(autospec=GenericTrafficGen)
543         tgen.traffic_finished = True
544         verified_dict = {"verified": True}
545         tgen.verify_traffic = lambda x: verified_dict
546         tgen.name = "tgen__1"
547         vnf = mock.Mock(autospec=GenericVNF)
548         vnf.runs_traffic = False
549         self.s.vnfs = [tgen, vnf]
550         self.s.traffic_profile = mock.Mock()
551         self.s.collector = mock.Mock(autospec=Collector)
552         self.s.collector.get_kpi = \
553             mock.Mock(return_value={tgen.name: verified_dict})
554         result = {}
555         self.s.run(result)
556         self.assertDictEqual(result, {tgen.name: verified_dict})
557
558     def test_setup(self):
559         with mock.patch("yardstick.ssh.SSH") as ssh:
560             ssh_mock = mock.Mock(autospec=ssh.SSH)
561             ssh_mock.execute = \
562                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
563             ssh.from_node.return_value = ssh_mock
564
565             tgen = mock.Mock(autospec=GenericTrafficGen)
566             tgen.traffic_finished = True
567             verified_dict = {"verified": True}
568             tgen.verify_traffic = lambda x: verified_dict
569             tgen.terminate = mock.Mock(return_value=True)
570             tgen.name = "tgen__1"
571             tgen.run_traffic.return_value = 'tg_id'
572             vnf = mock.Mock(autospec=GenericVNF)
573             vnf.runs_traffic = False
574             vnf.terminate = mock.Mock(return_value=True)
575             self.s.vnfs = [tgen, vnf]
576             self.s.traffic_profile = mock.Mock()
577             self.s.collector = mock.Mock(autospec=Collector)
578             self.s.collector.get_kpi = \
579                 mock.Mock(return_value={tgen.name: verified_dict})
580             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
581             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
582             self.s._fill_traffic_profile = \
583                 mock.Mock(return_value=TRAFFIC_PROFILE)
584
585     def test_setup_exception(self):
586         with mock.patch("yardstick.ssh.SSH") as ssh:
587             ssh_mock = mock.Mock(autospec=ssh.SSH)
588             ssh_mock.execute = \
589                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
590             ssh.from_node.return_value = ssh_mock
591
592             tgen = mock.Mock(autospec=GenericTrafficGen)
593             tgen.traffic_finished = True
594             verified_dict = {"verified": True}
595             tgen.verify_traffic = lambda x: verified_dict
596             tgen.terminate = mock.Mock(return_value=True)
597             tgen.name = "tgen__1"
598             vnf = mock.Mock(autospec=GenericVNF)
599             vnf.runs_traffic = False
600             vnf.instantiate.side_effect = RuntimeError(
601                 "error during instantiate")
602             vnf.terminate = mock.Mock(return_value=True)
603             self.s.vnfs = [tgen, vnf]
604             self.s.traffic_profile = mock.Mock()
605             self.s.collector = mock.Mock(autospec=Collector)
606             self.s.collector.get_kpi = \
607                 mock.Mock(return_value={tgen.name: verified_dict})
608             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
609             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
610             self.s._fill_traffic_profile = \
611                 mock.Mock(return_value=TRAFFIC_PROFILE)
612             with self.assertRaises(RuntimeError):
613                 self.s.setup()
614
615     def test__get_traffic_profile(self):
616         self.scenario_cfg["traffic_profile"] = \
617             self._get_file_abspath("ipv4_throughput_vpe.yaml")
618         self.assertIsNotNone(self.s._get_traffic_profile())
619
620     def test__get_traffic_profile_exception(self):
621         with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
622             with self.assertRaises(IOError):
623                 self.s._get_traffic_profile()
624
625     def test___get_traffic_imix_exception(self):
626         with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
627             self.assertEqual({'imix': {'64B': 100}},
628                              self.s._get_traffic_imix())
629
630     @mock.patch.object(base.TrafficProfile, 'get')
631     @mock.patch.object(vnfdgen, 'generate_vnfd')
632     def test__fill_traffic_profile(self, mock_generate, mock_tprofile_get):
633         fake_tprofile = mock.Mock()
634         fake_vnfd = mock.Mock()
635         with mock.patch.object(self.s, '_get_traffic_profile',
636                                return_value=fake_tprofile) as mock_get_tp:
637             mock_generate.return_value = fake_vnfd
638             self.s._fill_traffic_profile()
639             mock_get_tp.assert_called_once()
640             mock_generate.assert_called_once_with(
641                 fake_tprofile,
642                 {'downlink': {},
643                  'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
644                  'flow': {'flow': {}},
645                  'imix': {'imix': {'64B': 100}},
646                  'uplink': {},
647                  'duration': 30}
648             )
649             mock_tprofile_get.assert_called_once_with(fake_vnfd)
650
651     @mock.patch.object(utils, 'open_relative_file')
652     def test__get_topology(self, mock_open_path):
653         self.s.scenario_cfg['topology'] = 'fake_topology'
654         self.s.scenario_cfg['task_path'] = 'fake_path'
655         mock_open_path.side_effect = mock.mock_open(read_data='fake_data')
656         self.assertEqual('fake_data', self.s._get_topology())
657         mock_open_path.assert_called_once_with('fake_topology', 'fake_path')
658
659     @mock.patch.object(vnfdgen, 'generate_vnfd')
660     def test__render_topology(self, mock_generate):
661         fake_topology = 'fake_topology'
662         mock_generate.return_value = {'nsd:nsd-catalog': {'nsd': ['fake_nsd']}}
663         with mock.patch.object(self.s, '_get_topology',
664                                return_value=fake_topology) as mock_get_topology:
665             self.s._render_topology()
666             mock_get_topology.assert_called_once()
667
668         mock_generate.assert_called_once_with(
669             fake_topology,
670             {'extra_args': {'arg1': 'value1', 'arg2': 'value2'}}
671         )
672         self.assertEqual(self.s.topology, 'fake_nsd')
673
674     def test_get_mq_ids(self):
675         self.assertEqual(self.s._mq_ids, self.s.get_mq_ids())
676
677     def test_teardown(self):
678         vnf = mock.Mock(autospec=GenericVNF)
679         vnf.terminate = mock.Mock(return_value=True)
680         vnf.name = str(vnf)
681         self.s.vnfs = [vnf]
682         self.s.traffic_profile = mock.Mock()
683         self.s.collector = mock.Mock(autospec=Collector)
684         self.s.collector.stop = \
685             mock.Mock(return_value=True)
686         self.assertIsNone(self.s.teardown())
687
688     def test_teardown_exception(self):
689         vnf = mock.Mock(autospec=GenericVNF)
690         vnf.terminate = mock.Mock(
691             side_effect=RuntimeError("error duing terminate"))
692         vnf.name = str(vnf)
693         self.s.vnfs = [vnf]
694         self.s.traffic_profile = mock.Mock()
695         self.s.collector = mock.Mock(autospec=Collector)
696         self.s.collector.stop = \
697             mock.Mock(return_value=True)
698         with self.assertRaises(RuntimeError):
699             self.s.teardown()