Re-define the framesize and flow dynamic define in testcase
[yardstick.git] / tests / unit / benchmark / scenarios / networking / test_vnf_generic.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016-2017 Intel Corporation
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17
18 # Unittest for yardstick.benchmark.scenarios.networking.test_vnf_generic
19
20 from __future__ import absolute_import
21
22 import os
23 import errno
24 import unittest
25 import mock
26
27 from yardstick.benchmark.scenarios.networking.vnf_generic import \
28     SshManager, NetworkServiceTestCase, IncorrectConfig, \
29     open_relative_file
30 from yardstick.network_services.collector.subscriber import Collector
31 from yardstick.network_services.vnf_generic.vnf.base import \
32     GenericTrafficGen, GenericVNF
33
34 STL_MOCKS = {
35     'stl': mock.MagicMock(),
36     'stl.trex_stl_lib': mock.MagicMock(),
37     'stl.trex_stl_lib.base64': mock.MagicMock(),
38     'stl.trex_stl_lib.binascii': mock.MagicMock(),
39     'stl.trex_stl_lib.collections': mock.MagicMock(),
40     'stl.trex_stl_lib.copy': mock.MagicMock(),
41     'stl.trex_stl_lib.datetime': mock.MagicMock(),
42     'stl.trex_stl_lib.functools': mock.MagicMock(),
43     'stl.trex_stl_lib.imp': mock.MagicMock(),
44     'stl.trex_stl_lib.inspect': mock.MagicMock(),
45     'stl.trex_stl_lib.json': mock.MagicMock(),
46     'stl.trex_stl_lib.linecache': mock.MagicMock(),
47     'stl.trex_stl_lib.math': mock.MagicMock(),
48     'stl.trex_stl_lib.os': mock.MagicMock(),
49     'stl.trex_stl_lib.platform': mock.MagicMock(),
50     'stl.trex_stl_lib.pprint': mock.MagicMock(),
51     'stl.trex_stl_lib.random': mock.MagicMock(),
52     'stl.trex_stl_lib.re': mock.MagicMock(),
53     'stl.trex_stl_lib.scapy': mock.MagicMock(),
54     'stl.trex_stl_lib.socket': mock.MagicMock(),
55     'stl.trex_stl_lib.string': mock.MagicMock(),
56     'stl.trex_stl_lib.struct': mock.MagicMock(),
57     'stl.trex_stl_lib.sys': mock.MagicMock(),
58     'stl.trex_stl_lib.threading': mock.MagicMock(),
59     'stl.trex_stl_lib.time': mock.MagicMock(),
60     'stl.trex_stl_lib.traceback': mock.MagicMock(),
61     'stl.trex_stl_lib.trex_stl_async_client': mock.MagicMock(),
62     'stl.trex_stl_lib.trex_stl_client': mock.MagicMock(),
63     'stl.trex_stl_lib.trex_stl_exceptions': mock.MagicMock(),
64     'stl.trex_stl_lib.trex_stl_ext': mock.MagicMock(),
65     'stl.trex_stl_lib.trex_stl_jsonrpc_client': mock.MagicMock(),
66     'stl.trex_stl_lib.trex_stl_packet_builder_interface': mock.MagicMock(),
67     'stl.trex_stl_lib.trex_stl_packet_builder_scapy': mock.MagicMock(),
68     'stl.trex_stl_lib.trex_stl_port': mock.MagicMock(),
69     'stl.trex_stl_lib.trex_stl_stats': mock.MagicMock(),
70     'stl.trex_stl_lib.trex_stl_streams': mock.MagicMock(),
71     'stl.trex_stl_lib.trex_stl_types': mock.MagicMock(),
72     'stl.trex_stl_lib.types': mock.MagicMock(),
73     'stl.trex_stl_lib.utils': mock.MagicMock(),
74     'stl.trex_stl_lib.utils.argparse': mock.MagicMock(),
75     'stl.trex_stl_lib.utils.collections': mock.MagicMock(),
76     'stl.trex_stl_lib.utils.common': mock.MagicMock(),
77     'stl.trex_stl_lib.utils.json': mock.MagicMock(),
78     'stl.trex_stl_lib.utils.os': mock.MagicMock(),
79     'stl.trex_stl_lib.utils.parsing_opts': mock.MagicMock(),
80     'stl.trex_stl_lib.utils.pwd': mock.MagicMock(),
81     'stl.trex_stl_lib.utils.random': mock.MagicMock(),
82     'stl.trex_stl_lib.utils.re': mock.MagicMock(),
83     'stl.trex_stl_lib.utils.string': mock.MagicMock(),
84     'stl.trex_stl_lib.utils.sys': mock.MagicMock(),
85     'stl.trex_stl_lib.utils.text_opts': mock.MagicMock(),
86     'stl.trex_stl_lib.utils.text_tables': mock.MagicMock(),
87     'stl.trex_stl_lib.utils.texttable': mock.MagicMock(),
88     'stl.trex_stl_lib.warnings': mock.MagicMock(),
89     'stl.trex_stl_lib.yaml': mock.MagicMock(),
90     'stl.trex_stl_lib.zlib': mock.MagicMock(),
91     'stl.trex_stl_lib.zmq': mock.MagicMock(),
92 }
93
94 COMPLETE_TREX_VNFD = {
95     'vnfd:vnfd-catalog': {
96         'vnfd': [
97             {
98                 'benchmark': {
99                     'kpi': [
100                         'rx_throughput_fps',
101                         'tx_throughput_fps',
102                         'tx_throughput_mbps',
103                         'rx_throughput_mbps',
104                         'tx_throughput_pc_linerate',
105                         'rx_throughput_pc_linerate',
106                         'min_latency',
107                         'max_latency',
108                         'avg_latency',
109                     ],
110                 },
111                 'connection-point': [
112                     {
113                         'name': 'xe0',
114                         'type': 'VPORT',
115                     },
116                     {
117                         'name': 'xe1',
118                         'type': 'VPORT',
119                     },
120                 ],
121                 'description': 'TRex stateless traffic generator for RFC2544',
122                 'id': 'TrexTrafficGen',
123                 'mgmt-interface': {
124                     'ip': '1.1.1.1',
125                     'password': 'berta',
126                     'user': 'berta',
127                     'vdu-id': 'trexgen-baremetal',
128                 },
129                 'name': 'trexgen',
130                 'short-name': 'trexgen',
131                 'class-name': 'TrexTrafficGen',
132                 'vdu': [
133                     {
134                         'description': 'TRex stateless traffic generator for RFC2544',
135                         'external-interface': [
136                             {
137                                 'name': 'xe0',
138                                 'virtual-interface': {
139                                     'bandwidth': '10 Gbps',
140                                     'dst_ip': '1.1.1.1',
141                                     'dst_mac': '00:01:02:03:04:05',
142                                     'local_ip': '1.1.1.2',
143                                     'local_mac': '00:01:02:03:05:05',
144                                     'type': 'PCI-PASSTHROUGH',
145                                     'netmask': "255.255.255.0",
146                                     'driver': 'i40',
147                                     'vpci': '0000:00:10.2',
148                                 },
149                                 'vnfd-connection-point-ref': 'xe0',
150                             },
151                             {
152                                 'name': 'xe1',
153                                 'virtual-interface': {
154                                     'bandwidth': '10 Gbps',
155                                     'dst_ip': '2.1.1.1',
156                                     'dst_mac': '00:01:02:03:04:06',
157                                     'local_ip': '2.1.1.2',
158                                     'local_mac': '00:01:02:03:05:06',
159                                     'type': 'PCI-PASSTHROUGH',
160                                     'netmask': "255.255.255.0",
161                                     'driver': 'i40',
162                                     'vpci': '0000:00:10.1',
163                                 },
164                                 'vnfd-connection-point-ref': 'xe1',
165                             },
166                         ],
167                         'id': 'trexgen-baremetal',
168                         'name': 'trexgen-baremetal',
169                     },
170                 ],
171             },
172         ],
173     },
174 }
175
176 IP_ADDR_SHOW = """
177 28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
178 group default qlen 1000
179     link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
180     inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
181     inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
182        valid_lft forever preferred_lft forever
183 29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
184 group default qlen 1000
185     link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
186     inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
187     inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
188        valid_lft forever preferred_lft forever
189 """
190
191 SYS_CLASS_NET = """
192 lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> \
193 ../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
194 lrwxrwxrwx 1 root root 0 sie  3 10:37 eth2 -> \
195 ../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
196 """
197
198 TRAFFIC_PROFILE = {
199     "schema": "isb:traffic_profile:0.1",
200     "name": "fixed",
201     "description": "Fixed traffic profile to run UDP traffic",
202     "traffic_profile": {
203         "traffic_type": "FixedTraffic",
204         "frame_rate": 100,  # pps
205         "flow_number": 10,
206         "frame_size": 64,
207     },
208 }
209
210
211 class TestNetworkServiceTestCase(unittest.TestCase):
212
213     def setUp(self):
214         self.tg__1 = {
215             'name': 'trafficgen_1.yardstick',
216             'ip': '10.10.10.11',
217             'role': 'TrafficGen',
218             'user': 'root',
219             'password': 'r00t',
220             'interfaces': {
221                 'xe0': {
222                     'netmask': '255.255.255.0',
223                     'local_ip': '152.16.100.20',
224                     'local_mac': '00:00:00:00:00:01',
225                     'driver': 'i40e',
226                     'vpci': '0000:07:00.0',
227                     'dpdk_port_num': 0,
228                 },
229                 'xe1': {
230                     'netmask': '255.255.255.0',
231                     'local_ip': '152.16.40.20',
232                     'local_mac': '00:00:00:00:00:02',
233                     'driver': 'i40e',
234                     'vpci': '0000:07:00.1',
235                     'dpdk_port_num': 1,
236                 },
237             },
238         }
239
240         self.vnf__1 = {
241             'name': 'vnf.yardstick',
242             'ip': '10.10.10.12',
243             'host': '10.223.197.164',
244             'role': 'vnf',
245             'user': 'root',
246             'password': 'r00t',
247             'interfaces': {
248                 'xe0': {
249                     'netmask': '255.255.255.0',
250                     'local_ip': '152.16.100.19',
251                     'local_mac': '00:00:00:00:00:03',
252                     'driver': 'i40e',
253                     'vpci': '0000:07:00.0',
254                     'dpdk_port_num': 0,
255                 },
256                 'xe1': {
257                     'netmask': '255.255.255.0',
258                     'local_ip': '152.16.40.19',
259                     'local_mac': '00:00:00:00:00:04',
260                     'driver': 'i40e',
261                     'vpci': '0000:07:00.1',
262                     'dpdk_port_num': 1,
263                 },
264             },
265             'routing_table': [
266                 {
267                     'netmask': '255.255.255.0',
268                     'gateway': '152.16.100.20',
269                     'network': '152.16.100.20',
270                     'if': 'xe0',
271                 },
272                 {
273                     'netmask': '255.255.255.0',
274                     'gateway': '152.16.40.20',
275                     'network': '152.16.40.20',
276                     'if': 'xe1',
277                 },
278             ],
279             'nd_route_tbl': [
280                 {
281                     'netmask': '112',
282                     'gateway': '0064:ff9b:0:0:0:0:9810:6414',
283                     'network': '0064:ff9b:0:0:0:0:9810:6414',
284                     'if': 'xe0',
285                 },
286                 {
287                     'netmask': '112',
288                     'gateway': '0064:ff9b:0:0:0:0:9810:2814',
289                     'network': '0064:ff9b:0:0:0:0:9810:2814',
290                     'if': 'xe1',
291                 },
292             ],
293         }
294
295         self.context_cfg = {
296             'nodes': {
297                 'tg__1': self.tg__1,
298                 'vnf__1': self.vnf__1,
299             },
300             'networks': {
301                 'private': {
302                     'vld_id': 'private',
303                 },
304                 'public': {
305                     'vld_id': 'public',
306                 },
307             },
308         }
309
310         self.vld0 = {
311             'vnfd-connection-point-ref': [
312                 {
313                     'vnfd-connection-point-ref': 'xe0',
314                     'member-vnf-index-ref': '1',
315                     'vnfd-id-ref': 'trexgen'
316                 },
317                 {
318                     'vnfd-connection-point-ref': 'xe0',
319                     'member-vnf-index-ref': '2',
320                     'vnfd-id-ref': 'trexgen'
321                 }
322             ],
323             'type': 'ELAN',
324             'id': 'private',
325             'name': 'tg__1 to vnf__1 link 1'
326         }
327
328         self.vld1 = {
329             'vnfd-connection-point-ref': [
330                 {
331                     'vnfd-connection-point-ref': 'xe1',
332                     'member-vnf-index-ref': '1',
333                     'vnfd-id-ref': 'trexgen'
334                 },
335                 {
336                     'vnfd-connection-point-ref': 'xe1',
337                     'member-vnf-index-ref': '2',
338                     'vnfd-id-ref': 'trexgen'
339                 }
340             ],
341             'type': 'ELAN',
342             'id': 'public',
343             'name': 'vnf__1 to tg__1 link 2'
344         }
345
346         self.topology = {
347             'id': 'trex-tg-topology',
348             'short-name': 'trex-tg-topology',
349             'name': 'trex-tg-topology',
350             'description': 'trex-tg-topology',
351             'constituent-vnfd': [
352                 {
353                     'member-vnf-index': '1',
354                     'VNF model': 'tg_trex_tpl.yaml',
355                     'vnfd-id-ref': 'tg__1',
356                 },
357                 {
358                     'member-vnf-index': '2',
359                     'VNF model': 'tg_trex_tpl.yaml',
360                     'vnfd-id-ref': 'vnf__1',
361                 },
362             ],
363             'vld': [self.vld0, self.vld1],
364         }
365
366         self.scenario_cfg = {
367             'task_path': "",
368             "topology": self._get_file_abspath("vpe_vnf_topology.yaml"),
369             'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
370             'tc': 'tc_ipv4_1Mflow_64B_packetsize',
371             'traffic_profile': 'ipv4_throughput_vpe.yaml',
372             'type': 'ISB',
373             'tc_options': {
374                 'rfc2544': {
375                     'allowed_drop_rate': '0.8 - 1',
376                 },
377             },
378             'options': {
379                 'framesize': {'64B': 100}
380             },
381             'runner': {
382                 'object': 'NetworkServiceTestCase',
383                 'interval': 35,
384                 'output_filename': 'yardstick.out',
385                 'runner_id': 74476,
386                 'duration': 400,
387                 'type': 'Duration',
388             },
389             'traffic_options': {
390                 'flow': 'ipv4_1flow_Packets_vpe.yaml',
391                 'imix': 'imix_voice.yaml'
392             },
393             'nodes': {
394                 'tg__2': 'trafficgen_2.yardstick',
395                 'tg__1': 'trafficgen_1.yardstick',
396                 'vnf__1': 'vnf.yardstick',
397             },
398         }
399
400         self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
401
402     def _get_file_abspath(self, filename):
403         curr_path = os.path.dirname(os.path.abspath(__file__))
404         file_path = os.path.join(curr_path, filename)
405         return file_path
406
407     def test_ssh_manager(self):
408         with mock.patch("yardstick.ssh.SSH") as ssh:
409             ssh_mock = mock.Mock(autospec=ssh.SSH)
410             ssh_mock.execute = \
411                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
412             ssh.from_node.return_value = ssh_mock
413             for node, node_dict in self.context_cfg["nodes"].items():
414                 with SshManager(node_dict) as conn:
415                     self.assertIsNotNone(conn)
416
417     def test___init__(self):
418         assert self.topology
419
420     def test__get_ip_flow_range(self):
421         self.scenario_cfg["traffic_options"]["flow"] = \
422             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
423         result = '152.16.100.1-152.16.100.254'
424         self.assertEqual(result, self.s._get_ip_flow_range({"tg__1": 'xe0'}))
425
426     def test___get_traffic_flow(self):
427         self.scenario_cfg["traffic_options"]["flow"] = \
428             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
429         self.scenario_cfg["options"] = {}
430         self.scenario_cfg['options'] = {
431             'flow': {
432               'src_ip': [
433                 {
434                   'tg__1': 'xe0',
435                 },
436               ],
437               'dst_ip': [
438                 {
439                   'tg__1': 'xe1',
440                 },
441               ],
442               'public_ip': ['1.1.1.1'],
443             },
444         }
445         result = {'flow': {'dst_ip0': '152.16.40.1-152.16.40.254',
446                            'src_ip0': '152.16.100.1-152.16.100.254'}}
447
448         self.assertEqual(result, self.s._get_traffic_flow())
449
450     def test___get_traffic_flow_error(self):
451         self.scenario_cfg["traffic_options"]["flow"] = \
452             "ipv4_1flow_Packets_vpe.yaml1"
453         self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
454
455     def test_get_vnf_imp(self):
456         vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
457         with mock.patch.dict("sys.modules", STL_MOCKS):
458             self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
459
460             with self.assertRaises(IncorrectConfig) as raised:
461                 self.s.get_vnf_impl('NonExistentClass')
462
463             exc_str = str(raised.exception)
464             print(exc_str)
465             self.assertIn('No implementation', exc_str)
466             self.assertIn('found in', exc_str)
467
468     def test_load_vnf_models_invalid(self):
469         self.context_cfg["nodes"]['tg__1']['VNF model'] = \
470             self._get_file_abspath("tg_trex_tpl.yaml")
471         self.context_cfg["nodes"]['vnf__1']['VNF model'] = \
472             self._get_file_abspath("tg_trex_tpl.yaml")
473
474         vnf = mock.Mock(autospec=GenericVNF)
475         self.s.get_vnf_impl = mock.Mock(return_value=vnf)
476
477         self.assertIsNotNone(
478             self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
479
480     def test_map_topology_to_infrastructure(self):
481         with mock.patch("yardstick.ssh.SSH") as ssh:
482             ssh_mock = mock.Mock(autospec=ssh.SSH)
483             ssh_mock.execute = \
484                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
485             ssh.from_node.return_value = ssh_mock
486             self.s.map_topology_to_infrastructure()
487
488         nodes = self.context_cfg["nodes"]
489         self.assertEqual("../../vnf_descriptors/tg_rfc2544_tpl.yaml", nodes['tg__1']['VNF model'])
490         self.assertEqual("../../vnf_descriptors/vpe_vnf.yaml", nodes['vnf__1']['VNF model'])
491
492     def test_map_topology_to_infrastructure_insufficient_nodes(self):
493         del self.context_cfg['nodes']['vnf__1']
494         with mock.patch("yardstick.ssh.SSH") as ssh:
495             ssh_mock = mock.Mock(autospec=ssh.SSH)
496             ssh_mock.execute = \
497                 mock.Mock(return_value=(1, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
498             ssh.from_node.return_value = ssh_mock
499
500             with self.assertRaises(IncorrectConfig):
501                 self.s.map_topology_to_infrastructure()
502
503     def test_map_topology_to_infrastructure_config_invalid(self):
504         cfg = dict(self.context_cfg)
505         del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
506         with mock.patch("yardstick.ssh.SSH") as ssh:
507             ssh_mock = mock.Mock(autospec=ssh.SSH)
508             ssh_mock.execute = \
509                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
510             ssh.from_node.return_value = ssh_mock
511
512             with self.assertRaises(IncorrectConfig):
513                 self.s.map_topology_to_infrastructure()
514
515     def test__resolve_topology_invalid_config(self):
516         with mock.patch("yardstick.ssh.SSH") as ssh:
517             ssh_mock = mock.Mock(autospec=ssh.SSH)
518             ssh_mock.execute = \
519                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
520             ssh.from_node.return_value = ssh_mock
521
522             # purge an important key from the data structure
523             for interface in self.tg__1['interfaces'].values():
524                 del interface['local_mac']
525
526             with mock.patch(
527                 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
528                 with self.assertRaises(IncorrectConfig) as raised:
529                     self.s._resolve_topology()
530
531             self.assertIn('not found', str(raised.exception))
532
533             # restore local_mac
534             for index, interface in enumerate(self.tg__1['interfaces'].values()):
535                 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
536
537             # make a connection point ref with 3 points
538             self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
539                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
540
541             with mock.patch(
542                 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
543                 with self.assertRaises(IncorrectConfig) as raised:
544                     self.s._resolve_topology()
545
546             self.assertIn('wrong endpoint count', str(raised.exception))
547
548             # make a connection point ref with 1 point
549             self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
550                 self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
551
552             with mock.patch(
553                 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
554                 with self.assertRaises(IncorrectConfig) as raised:
555                     self.s._resolve_topology()
556
557             self.assertIn('wrong endpoint count', str(raised.exception))
558
559     def test_run(self):
560         tgen = mock.Mock(autospec=GenericTrafficGen)
561         tgen.traffic_finished = True
562         verified_dict = {"verified": True}
563         tgen.verify_traffic = lambda x: verified_dict
564         tgen.name = "tgen__1"
565         vnf = mock.Mock(autospec=GenericVNF)
566         vnf.runs_traffic = False
567         self.s.vnfs = [tgen, vnf]
568         self.s.traffic_profile = mock.Mock()
569         self.s.collector = mock.Mock(autospec=Collector)
570         self.s.collector.get_kpi = \
571             mock.Mock(return_value={tgen.name: verified_dict})
572         result = {}
573         self.s.run(result)
574         self.assertDictEqual(result, {tgen.name: verified_dict})
575
576     def test_setup(self):
577         with mock.patch("yardstick.ssh.SSH") as ssh:
578             ssh_mock = mock.Mock(autospec=ssh.SSH)
579             ssh_mock.execute = \
580                 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
581             ssh.from_node.return_value = ssh_mock
582
583             tgen = mock.Mock(autospec=GenericTrafficGen)
584             tgen.traffic_finished = True
585             verified_dict = {"verified": True}
586             tgen.verify_traffic = lambda x: verified_dict
587             tgen.terminate = mock.Mock(return_value=True)
588             tgen.name = "tgen__1"
589             vnf = mock.Mock(autospec=GenericVNF)
590             vnf.runs_traffic = False
591             vnf.terminate = mock.Mock(return_value=True)
592             self.s.vnfs = [tgen, vnf]
593             self.s.traffic_profile = mock.Mock()
594             self.s.collector = mock.Mock(autospec=Collector)
595             self.s.collector.get_kpi = \
596                 mock.Mock(return_value={tgen.name: verified_dict})
597             self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
598             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
599             self.s._fill_traffic_profile = \
600                 mock.Mock(return_value=TRAFFIC_PROFILE)
601             self.assertEqual(None, self.s.setup())
602
603     def test__get_traffic_profile(self):
604         self.scenario_cfg["traffic_profile"] = \
605             self._get_file_abspath("ipv4_throughput_vpe.yaml")
606         self.assertIsNotNone(self.s._get_traffic_profile())
607
608     def test__get_traffic_profile_exception(self):
609         with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
610             with self.assertRaises(IOError):
611                 self.s._get_traffic_profile()
612
613     def test___get_traffic_imix_exception(self):
614         with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
615             self.assertEqual({'imix': {'64B': 100}}, self.s._get_traffic_imix())
616
617     def test__fill_traffic_profile(self):
618         with mock.patch.dict("sys.modules", STL_MOCKS):
619             self.scenario_cfg["traffic_profile"] = \
620                 self._get_file_abspath("ipv4_throughput_vpe.yaml")
621             self.scenario_cfg["traffic_options"]["flow"] = \
622                 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
623             self.scenario_cfg["traffic_options"]["imix"] = \
624                 self._get_file_abspath("imix_voice.yaml")
625             self.assertIsNotNone(self.s._fill_traffic_profile())
626
627     def test_teardown(self):
628         vnf = mock.Mock(autospec=GenericVNF)
629         vnf.terminate = \
630             mock.Mock(return_value=True)
631         self.s.vnfs = [vnf]
632         self.s.traffic_profile = mock.Mock()
633         self.s.collector = mock.Mock(autospec=Collector)
634         self.s.collector.stop = \
635             mock.Mock(return_value=True)
636         self.assertIsNone(self.s.teardown())
637
638     SAMPLE_NETDEVS = {
639         'enp11s0': {
640             'address': '0a:de:ad:be:ef:f5',
641             'device': '0x1533',
642             'driver': 'igb',
643             'ifindex': '2',
644             'interface_name': 'enp11s0',
645             'operstate': 'down',
646             'pci_bus_id': '0000:0b:00.0',
647             'subsystem_device': '0x1533',
648             'subsystem_vendor': '0x15d9',
649             'vendor': '0x8086'
650         },
651         'lan': {
652             'address': '0a:de:ad:be:ef:f4',
653             'device': '0x153a',
654             'driver': 'e1000e',
655             'ifindex': '3',
656             'interface_name': 'lan',
657             'operstate': 'up',
658             'pci_bus_id': '0000:00:19.0',
659             'subsystem_device': '0x153a',
660             'subsystem_vendor': '0x15d9',
661             'vendor': '0x8086'
662         }
663     }
664
665     SAMPLE_VM_NETDEVS = {
666         'eth1': {
667             'address': 'fa:de:ad:be:ef:5b',
668             'device': '0x0001',
669             'driver': 'virtio_net',
670             'ifindex': '3',
671             'interface_name': 'eth1',
672             'operstate': 'down',
673             'pci_bus_id': '0000:00:04.0',
674             'vendor': '0x1af4'
675         }
676     }
677
678     def test_parse_netdev_info(self):
679         output = """\
680 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
681 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
682 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
683 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
684 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
685 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
686 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
687 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
688 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
689 /sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
690 /sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
691 /sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
692 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
693 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
694 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
695 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
696 /sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
697 /sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
698 """
699         res = NetworkServiceTestCase.parse_netdev_info(output)
700         assert res == self.SAMPLE_NETDEVS
701
702     def test_parse_netdev_info_virtio(self):
703         output = """\
704 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
705 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
706 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
707 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
708 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
709 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
710 """
711         res = NetworkServiceTestCase.parse_netdev_info(output)
712         assert res == self.SAMPLE_VM_NETDEVS
713
714     def test_sort_dpdk_port_num(self):
715         netdevs = self.SAMPLE_NETDEVS.copy()
716         NetworkServiceTestCase._sort_dpdk_port_num(netdevs)
717         assert netdevs['lan']['dpdk_port_num'] == 0
718         assert netdevs['enp11s0']['dpdk_port_num'] == 1
719
720     def test_probe_missing_values(self):
721         netdevs = self.SAMPLE_NETDEVS.copy()
722         network = {'local_mac': '0a:de:ad:be:ef:f5'}
723         NetworkServiceTestCase._probe_missing_values(netdevs, network)
724         assert network['vpci'] == '0000:0b:00.0'
725
726         network = {'local_mac': '0a:de:ad:be:ef:f4'}
727         NetworkServiceTestCase._probe_missing_values(netdevs, network)
728         assert network['vpci'] == '0000:00:19.0'
729
730     def test_open_relative_path(self):
731         mock_open = mock.mock_open()
732         mock_open_result = mock_open()
733         mock_open_call_count = 1  # initial call to get result
734
735         module_name = \
736             'yardstick.benchmark.scenarios.networking.vnf_generic.open'
737
738         # test
739         with mock.patch(module_name, mock_open, create=True):
740             self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
741
742             mock_open_call_count += 1  # one more call expected
743             self.assertEqual(mock_open.call_count, mock_open_call_count)
744             self.assertIn('foo', mock_open.call_args_list[-1][0][0])
745             self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
746
747             def open_effect(*args, **kwargs):
748                 if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
749                     return mock_open_result
750                 raise IOError(errno.ENOENT, 'not found')
751
752             mock_open.side_effect = open_effect
753             self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
754
755             mock_open_call_count += 2  # two more calls expected
756             self.assertEqual(mock_open.call_count, mock_open_call_count)
757             self.assertIn('foo', mock_open.call_args_list[-1][0][0])
758             self.assertIn('bar', mock_open.call_args_list[-1][0][0])
759
760             # test an IOError of type ENOENT
761             mock_open.side_effect = IOError(errno.ENOENT, 'not found')
762             with self.assertRaises(IOError):
763                 # the second call still raises
764                 open_relative_file('foo', 'bar')
765
766             mock_open_call_count += 2  # two more calls expected
767             self.assertEqual(mock_open.call_count, mock_open_call_count)
768             self.assertIn('foo', mock_open.call_args_list[-1][0][0])
769             self.assertIn('bar', mock_open.call_args_list[-1][0][0])
770
771             # test an IOError other than ENOENT
772             mock_open.side_effect = IOError(errno.EBUSY, 'busy')
773             with self.assertRaises(IOError):
774                 open_relative_file('foo', 'bar')
775
776             mock_open_call_count += 1  # one more call expected
777             self.assertEqual(mock_open.call_count, mock_open_call_count)