3 # Copyright (c) 2016-2017 Intel Corporation
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
18 # Unittest for yardstick.benchmark.scenarios.networking.test_vnf_generic
20 from __future__ import absolute_import
27 from yardstick.benchmark.scenarios.networking.vnf_generic import \
28 SshManager, NetworkServiceTestCase, IncorrectConfig, \
30 from yardstick.network_services.collector.subscriber import Collector
31 from yardstick.network_services.vnf_generic.vnf.base import \
32 GenericTrafficGen, GenericVNF
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(),
94 COMPLETE_TREX_VNFD = {
95 'vnfd:vnfd-catalog': {
102 'tx_throughput_mbps',
103 'rx_throughput_mbps',
104 'tx_throughput_pc_linerate',
105 'rx_throughput_pc_linerate',
111 'connection-point': [
121 'description': 'TRex stateless traffic generator for RFC2544',
122 'id': 'TrexTrafficGen',
127 'vdu-id': 'trexgen-baremetal',
130 'short-name': 'trexgen',
131 'class-name': 'TrexTrafficGen',
134 'description': 'TRex stateless traffic generator for RFC2544',
135 'external-interface': [
138 'virtual-interface': {
139 'bandwidth': '10 Gbps',
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",
147 'vpci': '0000:00:10.2',
149 'vnfd-connection-point-ref': 'xe0',
153 'virtual-interface': {
154 'bandwidth': '10 Gbps',
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",
162 'vpci': '0000:00:10.1',
164 'vnfd-connection-point-ref': 'xe1',
167 'id': 'trexgen-baremetal',
168 'name': 'trexgen-baremetal',
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
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
199 "schema": "isb:traffic_profile:0.1",
201 "description": "Fixed traffic profile to run UDP traffic",
203 "traffic_type": "FixedTraffic",
204 "frame_rate": 100, # pps
211 class TestNetworkServiceTestCase(unittest.TestCase):
215 'name': 'trafficgen_1.yardstick',
217 'role': 'TrafficGen',
222 'netmask': '255.255.255.0',
223 'local_ip': '152.16.100.20',
224 'local_mac': '00:00:00:00:00:01',
226 'vpci': '0000:07:00.0',
230 'netmask': '255.255.255.0',
231 'local_ip': '152.16.40.20',
232 'local_mac': '00:00:00:00:00:02',
234 'vpci': '0000:07:00.1',
241 'name': 'vnf.yardstick',
243 'host': '10.223.197.164',
249 'netmask': '255.255.255.0',
250 'local_ip': '152.16.100.19',
251 'local_mac': '00:00:00:00:00:03',
253 'vpci': '0000:07:00.0',
257 'netmask': '255.255.255.0',
258 'local_ip': '152.16.40.19',
259 'local_mac': '00:00:00:00:00:04',
261 'vpci': '0000:07:00.1',
267 'netmask': '255.255.255.0',
268 'gateway': '152.16.100.20',
269 'network': '152.16.100.20',
273 'netmask': '255.255.255.0',
274 'gateway': '152.16.40.20',
275 'network': '152.16.40.20',
282 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
283 'network': '0064:ff9b:0:0:0:0:9810:6414',
288 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
289 'network': '0064:ff9b:0:0:0:0:9810:2814',
298 'vnf__1': self.vnf__1,
311 'vnfd-connection-point-ref': [
313 'vnfd-connection-point-ref': 'xe0',
314 'member-vnf-index-ref': '1',
315 'vnfd-id-ref': 'trexgen'
318 'vnfd-connection-point-ref': 'xe0',
319 'member-vnf-index-ref': '2',
320 'vnfd-id-ref': 'trexgen'
325 'name': 'tg__1 to vnf__1 link 1'
329 'vnfd-connection-point-ref': [
331 'vnfd-connection-point-ref': 'xe1',
332 'member-vnf-index-ref': '1',
333 'vnfd-id-ref': 'trexgen'
336 'vnfd-connection-point-ref': 'xe1',
337 'member-vnf-index-ref': '2',
338 'vnfd-id-ref': 'trexgen'
343 'name': 'vnf__1 to tg__1 link 2'
347 'id': 'trex-tg-topology',
348 'short-name': 'trex-tg-topology',
349 'name': 'trex-tg-topology',
350 'description': 'trex-tg-topology',
351 'constituent-vnfd': [
353 'member-vnf-index': '1',
354 'VNF model': 'tg_trex_tpl.yaml',
355 'vnfd-id-ref': 'tg__1',
358 'member-vnf-index': '2',
359 'VNF model': 'tg_trex_tpl.yaml',
360 'vnfd-id-ref': 'vnf__1',
363 'vld': [self.vld0, self.vld1],
366 self.scenario_cfg = {
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',
375 'allowed_drop_rate': '0.8 - 1',
379 'framesize': {'64B': 100}
382 'object': 'NetworkServiceTestCase',
384 'output_filename': 'yardstick.out',
390 'flow': 'ipv4_1flow_Packets_vpe.yaml',
391 'imix': 'imix_voice.yaml'
394 'tg__2': 'trafficgen_2.yardstick',
395 'tg__1': 'trafficgen_1.yardstick',
396 'vnf__1': 'vnf.yardstick',
400 self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
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)
407 def test_ssh_manager(self):
408 with mock.patch("yardstick.ssh.SSH") as ssh:
409 ssh_mock = mock.Mock(autospec=ssh.SSH)
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)
417 def test___init__(self):
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'}))
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'] = {
442 'public_ip': ['1.1.1.1'],
445 result = {'flow': {'dst_ip0': '152.16.40.1-152.16.40.254',
446 'src_ip0': '152.16.100.1-152.16.100.254'}}
448 self.assertEqual(result, self.s._get_traffic_flow())
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())
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))
460 with self.assertRaises(IncorrectConfig) as raised:
461 self.s.get_vnf_impl('NonExistentClass')
463 exc_str = str(raised.exception)
465 self.assertIn('No implementation', exc_str)
466 self.assertIn('found in', exc_str)
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")
474 vnf = mock.Mock(autospec=GenericVNF)
475 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
477 self.assertIsNotNone(
478 self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
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)
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()
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'])
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)
497 mock.Mock(return_value=(1, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
498 ssh.from_node.return_value = ssh_mock
500 with self.assertRaises(IncorrectConfig):
501 self.s.map_topology_to_infrastructure()
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)
509 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
510 ssh.from_node.return_value = ssh_mock
512 with self.assertRaises(IncorrectConfig):
513 self.s.map_topology_to_infrastructure()
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)
519 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
520 ssh.from_node.return_value = ssh_mock
522 # purge an important key from the data structure
523 for interface in self.tg__1['interfaces'].values():
524 del interface['local_mac']
527 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
528 with self.assertRaises(IncorrectConfig) as raised:
529 self.s._resolve_topology()
531 self.assertIn('not found', str(raised.exception))
534 for index, interface in enumerate(self.tg__1['interfaces'].values()):
535 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
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])
542 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
543 with self.assertRaises(IncorrectConfig) as raised:
544 self.s._resolve_topology()
546 self.assertIn('wrong endpoint count', str(raised.exception))
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]
553 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
554 with self.assertRaises(IncorrectConfig) as raised:
555 self.s._resolve_topology()
557 self.assertIn('wrong endpoint count', str(raised.exception))
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})
574 self.assertDictEqual(result, {tgen.name: verified_dict})
576 def test_setup(self):
577 with mock.patch("yardstick.ssh.SSH") as ssh:
578 ssh_mock = mock.Mock(autospec=ssh.SSH)
580 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
581 ssh.from_node.return_value = ssh_mock
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())
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())
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()
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())
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())
627 def test_teardown(self):
628 vnf = mock.Mock(autospec=GenericVNF)
630 mock.Mock(return_value=True)
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())
640 'address': '0a:de:ad:be:ef:f5',
644 'interface_name': 'enp11s0',
646 'pci_bus_id': '0000:0b:00.0',
647 'subsystem_device': '0x1533',
648 'subsystem_vendor': '0x15d9',
652 'address': '0a:de:ad:be:ef:f4',
656 'interface_name': 'lan',
658 'pci_bus_id': '0000:00:19.0',
659 'subsystem_device': '0x153a',
660 'subsystem_vendor': '0x15d9',
665 SAMPLE_VM_NETDEVS = {
667 'address': 'fa:de:ad:be:ef:5b',
669 'driver': 'virtio_net',
671 'interface_name': 'eth1',
673 'pci_bus_id': '0000:00:04.0',
678 def test_parse_netdev_info(self):
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
699 res = NetworkServiceTestCase.parse_netdev_info(output)
700 assert res == self.SAMPLE_NETDEVS
702 def test_parse_netdev_info_virtio(self):
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
711 res = NetworkServiceTestCase.parse_netdev_info(output)
712 assert res == self.SAMPLE_VM_NETDEVS
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
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'
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'
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
736 'yardstick.benchmark.scenarios.networking.vnf_generic.open'
739 with mock.patch(module_name, mock_open, create=True):
740 self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
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])
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')
752 mock_open.side_effect = open_effect
753 self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
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])
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')
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])
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')
776 mock_open_call_count += 1 # one more call expected
777 self.assertEqual(mock_open.call_count, mock_open_call_count)