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 __future__ import absolute_import
19 import six.moves.configparser as configparser
24 from multiprocessing import Process, Queue
26 from tests.unit import STL_MOCKS
27 from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
30 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
32 STLClient = mock.MagicMock()
33 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
37 from yardstick.network_services.vnf_generic.vnf.vpe_vnf import ConfigCreate
38 from yardstick.network_services.nfvi.resource import ResourceProfile
39 from yardstick.network_services.vnf_generic.vnf.vpe_vnf import \
40 VpeApproxVnf, VpeApproxSetupEnvHelper
42 from tests.unit.network_services.vnf_generic.vnf.test_base import FileAbsPath
43 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
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):
58 def test___init__(self):
59 config_create = ConfigCreate([0], [1], 2)
60 self.assertEqual(config_create.priv_ports, [0])
61 self.assertEqual(config_create.pub_ports, [1])
62 self.assertEqual(config_create.socket, 2)
64 def test_vpe_initialize(self):
65 config_create = ConfigCreate([0], [1], 2)
66 config = configparser.ConfigParser()
67 config_create.vpe_initialize(config)
68 self.assertEqual(config.get('EAL', 'log_level'), '0')
69 self.assertEqual(config.get('PIPELINE0', 'type'), 'MASTER')
70 self.assertEqual(config.get('PIPELINE0', 'core'), 's2C0')
71 self.assertEqual(config.get('MEMPOOL0', 'pool_size'), '256K')
72 self.assertEqual(config.get('MEMPOOL1', 'pool_size'), '2M')
74 def test_vpe_rxq(self):
75 config_create = ConfigCreate([0], [1, 2], 3)
76 config = configparser.ConfigParser()
77 config_create.vpe_rxq(config)
78 self.assertEqual(config.get('RXQ1.0', 'mempool'), 'MEMPOOL1')
79 self.assertEqual(config.get('RXQ2.0', 'mempool'), 'MEMPOOL1')
81 def test_get_sink_swq(self):
82 config_create = ConfigCreate([0], [1], 2)
83 config = configparser.ConfigParser()
84 config.add_section('PIPELINE0')
85 config.set('PIPELINE0', 'key1', 'value1')
86 config.set('PIPELINE0', 'key2', 'value2 SINK')
87 config.set('PIPELINE0', 'key3', 'TM value3')
88 config.set('PIPELINE0', 'key4', 'value4')
89 config.set('PIPELINE0', 'key5', 'the SINK value5')
91 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key1', 5), 'SWQ-1')
92 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key2', 5), 'SWQ-1 SINK0')
93 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key3', 5), 'SWQ-1 TM5')
94 config_create.sw_q += 1
95 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key4', 5), 'SWQ0')
96 self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key5', 5), 'SWQ0 SINK1')
98 def test_generate_vpe_script(self):
99 vpe_config_vnf = ConfigCreate([0], [0], 0)
102 "virtual-interface": {
104 "dst_mac": "00:00:00:00:00:00:02",
108 result = vpe_config_vnf.generate_vpe_script(intf)
109 self.assertIsInstance(result, str)
110 self.assertNotEqual(result, '')
112 def test_create_vpe_config(self):
135 config_create = ConfigCreate(priv_ports, pub_ports, 23)
136 curr_path = os.path.dirname(os.path.abspath(__file__))
137 vpe_cfg = "samples/vnf_samples/nsut/vpe/vpe_config"
138 vnf_cfg = os.path.join(curr_path, "../../../../..", vpe_cfg)
139 config_create.create_vpe_config(vnf_cfg)
140 os.system("git checkout -- %s" % vnf_cfg)
143 @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
144 class TestVpeApproxVnf(unittest.TestCase):
147 'short-name': 'VpeVnf',
152 'network': '152.16.100.20',
153 'netmask': '255.255.255.0',
154 'gateway': '152.16.100.20',
158 'network': '152.16.40.20',
159 'netmask': '255.255.255.0',
160 'gateway': '152.16.40.20',
164 'description': 'VPE approximation using DPDK',
165 'name': 'vpevnf-baremetal',
168 'network': '0064:ff9b:0:0:0:0:9810:6414',
170 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
174 'network': '0064:ff9b:0:0:0:0:9810:2814',
176 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
180 'id': 'vpevnf-baremetal',
181 'external-interface': [
183 'virtual-interface': {
184 'dst_mac': '00:00:00:00:00:04',
185 'vpci': '0000:05:00.0',
186 'local_ip': '152.16.100.19',
187 'type': 'PCI-PASSTHROUGH',
188 'netmask': '255.255.255.0',
190 'bandwidth': '10 Gbps',
192 'dst_ip': '152.16.100.20',
193 'local_iface_name': 'xe0',
194 'local_mac': '00:00:00:00:00:02',
195 'vld_id': 'private_0',
198 'vnfd-connection-point-ref': 'xe0',
202 'virtual-interface': {
203 'dst_mac': '00:00:00:00:00:03',
204 'vpci': '0000:05:00.1',
205 'local_ip': '152.16.40.19',
206 'type': 'PCI-PASSTHROUGH',
208 'netmask': '255.255.255.0',
210 'bandwidth': '10 Gbps',
211 'dst_ip': '152.16.40.20',
212 'local_iface_name': 'xe1',
213 'local_mac': '00:00:00:00:00:01',
214 'vld_id': 'public_0',
217 'vnfd-connection-point-ref': 'xe1',
223 'description': 'Vpe approximation using DPDK',
225 'vdu-id': 'vpevnf-baremetal',
238 'connection-point': [
248 'id': 'VpeApproxVnf',
253 'vnfd:vnfd-catalog': {
265 'allowed_drop_rate': '0.8 - 1',
268 'cfg': 'acl_1rule.yaml',
278 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
279 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
281 'object': 'NetworkServiceTestCase',
283 'output_filename': '/tmp/yardstick.out',
288 'traffic_profile': 'ipv4_throughput_vpe.yaml',
290 'flow': 'ipv4_Packets_vpe.yaml',
291 'imix': 'imix_voice.yaml',
295 'tg__2': 'trafficgen_2.yardstick',
296 'tg__1': 'trafficgen_1.yardstick',
297 'vnf__1': 'vnf.yardstick',
299 'topology': 'vpe-tg-topology-baremetal.yaml',
305 'member-vnf-index': '3',
306 'role': 'TrafficGen',
307 'name': 'trafficgen_2.yardstick',
308 'vnfd-id-ref': 'tg__2',
312 'local_iface_name': 'ens513f0',
314 'netmask': '255.255.255.0',
315 'local_ip': '152.16.40.20',
316 'dst_mac': '00:00:00:00:00:01',
317 'local_mac': '00:00:00:00:00:03',
318 'dst_ip': '152.16.40.19',
320 'vpci': '0000:02:00.0',
324 'local_iface_name': 'ens513f1',
325 'netmask': '255.255.255.0',
326 'network': '202.16.100.0',
327 'local_ip': '202.16.100.20',
328 'local_mac': '00:1e:67:d0:60:5d',
330 'vpci': '0000:02:00.1',
335 'VNF model': 'l3fwd_vnf.yaml',
339 'member-vnf-index': '1',
340 'role': 'TrafficGen',
341 'name': 'trafficgen_1.yardstick',
342 'vnfd-id-ref': 'tg__1',
346 'local_iface_name': 'ens785f0',
348 'netmask': '255.255.255.0',
349 'local_ip': '152.16.100.20',
350 'dst_mac': '00:00:00:00:00:02',
351 'local_mac': '00:00:00:00:00:04',
352 'dst_ip': '152.16.100.19',
354 'vpci': '0000:05:00.0',
358 'local_iface_name': 'ens785f1',
359 'netmask': '255.255.255.0',
360 'local_ip': '152.16.100.21',
361 'local_mac': '00:00:00:00:00:01',
363 'vpci': '0000:05:00.1',
368 'VNF model': 'tg_rfc2544_tpl.yaml',
372 'name': 'vnf.yardstick',
373 'vnfd-id-ref': 'vnf__1',
377 'local_iface_name': 'ens786f0',
379 'netmask': '255.255.255.0',
380 'local_ip': '152.16.100.19',
381 'dst_mac': '00:00:00:00:00:04',
382 'local_mac': '00:00:00:00:00:02',
383 'dst_ip': '152.16.100.20',
385 'vpci': '0000:05:00.0',
389 'local_iface_name': 'ens786f1',
391 'netmask': '255.255.255.0',
392 'local_ip': '152.16.40.19',
393 'dst_mac': '00:00:00:00:00:03',
394 'local_mac': '00:00:00:00:00:01',
395 'dst_ip': '152.16.40.20',
397 'vpci': '0000:05:00.1',
403 'netmask': '255.255.255.0',
404 'gateway': '152.16.100.20',
405 'network': '152.16.100.20',
409 'netmask': '255.255.255.0',
410 'gateway': '152.16.40.20',
411 'network': '152.16.40.20',
415 'member-vnf-index': '2',
422 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
423 'network': '0064:ff9b:0:0:0:0:9810:6414',
428 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
429 'network': '0064:ff9b:0:0:0:0:9810:2814',
434 'VNF model': 'vpe_vnf.yaml',
439 def test___init__(self, _):
440 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
441 self.assertIsNone(vpe_approx_vnf._vnf_process)
443 @mock.patch(SSH_HELPER)
444 def test_collect_kpi_sa_not_running(self, ssh, _):
447 resource = mock.Mock(autospec=ResourceProfile)
448 resource.check_if_sa_running.return_value = False, 'error'
449 resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
451 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
452 vpe_approx_vnf.q_in = mock.MagicMock()
453 vpe_approx_vnf.q_out = mock.MagicMock()
454 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
455 vpe_approx_vnf.resource_helper.resource = resource
458 'pkt_in_down_stream': 0,
459 'pkt_in_up_stream': 0,
460 'pkt_drop_down_stream': 0,
461 'pkt_drop_up_stream': 0,
462 'collect_stats': {'core': {}},
464 self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
466 @mock.patch(SSH_HELPER)
467 def test_collect_kpi_sa_running(self, ssh, _):
470 resource = mock.Mock(autospec=ResourceProfile)
471 resource.check_if_sa_running.return_value = True, 'good'
472 resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
474 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
475 vpe_approx_vnf.q_in = mock.MagicMock()
476 vpe_approx_vnf.q_out = mock.MagicMock()
477 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
478 vpe_approx_vnf.resource_helper.resource = resource
481 'pkt_in_down_stream': 0,
482 'pkt_in_up_stream': 0,
483 'pkt_drop_down_stream': 0,
484 'pkt_drop_up_stream': 0,
485 'collect_stats': {'core': {'foo': 234}},
487 self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
489 @mock.patch(SSH_HELPER)
490 def test_vnf_execute(self, ssh, _):
492 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
493 vpe_approx_vnf.q_in = mock.MagicMock()
494 vpe_approx_vnf.q_out = mock.MagicMock()
495 vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
496 self.assertEqual(vpe_approx_vnf.vnf_execute("quit", 0), '')
498 @mock.patch(SSH_HELPER)
499 def test_run_vpe(self, ssh, _):
502 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
503 vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
504 vpe_approx_vnf.vnf_cfg = {
507 'worker_config': '1C/1T',
510 vpe_approx_vnf.scenario_helper.scenario_cfg = {
514 'topology': 'nsb_test_case.yaml',
515 'vnf_config': 'vpe_config',
519 vpe_approx_vnf.topology = "nsb_test_case.yaml"
520 vpe_approx_vnf.nfvi_type = "baremetal"
521 vpe_approx_vnf._provide_config_file = mock.Mock()
522 vpe_approx_vnf._build_config = mock.MagicMock()
524 self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
525 self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
526 self.assertIsNone(vpe_approx_vnf._run())
528 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig")
529 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
530 @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.ConfigCreate")
531 @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.open")
532 @mock.patch(SSH_HELPER)
533 def test_build_config(self, mock_mul, mock_context, mock_config, mock_open, ssh, _):
535 vpe_approx_vnf = VpeApproxSetupEnvHelper(mock.MagicMock(),
536 mock.MagicMock, mock.MagicMock)
537 vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
538 vpe_approx_vnf.generate_port_pairs = mock.Mock()
539 vpe_approx_vnf.tg_port_pairs = [[[0], [1]]]
540 vpe_approx_vnf.vnf_port_pairs = [[[0], [1]]]
541 vpe_approx_vnf.vnf_cfg = {
544 'worker_config': '1C/1T',
547 vpe_approx_vnf.scenario_helper.scenario_cfg = {
551 'topology': 'nsb_test_case.yaml',
552 'vnf_config': 'vpe_config',
556 vpe_approx_vnf.topology = "nsb_test_case.yaml"
557 vpe_approx_vnf.nfvi_type = "baremetal"
558 vpe_approx_vnf._provide_config_file = mock.Mock()
560 vpe_approx_vnf.ssh_helper = mock.MagicMock()
561 vpe_approx_vnf.scenario_helper = mock.MagicMock()
562 vpe_approx_vnf.ssh_helper.bin_path = mock.Mock()
563 vpe_approx_vnf.ssh_helper.upload_config_file = mock.MagicMock()
564 self.assertIsNone(vpe_approx_vnf._build_vnf_ports())
565 self.assertIsNotNone(vpe_approx_vnf.build_config())
567 @mock.patch(SSH_HELPER)
568 def test_wait_for_instantiate(self, ssh, _):
571 mock_process = mock.Mock(autospec=Process)
572 mock_process.is_alive.return_value = True
573 mock_process.exitcode = 432
575 mock_q_out = mock.Mock(autospec=Queue)
576 mock_q_out.get.side_effect = iter(["pipeline>"])
577 mock_q_out.qsize.side_effect = range(1, -1, -1)
579 mock_resource = mock.MagicMock()
581 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
582 vpe_approx_vnf._vnf_process = mock_process
583 vpe_approx_vnf.q_out = mock_q_out
584 vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
585 vpe_approx_vnf.resource_helper.resource = mock_resource
587 vpe_approx_vnf.q_out.put("pipeline>")
588 self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
590 @mock.patch(SSH_HELPER)
591 def test_wait_for_instantiate_fragmented(self, ssh, _):
594 mock_process = mock.Mock(autospec=Process)
595 mock_process.is_alive.return_value = True
596 mock_process.exitcode = 432
598 # test that fragmented pipeline prompt is recognized
599 mock_q_out = mock.Mock(autospec=Queue)
600 mock_q_out.get.side_effect = iter(["wow pipel", "ine>"])
601 mock_q_out.qsize.side_effect = range(2, -1, -1)
603 mock_resource = mock.MagicMock()
605 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
606 vpe_approx_vnf._vnf_process = mock_process
607 vpe_approx_vnf.q_out = mock_q_out
608 vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
609 vpe_approx_vnf.resource_helper.resource = mock_resource
611 self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
613 @mock.patch(SSH_HELPER)
614 def test_wait_for_instantiate_crash(self, ssh, _):
615 mock_ssh(ssh, exec_result=(1, "", ""))
617 mock_process = mock.Mock(autospec=Process)
618 mock_process.is_alive.return_value = False
619 mock_process.exitcode = 432
621 mock_resource = mock.MagicMock()
623 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
624 vpe_approx_vnf._vnf_process = mock_process
625 vpe_approx_vnf.resource_helper.resource = mock_resource
627 with self.assertRaises(RuntimeError) as raised:
628 vpe_approx_vnf.wait_for_instantiate()
630 self.assertIn('VNF process died', str(raised.exception))
632 @mock.patch(SSH_HELPER)
633 def test_wait_for_instantiate_panic(self, ssh, _):
634 mock_ssh(ssh, exec_result=(1, "", ""))
636 mock_process = mock.Mock(autospec=Process)
637 mock_process.is_alive.return_value = True
638 mock_process.exitcode = 432
640 mock_resource = mock.MagicMock()
642 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
643 vpe_approx_vnf._vnf_process = mock_process
644 vpe_approx_vnf.resource_helper.resource = mock_resource
646 vpe_approx_vnf.q_out.put("PANIC")
647 with self.assertRaises(RuntimeError) as raised:
648 vpe_approx_vnf.wait_for_instantiate()
650 self.assertIn('Error starting', str(raised.exception))
652 @mock.patch(SSH_HELPER)
653 def test_wait_for_instantiate_panic_fragmented(self, ssh, _):
654 mock_ssh(ssh, exec_result=(1, "", ""))
656 mock_process = mock.Mock(autospec=Process)
657 mock_process.is_alive.return_value = True
658 mock_process.exitcode = 432
660 # test that fragmented PANIC is recognized
661 mock_q_out = mock.Mock(autospec=Queue)
662 mock_q_out.get.side_effect = iter(["omg PA", "NIC this is bad"])
663 mock_q_out.qsize.side_effect = range(2, -1, -1)
665 mock_resource = mock.MagicMock()
667 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
668 vpe_approx_vnf._vnf_process = mock_process
669 vpe_approx_vnf.q_out = mock_q_out
670 vpe_approx_vnf.resource_helper.resource = mock_resource
672 with self.assertRaises(RuntimeError) as raised:
673 vpe_approx_vnf.wait_for_instantiate()
675 self.assertIn('Error starting', str(raised.exception))
677 def test_scale(self, _):
678 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
679 with self.assertRaises(NotImplementedError):
680 vpe_approx_vnf.scale('')
682 @mock.patch(SSH_HELPER)
683 def test_terminate(self, ssh, _):
686 vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
687 vpe_approx_vnf._vnf_process = mock.MagicMock()
688 vpe_approx_vnf._resource_collect_stop = mock.Mock()
689 vpe_approx_vnf.resource_helper = mock.MagicMock()
691 self.assertIsNone(vpe_approx_vnf.terminate())
694 if __name__ == '__main__':