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 copy import deepcopy
29 from tests.unit import STL_MOCKS
30 from yardstick.benchmark.scenarios.networking.vnf_generic import \
31 SshManager, NetworkServiceTestCase, IncorrectConfig, \
33 from yardstick.network_services.collector.subscriber import Collector
34 from yardstick.network_services.vnf_generic.vnf.base import \
35 GenericTrafficGen, GenericVNF
38 COMPLETE_TREX_VNFD = {
39 'vnfd:vnfd-catalog': {
48 'tx_throughput_pc_linerate',
49 'rx_throughput_pc_linerate',
65 'description': 'TRex stateless traffic generator for RFC2544',
66 'id': 'TrexTrafficGen',
71 'vdu-id': 'trexgen-baremetal',
74 'short-name': 'trexgen',
75 'class-name': 'TrexTrafficGen',
78 'description': 'TRex stateless traffic generator for RFC2544',
79 'external-interface': [
82 'virtual-interface': {
83 'bandwidth': '10 Gbps',
85 'dst_mac': '00:01:02:03:04:05',
86 'local_ip': '1.1.1.2',
87 'local_mac': '00:01:02:03:05:05',
88 'type': 'PCI-PASSTHROUGH',
89 'netmask': "255.255.255.0",
91 'vpci': '0000:00:10.2',
93 'vnfd-connection-point-ref': 'xe0',
97 'virtual-interface': {
98 'bandwidth': '10 Gbps',
100 'dst_mac': '00:01:02:03:04:06',
101 'local_ip': '2.1.1.2',
102 'local_mac': '00:01:02:03:05:06',
103 'type': 'PCI-PASSTHROUGH',
104 'netmask': "255.255.255.0",
106 'vpci': '0000:00:10.1',
108 'vnfd-connection-point-ref': 'xe1',
111 'id': 'trexgen-baremetal',
112 'name': 'trexgen-baremetal',
121 28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
122 group default qlen 1000
123 link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
124 inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
125 inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
126 valid_lft forever preferred_lft forever
127 29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
128 group default qlen 1000
129 link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
130 inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
131 inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
132 valid_lft forever preferred_lft forever
136 lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> \
137 ../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
138 lrwxrwxrwx 1 root root 0 sie 3 10:37 eth2 -> \
139 ../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
143 "schema": "isb:traffic_profile:0.1",
145 "description": "Fixed traffic profile to run UDP traffic",
147 "traffic_type": "FixedTraffic",
148 "frame_rate": 100, # pps
155 class TestNetworkServiceTestCase(unittest.TestCase):
159 'name': 'trafficgen_1.yardstick',
161 'role': 'TrafficGen',
166 'netmask': '255.255.255.0',
167 'local_ip': '152.16.100.20',
168 'local_mac': '00:00:00:00:00:01',
170 'vpci': '0000:07:00.0',
174 'netmask': '255.255.255.0',
175 'local_ip': '152.16.40.20',
176 'local_mac': '00:00:00:00:00:02',
178 'vpci': '0000:07:00.1',
185 'name': 'vnf.yardstick',
187 'host': '10.223.197.164',
193 'netmask': '255.255.255.0',
194 'local_ip': '152.16.100.19',
195 'local_mac': '00:00:00:00:00:03',
197 'vpci': '0000:07:00.0',
201 'netmask': '255.255.255.0',
202 'local_ip': '152.16.40.19',
203 'local_mac': '00:00:00:00:00:04',
205 'vpci': '0000:07:00.1',
211 'netmask': '255.255.255.0',
212 'gateway': '152.16.100.20',
213 'network': '152.16.100.20',
217 'netmask': '255.255.255.0',
218 'gateway': '152.16.40.20',
219 'network': '152.16.40.20',
226 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
227 'network': '0064:ff9b:0:0:0:0:9810:6414',
232 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
233 'network': '0064:ff9b:0:0:0:0:9810:2814',
242 'vnf__1': self.vnf__1,
246 'vld_id': GenericVNF.UPLINK,
248 GenericVNF.DOWNLINK: {
249 'vld_id': GenericVNF.DOWNLINK,
255 'vnfd-connection-point-ref': [
257 'vnfd-connection-point-ref': 'xe0',
258 'member-vnf-index-ref': '1',
259 'vnfd-id-ref': 'trexgen'
262 'vnfd-connection-point-ref': 'xe0',
263 'member-vnf-index-ref': '2',
264 'vnfd-id-ref': 'trexgen'
268 'id': GenericVNF.UPLINK,
269 'name': 'tg__1 to vnf__1 link 1'
273 'vnfd-connection-point-ref': [
275 'vnfd-connection-point-ref': 'xe1',
276 'member-vnf-index-ref': '1',
277 'vnfd-id-ref': 'trexgen'
280 'vnfd-connection-point-ref': 'xe1',
281 'member-vnf-index-ref': '2',
282 'vnfd-id-ref': 'trexgen'
286 'id': GenericVNF.DOWNLINK,
287 'name': 'vnf__1 to tg__1 link 2'
291 'id': 'trex-tg-topology',
292 'short-name': 'trex-tg-topology',
293 'name': 'trex-tg-topology',
294 'description': 'trex-tg-topology',
295 'constituent-vnfd': [
297 'member-vnf-index': '1',
298 'VNF model': 'tg_trex_tpl.yaml',
299 'vnfd-id-ref': 'tg__1',
302 'member-vnf-index': '2',
303 'VNF model': 'tg_trex_tpl.yaml',
304 'vnfd-id-ref': 'vnf__1',
307 'vld': [self.vld0, self.vld1],
310 self.scenario_cfg = {
312 "topology": self._get_file_abspath("vpe_vnf_topology.yaml"),
313 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
314 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
315 'traffic_profile': 'ipv4_throughput_vpe.yaml',
319 'allowed_drop_rate': '0.8 - 1',
323 'framesize': {'64B': 100}
326 'object': 'NetworkServiceTestCase',
328 'output_filename': 'yardstick.out',
334 'flow': 'ipv4_1flow_Packets_vpe.yaml',
335 'imix': 'imix_voice.yaml'
338 'tg__2': 'trafficgen_2.yardstick',
339 'tg__1': 'trafficgen_1.yardstick',
340 'vnf__1': 'vnf.yardstick',
344 self.s = NetworkServiceTestCase(self.scenario_cfg, self.context_cfg)
346 def _get_file_abspath(self, filename):
347 curr_path = os.path.dirname(os.path.abspath(__file__))
348 file_path = os.path.join(curr_path, filename)
351 def test_ssh_manager(self):
352 with mock.patch("yardstick.ssh.SSH") as ssh:
353 ssh_mock = mock.Mock(autospec=ssh.SSH)
355 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
356 ssh.from_node.return_value = ssh_mock
357 for node, node_dict in self.context_cfg["nodes"].items():
358 with SshManager(node_dict) as conn:
359 self.assertIsNotNone(conn)
361 def test___init__(self):
364 def test__get_ip_flow_range_string(self):
365 self.scenario_cfg["traffic_options"]["flow"] = \
366 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
367 result = '152.16.100.2-152.16.100.254'
368 self.assertEqual(result, self.s._get_ip_flow_range('152.16.100.2-152.16.100.254'))
370 def test__get_ip_flow_range(self):
371 self.scenario_cfg["traffic_options"]["flow"] = \
372 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
373 result = '152.16.100.2-152.16.100.254'
374 self.assertEqual(result, self.s._get_ip_flow_range({"tg__1": 'xe0'}))
376 @mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.ipaddress')
377 def test__get_ip_flow_range_no_node_data(self, mock_ipaddress):
378 scenario_cfg = deepcopy(self.scenario_cfg)
379 scenario_cfg["traffic_options"]["flow"] = \
380 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
382 mock_ipaddress.ip_network.return_value = ipaddr = mock.Mock()
383 ipaddr.hosts.return_value = []
386 result = self.s._get_ip_flow_range({"tg__2": 'xe0'})
387 self.assertEqual(result, expected)
389 def test__get_ip_flow_range_no_nodes(self):
391 result = self.s._get_ip_flow_range({})
392 self.assertEqual(result, expected)
394 def test___get_traffic_flow(self):
395 self.scenario_cfg["traffic_options"]["flow"] = \
396 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
397 self.scenario_cfg["options"] = {}
398 self.scenario_cfg['options'] = {
410 'public_ip': ['1.1.1.1'],
413 result = {'flow': {'dst_ip0': '152.16.40.2-152.16.40.254',
414 'src_ip0': '152.16.100.2-152.16.100.254'}}
416 self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
418 def test___get_traffic_flow_error(self):
419 self.scenario_cfg["traffic_options"]["flow"] = \
420 "ipv4_1flow_Packets_vpe.yaml1"
421 self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
423 def test_get_vnf_imp(self):
424 vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
425 with mock.patch.dict("sys.modules", STL_MOCKS):
426 self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
428 with self.assertRaises(IncorrectConfig) as raised:
429 self.s.get_vnf_impl('NonExistentClass')
431 exc_str = str(raised.exception)
433 self.assertIn('No implementation', exc_str)
434 self.assertIn('found in', exc_str)
436 def test_load_vnf_models_invalid(self):
437 self.context_cfg["nodes"]['tg__1']['VNF model'] = \
438 self._get_file_abspath("tg_trex_tpl.yaml")
439 self.context_cfg["nodes"]['vnf__1']['VNF model'] = \
440 self._get_file_abspath("tg_trex_tpl.yaml")
442 vnf = mock.Mock(autospec=GenericVNF)
443 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
445 self.assertIsNotNone(
446 self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
448 def test_load_vnf_models_no_model(self):
449 vnf = mock.Mock(autospec=GenericVNF)
450 self.s.get_vnf_impl = mock.Mock(return_value=vnf)
452 self.assertIsNotNone(
453 self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
455 def test_map_topology_to_infrastructure(self):
456 with mock.patch("yardstick.ssh.SSH") as ssh:
457 ssh_mock = mock.Mock(autospec=ssh.SSH)
459 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
460 ssh.from_node.return_value = ssh_mock
461 self.s.map_topology_to_infrastructure()
463 nodes = self.context_cfg["nodes"]
464 self.assertEqual("../../vnf_descriptors/tg_rfc2544_tpl.yaml", nodes['tg__1']['VNF model'])
465 self.assertEqual("../../vnf_descriptors/vpe_vnf.yaml", nodes['vnf__1']['VNF model'])
467 def test_map_topology_to_infrastructure_insufficient_nodes(self):
468 del self.context_cfg['nodes']['vnf__1']
469 with mock.patch("yardstick.ssh.SSH") as ssh:
470 ssh_mock = mock.Mock(autospec=ssh.SSH)
472 mock.Mock(return_value=(1, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
473 ssh.from_node.return_value = ssh_mock
475 with self.assertRaises(IncorrectConfig):
476 self.s.map_topology_to_infrastructure()
478 def test_map_topology_to_infrastructure_config_invalid(self):
479 cfg = dict(self.context_cfg)
480 del cfg['nodes']['vnf__1']['interfaces']['xe0']['local_mac']
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
487 with self.assertRaises(IncorrectConfig):
488 self.s.map_topology_to_infrastructure()
490 def test__resolve_topology_invalid_config(self):
491 with mock.patch("yardstick.ssh.SSH") as ssh:
492 ssh_mock = mock.Mock(autospec=ssh.SSH)
494 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
495 ssh.from_node.return_value = ssh_mock
497 # purge an important key from the data structure
498 for interface in self.tg__1['interfaces'].values():
499 del interface['local_mac']
502 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
503 with self.assertRaises(IncorrectConfig) as raised:
504 self.s._resolve_topology()
506 self.assertIn('not found', str(raised.exception))
509 for index, interface in enumerate(self.tg__1['interfaces'].values()):
510 interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
512 # make a connection point ref with 3 points
513 self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
514 self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
517 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
518 with self.assertRaises(IncorrectConfig) as raised:
519 self.s._resolve_topology()
521 self.assertIn('wrong endpoint count', str(raised.exception))
523 # make a connection point ref with 1 point
524 self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
525 self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
528 "yardstick.benchmark.scenarios.networking.vnf_generic.LOG") as mock_log:
529 with self.assertRaises(IncorrectConfig) as raised:
530 self.s._resolve_topology()
532 self.assertIn('wrong endpoint count', str(raised.exception))
535 tgen = mock.Mock(autospec=GenericTrafficGen)
536 tgen.traffic_finished = True
537 verified_dict = {"verified": True}
538 tgen.verify_traffic = lambda x: verified_dict
539 tgen.name = "tgen__1"
540 vnf = mock.Mock(autospec=GenericVNF)
541 vnf.runs_traffic = False
542 self.s.vnfs = [tgen, vnf]
543 self.s.traffic_profile = mock.Mock()
544 self.s.collector = mock.Mock(autospec=Collector)
545 self.s.collector.get_kpi = \
546 mock.Mock(return_value={tgen.name: verified_dict})
549 self.assertDictEqual(result, {tgen.name: verified_dict})
551 def test_setup(self):
552 with mock.patch("yardstick.ssh.SSH") as ssh:
553 ssh_mock = mock.Mock(autospec=ssh.SSH)
555 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
556 ssh.from_node.return_value = ssh_mock
558 tgen = mock.Mock(autospec=GenericTrafficGen)
559 tgen.traffic_finished = True
560 verified_dict = {"verified": True}
561 tgen.verify_traffic = lambda x: verified_dict
562 tgen.terminate = mock.Mock(return_value=True)
563 tgen.name = "tgen__1"
564 vnf = mock.Mock(autospec=GenericVNF)
565 vnf.runs_traffic = False
566 vnf.terminate = mock.Mock(return_value=True)
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 self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
573 self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
574 self.s._fill_traffic_profile = \
575 mock.Mock(return_value=TRAFFIC_PROFILE)
576 self.assertEqual(None, self.s.setup())
578 def test_setup_exception(self):
579 with mock.patch("yardstick.ssh.SSH") as ssh:
580 ssh_mock = mock.Mock(autospec=ssh.SSH)
582 mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
583 ssh.from_node.return_value = ssh_mock
585 tgen = mock.Mock(autospec=GenericTrafficGen)
586 tgen.traffic_finished = True
587 verified_dict = {"verified": True}
588 tgen.verify_traffic = lambda x: verified_dict
589 tgen.terminate = mock.Mock(return_value=True)
590 tgen.name = "tgen__1"
591 vnf = mock.Mock(autospec=GenericVNF)
592 vnf.runs_traffic = False
593 vnf.instantiate.side_effect = RuntimeError("error during instantiate")
594 vnf.terminate = mock.Mock(return_value=True)
595 self.s.vnfs = [tgen, vnf]
596 self.s.traffic_profile = mock.Mock()
597 self.s.collector = mock.Mock(autospec=Collector)
598 self.s.collector.get_kpi = \
599 mock.Mock(return_value={tgen.name: verified_dict})
600 self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
601 self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
602 self.s._fill_traffic_profile = \
603 mock.Mock(return_value=TRAFFIC_PROFILE)
604 with self.assertRaises(RuntimeError):
607 def test__get_traffic_profile(self):
608 self.scenario_cfg["traffic_profile"] = \
609 self._get_file_abspath("ipv4_throughput_vpe.yaml")
610 self.assertIsNotNone(self.s._get_traffic_profile())
612 def test__get_traffic_profile_exception(self):
613 with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
614 with self.assertRaises(IOError):
615 self.s._get_traffic_profile()
617 def test___get_traffic_imix_exception(self):
618 with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
619 self.assertEqual({'imix': {'64B': 100}}, self.s._get_traffic_imix())
621 def test__fill_traffic_profile(self):
622 with mock.patch.dict("sys.modules", STL_MOCKS):
623 self.scenario_cfg["traffic_profile"] = \
624 self._get_file_abspath("ipv4_throughput_vpe.yaml")
625 self.scenario_cfg["traffic_options"]["flow"] = \
626 self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
627 self.scenario_cfg["traffic_options"]["imix"] = \
628 self._get_file_abspath("imix_voice.yaml")
629 self.assertIsNotNone(self.s._fill_traffic_profile())
631 def test_teardown(self):
632 vnf = mock.Mock(autospec=GenericVNF)
633 vnf.terminate = mock.Mock(return_value=True)
636 self.s.traffic_profile = mock.Mock()
637 self.s.collector = mock.Mock(autospec=Collector)
638 self.s.collector.stop = \
639 mock.Mock(return_value=True)
640 self.assertIsNone(self.s.teardown())
642 def test_teardown_exception(self):
643 vnf = mock.Mock(autospec=GenericVNF)
644 vnf.terminate = mock.Mock(side_effect=RuntimeError("error duing terminate"))
647 self.s.traffic_profile = mock.Mock()
648 self.s.collector = mock.Mock(autospec=Collector)
649 self.s.collector.stop = \
650 mock.Mock(return_value=True)
651 with self.assertRaises(RuntimeError):
656 'address': '0a:de:ad:be:ef:f5',
660 'interface_name': 'enp11s0',
662 'pci_bus_id': '0000:0b:00.0',
663 'subsystem_device': '0x1533',
664 'subsystem_vendor': '0x15d9',
668 'address': '0a:de:ad:be:ef:f4',
672 'interface_name': 'lan',
674 'pci_bus_id': '0000:00:19.0',
675 'subsystem_device': '0x153a',
676 'subsystem_vendor': '0x15d9',
681 SAMPLE_VM_NETDEVS = {
683 'address': 'fa:de:ad:be:ef:5b',
685 'driver': 'virtio_net',
687 'interface_name': 'eth1',
689 'pci_bus_id': '0000:00:04.0',
694 def test_parse_netdev_info(self):
696 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
697 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
698 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
699 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
700 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
701 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
702 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
703 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
704 /sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
705 /sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
706 /sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
707 /sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
708 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
709 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
710 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
711 /sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
712 /sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
713 /sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
715 res = NetworkServiceTestCase.parse_netdev_info(output)
716 assert res == self.SAMPLE_NETDEVS
718 def test_parse_netdev_info_virtio(self):
720 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
721 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
722 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
723 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
724 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
725 /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
727 res = NetworkServiceTestCase.parse_netdev_info(output)
728 assert res == self.SAMPLE_VM_NETDEVS
730 def test_probe_missing_values(self):
731 netdevs = self.SAMPLE_NETDEVS.copy()
732 network = {'local_mac': '0a:de:ad:be:ef:f5'}
733 NetworkServiceTestCase._probe_missing_values(netdevs, network)
734 assert network['vpci'] == '0000:0b:00.0'
736 network = {'local_mac': '0a:de:ad:be:ef:f4'}
737 NetworkServiceTestCase._probe_missing_values(netdevs, network)
738 assert network['vpci'] == '0000:00:19.0'
740 def test_open_relative_path(self):
741 mock_open = mock.mock_open()
742 mock_open_result = mock_open()
743 mock_open_call_count = 1 # initial call to get result
746 'yardstick.benchmark.scenarios.networking.vnf_generic.open'
749 with mock.patch(module_name, mock_open, create=True):
750 self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
752 mock_open_call_count += 1 # one more call expected
753 self.assertEqual(mock_open.call_count, mock_open_call_count)
754 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
755 self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
757 def open_effect(*args, **kwargs):
758 if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
759 return mock_open_result
760 raise IOError(errno.ENOENT, 'not found')
762 mock_open.side_effect = open_effect
763 self.assertEqual(open_relative_file('foo', 'bar'), mock_open_result)
765 mock_open_call_count += 2 # two more calls expected
766 self.assertEqual(mock_open.call_count, mock_open_call_count)
767 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
768 self.assertIn('bar', mock_open.call_args_list[-1][0][0])
770 # test an IOError of type ENOENT
771 mock_open.side_effect = IOError(errno.ENOENT, 'not found')
772 with self.assertRaises(IOError):
773 # the second call still raises
774 open_relative_file('foo', 'bar')
776 mock_open_call_count += 2 # two more calls expected
777 self.assertEqual(mock_open.call_count, mock_open_call_count)
778 self.assertIn('foo', mock_open.call_args_list[-1][0][0])
779 self.assertIn('bar', mock_open.call_args_list[-1][0][0])
781 # test an IOError other than ENOENT
782 mock_open.side_effect = IOError(errno.EBUSY, 'busy')
783 with self.assertRaises(IOError):
784 open_relative_file('foo', 'bar')
786 mock_open_call_count += 1 # one more call expected
787 self.assertEqual(mock_open.call_count, mock_open_call_count)