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 from multiprocessing import Process, Queue
23 import six.moves.configparser as configparser
26 from tests.unit import STL_MOCKS
27 from tests.unit.network_services.vnf_generic.vnf.test_base import FileAbsPath
28 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
29 from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
30 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
33 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
35 STLClient = mock.MagicMock()
36 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
40 from yardstick.network_services.vnf_generic.vnf.vpe_vnf import ConfigCreate
41 from yardstick.network_services.nfvi.resource import ResourceProfile
42 from yardstick.network_services.vnf_generic.vnf.vpe_vnf import \
43 VpeApproxVnf, VpeApproxSetupEnvHelper
46 TEST_FILE_YAML = 'nsb_test_case.yaml'
50 PING_OUTPUT_1 = "Pkts in: 101\r\n\tPkts dropped by AH: 100\r\n\tPkts dropped by other: 100"
52 MODULE_PATH = FileAbsPath(__file__)
53 get_file_abspath = MODULE_PATH.get_path
56 class TestConfigCreate(unittest.TestCase):
59 'short-name': 'VpeVnf',
64 'network': '152.16.100.20',
65 'netmask': '255.255.255.0',
66 'gateway': '152.16.100.20',
70 'network': '152.16.40.20',
71 'netmask': '255.255.255.0',
72 'gateway': '152.16.40.20',
76 'description': 'VPE approximation using DPDK',
77 'name': 'vpevnf-baremetal',
80 'network': '0064:ff9b:0:0:0:0:9810:6414',
82 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
86 'network': '0064:ff9b:0:0:0:0:9810:2814',
88 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
92 'id': 'vpevnf-baremetal',
93 'external-interface': [
95 'virtual-interface': {
96 'dst_mac': '00:00:00:00:00:03',
97 'vpci': '0000:05:00.0',
98 'local_ip': '152.16.100.19',
99 'type': 'PCI-PASSTHROUGH',
100 'netmask': '255.255.255.0',
102 'bandwidth': '10 Gbps',
103 'dst_ip': '152.16.100.20',
104 'local_mac': '00:00:00:00:00:01',
105 'vld_id': 'uplink_0',
108 'vnfd-connection-point-ref': 'xe0',
112 'virtual-interface': {
113 'dst_mac': '00:00:00:00:00:04',
114 'vpci': '0000:05:00.1',
115 'local_ip': '152.16.40.19',
116 'type': 'PCI-PASSTHROUGH',
117 'netmask': '255.255.255.0',
119 'bandwidth': '10 Gbps',
120 'dst_ip': '152.16.40.20',
121 'local_mac': '00:00:00:00:00:02',
122 'vld_id': 'downlink_0',
125 'vnfd-connection-point-ref': 'xe1',
131 'description': 'Vpe approximation using DPDK',
133 'vdu-id': 'vpevnf-baremetal',
146 'connection-point': [
156 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
159 def test___init__(self):
160 vnfd_helper = VnfdHelper(self.VNFD_0)
161 config_create = ConfigCreate(vnfd_helper, 2)
162 self.assertEqual(config_create.uplink_ports, ['xe0'])
163 self.assertEqual(config_create.downlink_ports, ['xe1'])
164 self.assertEqual(config_create.socket, 2)
166 def test_vpe_initialize(self):
167 vnfd_helper = VnfdHelper(self.VNFD_0)
168 config_create = ConfigCreate(vnfd_helper, 2)
169 config = configparser.ConfigParser()
170 config_create.vpe_initialize(config)
171 self.assertEqual(config.get('EAL', 'log_level'), '0')
172 self.assertEqual(config.get('PIPELINE0', 'type'), 'MASTER')
173 self.assertEqual(config.get('PIPELINE0', 'core'), 's2C0')
174 self.assertEqual(config.get('MEMPOOL0', 'pool_size'), '256K')
175 self.assertEqual(config.get('MEMPOOL1', 'pool_size'), '2M')
177 def test_vpe_rxq(self):
178 vnfd_helper = VnfdHelper(self.VNFD_0)
179 config_create = ConfigCreate(vnfd_helper, 2)
180 config = configparser.ConfigParser()
181 config_create.downlink_ports = ['xe0']
182 config_create.vpe_rxq(config)
183 self.assertEqual(config.get('RXQ0.0', 'mempool'), 'MEMPOOL1')
185 def test_get_sink_swq(self):
186 vnfd_helper = VnfdHelper(self.VNFD_0)
187 config_create = ConfigCreate(vnfd_helper, 2)
188 config = configparser.ConfigParser()
189 config.add_section('PIPELINE0')
190 config.set('PIPELINE0', 'key1', 'value1')
191 config.set('PIPELINE0', 'key2', 'value2 SINK')
192 config.set('PIPELINE0', 'key3', 'TM value3')
193 config.set('PIPELINE0', 'key4', 'value4')
194 config.set('PIPELINE0', 'key5', 'the SINK value5')
196 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key1', 5), 'SWQ-1')
197 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key2', 5), 'SWQ-1 SINK0')
198 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key3', 5), 'SWQ-1 TM5')
199 config_create.sw_q += 1
200 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key4', 5), 'SWQ0')
201 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key5', 5), 'SWQ0 SINK1')
203 def test_generate_vpe_script(self):
204 vnfd_helper = VnfdHelper(self.VNFD_0)
205 vpe_config_vnf = ConfigCreate(vnfd_helper, 2)
209 "virtual-interface": {
211 "dst_mac": "00:00:00:00:00:00:02",
216 "virtual-interface": {
218 "dst_mac": "00:00:00:00:00:00:02",
222 vpe_config_vnf.downlink_ports = ['xe1']
223 vpe_config_vnf.uplink_ports = ['xe2']
224 result = vpe_config_vnf.generate_vpe_script(intf)
225 self.assertIsInstance(result, str)
226 self.assertNotEqual(result, '')
228 def test_create_vpe_config(self):
229 vnfd_helper = VnfdHelper(self.VNFD_0)
230 config_create = ConfigCreate(vnfd_helper, 23)
231 config_create.downlink_ports = ['xe1']
232 config_create.uplink_ports = ['xe1']
233 curr_path = os.path.dirname(os.path.abspath(__file__))
234 vpe_cfg = "samples/vnf_samples/nsut/vpe/vpe_config"
235 vnf_cfg = os.path.join(curr_path, "../../../../..", vpe_cfg)
236 config_create.create_vpe_config(vnf_cfg)
237 os.system("git checkout -- %s" % vnf_cfg)
240 class TestVpeApproxVnf(unittest.TestCase):
243 'short-name': 'VpeVnf',
248 'network': '152.16.100.20',
249 'netmask': '255.255.255.0',
250 'gateway': '152.16.100.20',
254 'network': '152.16.40.20',
255 'netmask': '255.255.255.0',
256 'gateway': '152.16.40.20',
260 'description': 'VPE approximation using DPDK',
261 'name': 'vpevnf-baremetal',
264 'network': '0064:ff9b:0:0:0:0:9810:6414',
266 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
270 'network': '0064:ff9b:0:0:0:0:9810:2814',
272 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
276 'id': 'vpevnf-baremetal',
277 'external-interface': [
279 'virtual-interface': {
280 'dst_mac': '00:00:00:00:00:04',
281 'vpci': '0000:05:00.0',
282 'local_ip': '152.16.100.19',
283 'type': 'PCI-PASSTHROUGH',
284 'netmask': '255.255.255.0',
286 'bandwidth': '10 Gbps',
288 'dst_ip': '152.16.100.20',
289 'local_iface_name': 'xe0',
290 'local_mac': '00:00:00:00:00:02',
291 'vld_id': 'uplink_0',
294 'vnfd-connection-point-ref': 'xe0',
298 'virtual-interface': {
299 'dst_mac': '00:00:00:00:00:03',
300 'vpci': '0000:05:00.1',
301 'local_ip': '152.16.40.19',
302 'type': 'PCI-PASSTHROUGH',
304 'netmask': '255.255.255.0',
306 'bandwidth': '10 Gbps',
307 'dst_ip': '152.16.40.20',
308 'local_iface_name': 'xe1',
309 'local_mac': '00:00:00:00:00:01',
310 'vld_id': 'downlink_0',
313 'vnfd-connection-point-ref': 'xe1',
319 'description': 'Vpe approximation using DPDK',
321 'vdu-id': 'vpevnf-baremetal',
334 'connection-point': [
344 'id': 'VpeApproxVnf',
349 'vnfd:vnfd-catalog': {
361 'allowed_drop_rate': '0.8 - 1',
364 'cfg': 'acl_1rule.yaml',
374 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
375 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
377 'object': 'NetworkServiceTestCase',
379 'output_filename': '/tmp/yardstick.out',
384 'traffic_profile': 'ipv4_throughput_vpe.yaml',
386 'flow': 'ipv4_Packets_vpe.yaml',
387 'imix': 'imix_voice.yaml',
391 'tg__2': 'trafficgen_2.yardstick',
392 'tg__1': 'trafficgen_1.yardstick',
393 'vnf__1': 'vnf.yardstick',
395 'topology': 'vpe-tg-topology-baremetal.yaml',
401 'member-vnf-index': '3',
402 'role': 'TrafficGen',
403 'name': 'trafficgen_2.yardstick',
404 'vnfd-id-ref': 'tg__2',
408 'local_iface_name': 'ens513f0',
409 'vld_id': VpeApproxVnf.DOWNLINK,
410 'netmask': '255.255.255.0',
411 'local_ip': '152.16.40.20',
412 'dst_mac': '00:00:00:00:00:01',
413 'local_mac': '00:00:00:00:00:03',
414 'dst_ip': '152.16.40.19',
416 'vpci': '0000:02:00.0',
420 'local_iface_name': 'ens513f1',
421 'netmask': '255.255.255.0',
422 'network': '202.16.100.0',
423 'local_ip': '202.16.100.20',
424 'local_mac': '00:1e:67:d0:60:5d',
426 'vpci': '0000:02:00.1',
431 'VNF model': 'l3fwd_vnf.yaml',
435 'member-vnf-index': '1',
436 'role': 'TrafficGen',
437 'name': 'trafficgen_1.yardstick',
438 'vnfd-id-ref': 'tg__1',
442 'local_iface_name': 'ens785f0',
443 'vld_id': VpeApproxVnf.UPLINK,
444 'netmask': '255.255.255.0',
445 'local_ip': '152.16.100.20',
446 'dst_mac': '00:00:00:00:00:02',
447 'local_mac': '00:00:00:00:00:04',
448 'dst_ip': '152.16.100.19',
450 'vpci': '0000:05:00.0',
454 'local_iface_name': 'ens785f1',
455 'netmask': '255.255.255.0',
456 'local_ip': '152.16.100.21',
457 'local_mac': '00:00:00:00:00:01',
459 'vpci': '0000:05:00.1',
464 'VNF model': 'tg_rfc2544_tpl.yaml',
468 'name': 'vnf.yardstick',
469 'vnfd-id-ref': 'vnf__1',
473 'local_iface_name': 'ens786f0',
474 'vld_id': VpeApproxVnf.UPLINK,
475 'netmask': '255.255.255.0',
476 'local_ip': '152.16.100.19',
477 'dst_mac': '00:00:00:00:00:04',
478 'local_mac': '00:00:00:00:00:02',
479 'dst_ip': '152.16.100.20',
481 'vpci': '0000:05:00.0',
485 'local_iface_name': 'ens786f1',
486 'vld_id': VpeApproxVnf.DOWNLINK,
487 'netmask': '255.255.255.0',
488 'local_ip': '152.16.40.19',
489 'dst_mac': '00:00:00:00:00:03',
490 'local_mac': '00:00:00:00:00:01',
491 'dst_ip': '152.16.40.20',
493 'vpci': '0000:05:00.1',
499 'netmask': '255.255.255.0',
500 'gateway': '152.16.100.20',
501 'network': '152.16.100.20',
505 'netmask': '255.255.255.0',
506 'gateway': '152.16.40.20',
507 'network': '152.16.40.20',
511 'member-vnf-index': '2',
518 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
519 'network': '0064:ff9b:0:0:0:0:9810:6414',
524 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
525 'network': '0064:ff9b:0:0:0:0:9810:2814',
530 'VNF model': 'vpe_vnf.yaml',
536 self.mock_sleep = mock.patch.object(time, 'sleep').start()
538 def test___init__(self):
539 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
540 self.assertIsNone(vpe_approx_vnf._vnf_process)
542 @mock.patch(SSH_HELPER)
543 def test_collect_kpi_sa_not_running(self, ssh):
546 resource = mock.Mock(autospec=ResourceProfile)
547 resource.check_if_system_agent_running.return_value = 1, ''
548 resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
549 resource.check_if_system_agent_running.return_value = (1, None)
551 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
552 vpe_approx_vnf.q_in = mock.MagicMock()
553 vpe_approx_vnf.q_out = mock.MagicMock()
554 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
555 vpe_approx_vnf.resource_helper.resource = resource
558 'pkt_in_down_stream': 0,
559 'pkt_in_up_stream': 0,
560 'pkt_drop_down_stream': 0,
561 'pkt_drop_up_stream': 0,
562 'collect_stats': {'core': {}},
564 self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
566 @mock.patch(SSH_HELPER)
567 def test_collect_kpi_sa_running(self, ssh):
570 resource = mock.Mock(autospec=ResourceProfile)
571 resource.check_if_system_agent_running.return_value = 0, '1234'
572 resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
574 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
575 vpe_approx_vnf.q_in = mock.MagicMock()
576 vpe_approx_vnf.q_out = mock.MagicMock()
577 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
578 vpe_approx_vnf.resource_helper.resource = resource
581 'pkt_in_down_stream': 0,
582 'pkt_in_up_stream': 0,
583 'pkt_drop_down_stream': 0,
584 'pkt_drop_up_stream': 0,
585 'collect_stats': {'core': {'foo': 234}},
587 self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
589 @mock.patch(SSH_HELPER)
590 def test_vnf_execute(self, ssh):
592 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
593 vpe_approx_vnf.q_in = mock.MagicMock()
594 vpe_approx_vnf.q_out = mock.MagicMock()
595 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
596 self.assertEqual(vpe_approx_vnf.vnf_execute("quit", 0), '')
598 @mock.patch(SSH_HELPER)
599 def test_run_vpe(self, ssh):
602 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
603 vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
604 vpe_approx_vnf.vnf_cfg = {
607 'worker_config': '1C/1T',
610 vpe_approx_vnf.scenario_helper.scenario_cfg = {
614 'topology': 'nsb_test_case.yaml',
615 'vnf_config': 'vpe_config',
619 vpe_approx_vnf.topology = "nsb_test_case.yaml"
620 vpe_approx_vnf.nfvi_type = "baremetal"
621 vpe_approx_vnf._provide_config_file = mock.Mock()
622 vpe_approx_vnf._build_config = mock.MagicMock()
624 self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
625 self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
626 self.assertIsNone(vpe_approx_vnf._run())
628 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig")
629 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
630 @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.ConfigCreate")
631 @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.open")
632 @mock.patch(SSH_HELPER)
633 def test_build_config(self, ssh, *args):
635 vpe_approx_vnf = VpeApproxSetupEnvHelper(mock.MagicMock(),
636 mock.MagicMock, mock.MagicMock)
637 vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
638 vpe_approx_vnf.generate_port_pairs = mock.Mock()
639 vpe_approx_vnf.vnf_cfg = {
642 'worker_config': '1C/1T',
645 vpe_approx_vnf.scenario_helper.scenario_cfg = {
649 'topology': 'nsb_test_case.yaml',
650 'vnf_config': 'vpe_config',
654 vpe_approx_vnf.topology = "nsb_test_case.yaml"
655 vpe_approx_vnf.nfvi_type = "baremetal"
656 vpe_approx_vnf._provide_config_file = mock.Mock()
658 vpe_approx_vnf.ssh_helper = mock.MagicMock()
659 vpe_approx_vnf.scenario_helper = mock.MagicMock()
660 vpe_approx_vnf.ssh_helper.bin_path = mock.Mock()
661 vpe_approx_vnf.ssh_helper.upload_config_file = mock.MagicMock()
662 self.assertIsNone(vpe_approx_vnf._build_vnf_ports())
663 self.assertIsNotNone(vpe_approx_vnf.build_config())
665 @mock.patch(SSH_HELPER)
666 def test_wait_for_instantiate(self, ssh):
669 mock_process = mock.Mock(autospec=Process)
670 mock_process.is_alive.return_value = True
671 mock_process.exitcode = 432
673 mock_q_out = mock.Mock(autospec=Queue)
674 mock_q_out.get.side_effect = iter(["pipeline>"])
675 mock_q_out.qsize.side_effect = range(1, -1, -1)
677 mock_resource = mock.MagicMock()
679 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
680 vpe_approx_vnf._vnf_process = mock_process
681 vpe_approx_vnf.q_out = mock_q_out
682 vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
683 vpe_approx_vnf.resource_helper.resource = mock_resource
685 vpe_approx_vnf.q_out.put("pipeline>")
686 self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
688 @mock.patch(SSH_HELPER)
689 def test_wait_for_instantiate_fragmented(self, ssh):
692 mock_process = mock.Mock(autospec=Process)
693 mock_process.is_alive.return_value = True
694 mock_process.exitcode = 432
696 # test that fragmented pipeline prompt is recognized
697 mock_q_out = mock.Mock(autospec=Queue)
698 mock_q_out.get.side_effect = iter(["wow pipel", "ine>"])
699 mock_q_out.qsize.side_effect = range(2, -1, -1)
701 mock_resource = mock.MagicMock()
703 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
704 vpe_approx_vnf._vnf_process = mock_process
705 vpe_approx_vnf.q_out = mock_q_out
706 vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
707 vpe_approx_vnf.resource_helper.resource = mock_resource
709 self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
711 @mock.patch(SSH_HELPER)
712 def test_wait_for_instantiate_crash(self, ssh):
713 mock_ssh(ssh, exec_result=(1, "", ""))
715 mock_process = mock.Mock(autospec=Process)
716 mock_process.is_alive.return_value = False
717 mock_process.exitcode = 432
719 mock_resource = mock.MagicMock()
721 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
722 vpe_approx_vnf._vnf_process = mock_process
723 vpe_approx_vnf.resource_helper.resource = mock_resource
725 with self.assertRaises(RuntimeError) as raised:
726 vpe_approx_vnf.wait_for_instantiate()
728 self.assertIn('VNF process died', str(raised.exception))
730 @mock.patch(SSH_HELPER)
731 def test_wait_for_instantiate_panic(self, ssh):
732 mock_ssh(ssh, exec_result=(1, "", ""))
734 mock_process = mock.Mock(autospec=Process)
735 mock_process.is_alive.return_value = True
736 mock_process.exitcode = 432
738 mock_resource = mock.MagicMock()
740 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
741 vpe_approx_vnf._vnf_process = mock_process
742 vpe_approx_vnf.resource_helper.resource = mock_resource
744 vpe_approx_vnf.q_out.put("PANIC")
745 with self.assertRaises(RuntimeError) as raised:
746 vpe_approx_vnf.wait_for_instantiate()
748 self.assertIn('Error starting', str(raised.exception))
750 @mock.patch(SSH_HELPER)
751 def test_wait_for_instantiate_panic_fragmented(self, ssh):
752 mock_ssh(ssh, exec_result=(1, "", ""))
754 mock_process = mock.Mock(autospec=Process)
755 mock_process.is_alive.return_value = True
756 mock_process.exitcode = 432
758 # test that fragmented PANIC is recognized
759 mock_q_out = mock.Mock(autospec=Queue)
760 mock_q_out.get.side_effect = iter(["omg PA", "NIC this is bad"])
761 mock_q_out.qsize.side_effect = range(2, -1, -1)
763 mock_resource = mock.MagicMock()
765 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
766 vpe_approx_vnf._vnf_process = mock_process
767 vpe_approx_vnf.q_out = mock_q_out
768 vpe_approx_vnf.resource_helper.resource = mock_resource
770 with self.assertRaises(RuntimeError) as raised:
771 vpe_approx_vnf.wait_for_instantiate()
773 self.assertIn('Error starting', str(raised.exception))
775 @mock.patch(SSH_HELPER)
776 def test_terminate(self, ssh):
779 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
780 vpe_approx_vnf._vnf_process = mock.MagicMock()
781 vpe_approx_vnf._resource_collect_stop = mock.Mock()
782 vpe_approx_vnf.resource_helper = mock.MagicMock()
784 self.assertIsNone(vpe_approx_vnf.terminate())