diff options
Diffstat (limited to 'yardstick/tests/unit/network_services/vnf_generic')
5 files changed, 4079 insertions, 12 deletions
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py index f8126307c..8b245b3bf 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py @@ -19,11 +19,12 @@ import mock from yardstick.benchmark.contexts import base as ctx_base from yardstick.common import utils +from yardstick.network_services.helpers import cpu from yardstick.network_services.nfvi.resource import ResourceProfile -from yardstick.network_services.vnf_generic.vnf import ipsec_vnf +from yardstick.network_services.vnf_generic.vnf import ipsec_vnf, vpp_helpers from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper -from yardstick.network_services.vnf_generic.vnf.ipsec_vnf import \ - VipsecApproxSetupEnvHelper +from yardstick.network_services.vnf_generic.vnf.ipsec_vnf import CryptoAlg, \ + IntegAlg, VipsecApproxSetupEnvHelper from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import \ mock_ssh @@ -32,6 +33,24 @@ SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper NAME = 'vnf__1' +class TestCryptoAlg(unittest.TestCase): + + def test__init__(self): + encr_alg = CryptoAlg.AES_GCM_128 + self.assertEqual('aes-gcm-128', encr_alg.alg_name) + self.assertEqual('AES-GCM', encr_alg.scapy_name) + self.assertEqual(20, encr_alg.key_len) + + +class TestIntegAlg(unittest.TestCase): + + def test__init__(self): + auth_alg = IntegAlg.AES_GCM_128 + self.assertEqual('aes-gcm-128', auth_alg.alg_name) + self.assertEqual('AES-GCM', auth_alg.scapy_name) + self.assertEqual(20, auth_alg.key_len) + + @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process") class TestVipsecApproxVnf(unittest.TestCase): VNFD = {'vnfd:vnfd-catalog': @@ -791,6 +810,62 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): } } + ALL_OPTIONS_CBC_ALGORITHMS = { + "flow": { + "count": 1, + "dst_ip": [ + "20.0.0.0-20.0.0.100" + ], + "src_ip": [ + "10.0.0.0-10.0.0.100" + ] + }, + "framesize": { + "downlink": { + "64B": 100 + }, + "uplink": { + "64B": 100 + } + }, + "rfc2544": { + "allowed_drop_rate": "0.0 - 0.005" + }, + "tg__0": { + "collectd": { + "interval": 1 + }, + "queues_per_port": 7 + }, + "traffic_type": 4, + "vnf__0": { + "collectd": { + "interval": 1 + }, + "vnf_config": { + "crypto_type": "SW_cryptodev", + "rxq": 1, + "worker_config": "1C/1T", + "worker_threads": 4 + } + }, + "vnf__1": { + "collectd": { + "interval": 1 + }, + "vnf_config": { + "crypto_type": "SW_cryptodev", + "rxq": 1, + "worker_config": "1C/1T", + "worker_threads": 4 + } + }, + "vpp_config": { + "crypto_algorithms": "cbc-sha1", + "tunnel": 1 + } + } + ALL_OPTIONS_ERROR = { "flow_error": { "count": 1, @@ -859,6 +934,18 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): } } + OPTIONS_HW = { + "collectd": { + "interval": 1 + }, + "vnf_config": { + "crypto_type": "HW_cryptodev", + "rxq": 1, + "worker_config": "1C/1T", + "worker_threads": 4 + } + } + CPU_LAYOUT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1, 1, 0], [2, 1, 0, 0, 0, 2, 2, 1], @@ -877,6 +964,24 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): [15, 8, 0, 1, 0, 15, 15, 7], [16, 9, 0, 1, 0, 16, 16, 8], [17, 9, 0, 1, 0, 17, 17, 8]]} + CPU_SMT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 1, 0], + [2, 1, 0, 0, 0, 2, 2, 1], + [3, 1, 0, 0, 0, 3, 3, 1], + [4, 2, 0, 0, 0, 4, 4, 2], + [5, 2, 0, 0, 0, 5, 5, 2], + [6, 3, 0, 0, 0, 6, 6, 3], + [7, 3, 0, 0, 0, 7, 7, 3], + [8, 4, 0, 0, 0, 8, 8, 4], + [9, 5, 0, 1, 0, 0, 0, 0], + [10, 6, 0, 1, 0, 1, 1, 0], + [11, 6, 0, 1, 0, 2, 2, 1], + [12, 7, 0, 1, 0, 3, 3, 1], + [13, 7, 0, 1, 0, 4, 4, 2], + [14, 8, 0, 1, 0, 5, 5, 2], + [15, 8, 0, 1, 0, 6, 6, 3], + [16, 9, 0, 1, 0, 7, 7, 3], + [17, 9, 0, 1, 0, 8, 8, 4]]} VPP_INTERFACES_DUMP = [ { @@ -1126,12 +1231,97 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): vnfd_helper = VnfdHelper( TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.build_config()) + self.assertEqual(0, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'numa_node')) + self.assertEqual('TenGigabitEthernetff/6/0', + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'vpp_name')) + self.assertEqual(1, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'vpp_sw_index')) + self.assertEqual(0, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'numa_node')) + self.assertEqual('VirtualFunctionEthernetff/7/0', + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'vpp_name')) + self.assertEqual(2, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'vpp_sw_index')) + self.assertGreaterEqual(ssh_helper.execute.call_count, 4) + + def test_build_config_cbc_algorithms(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS_CBC_ALGORITHMS ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper) - ipsec_approx_setup_helper.build_config() + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.build_config()) + self.assertEqual(0, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'numa_node')) + self.assertEqual('TenGigabitEthernetff/6/0', + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'vpp_name')) + self.assertEqual(1, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'vpp_sw_index')) + self.assertEqual(0, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'numa_node')) + self.assertEqual('VirtualFunctionEthernetff/7/0', + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'vpp_name')) + self.assertEqual(2, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'vpp_sw_index')) + self.assertGreaterEqual(ssh_helper.execute.call_count, 4) @mock.patch.object(utils, 'setup_hugepages') def test_setup_vnf_environment(self, *args): @@ -1147,9 +1337,36 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper) - self.assertIsInstance( - ipsec_approx_setup_helper.setup_vnf_environment(), - ResourceProfile) + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + self.assertIsInstance( + ipsec_approx_setup_helper.setup_vnf_environment(), + ResourceProfile) + self.assertEqual(0, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'numa_node')) + self.assertEqual('TenGigabitEthernetff/6/0', + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'vpp_name')) + self.assertEqual(1, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe0', 'vpp_sw_index')) + self.assertEqual(0, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'numa_node')) + self.assertEqual('VirtualFunctionEthernetff/7/0', + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'vpp_name')) + self.assertEqual(2, + ipsec_approx_setup_helper.get_value_by_interface_key( + 'xe1', 'vpp_sw_index')) + self.assertGreaterEqual(ssh_helper.execute.call_count, 4) def test_calculate_frame_size(self): vnfd_helper = VnfdHelper( @@ -1214,6 +1431,90 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): self.assertFalse(ipsec_approx_setup_helper.check_status()) def test_get_vpp_statistics(self): + def execute(cmd): + if 'TenGigabitEthernetff/6/0' in cmd: + return 0, output_xe0, '' + elif 'VirtualFunctionEthernetff/7/0' in cmd: + return 0, output_xe1, '' + return 0, '0', '' + + output_xe0 = \ + ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \ + ' Counter Count \n' \ + 'TenGigabitEthernetff/6/0 1 up 9200/0/0/0 ' \ + 'rx packets 23373568\n' \ + ' ' \ + 'rx bytes 1402414080\n' \ + ' ' \ + 'tx packets 20476416\n' \ + ' ' \ + 'tx bytes 1228584960\n' \ + ' ' \ + 'ip4 23373568\n' \ + ' ' \ + 'rx-miss 27789925' + output_xe1 = \ + ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \ + ' Counter Count \n' \ + 'VirtualFunctionEthernetff/7/0 2 up 9200/0/0/0 ' \ + 'rx packets 23373568\n' \ + ' ' \ + 'rx bytes 1402414080\n' \ + ' ' \ + 'tx packets 20476416\n' \ + ' ' \ + 'tx bytes 1228584960\n' \ + ' ' \ + 'ip4 23373568\n' \ + ' ' \ + 'rx-miss 27789925' + + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute = execute + scenario_helper = mock.Mock() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertEqual({'xe0': {'packets_dropped': 27789925, + 'packets_fwd': 20476416, + 'packets_in': 23373568}, + 'xe1': {'packets_dropped': 27789925, + 'packets_fwd': 20476416, + 'packets_in': 23373568}}, + ipsec_approx_setup_helper.get_vpp_statistics()) + + def test_parser_vpp_stats(self): + output = \ + ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \ + 'Counter Count \n' \ + 'TenGigabitEthernetff/6/0 1 up 9200/0/0/0 ' \ + 'rx packets 23373568\n' \ + ' ' \ + 'rx bytes 1402414080\n' \ + ' ' \ + 'tx packets 20476416\n' \ + ' ' \ + 'tx bytes 1228584960\n' \ + ' ' \ + 'ip4 23373568\n' \ + ' ' \ + 'rx-miss 27789925' vnfd_helper = VnfdHelper( TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) ssh_helper = mock.Mock() @@ -1222,18 +1523,152 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper) - ipsec_approx_setup_helper.get_vpp_statistics() + self.assertEqual({'xe0': {'packets_dropped': 27789925, + 'packets_fwd': 20476416, + 'packets_in': 23373568}}, + ipsec_approx_setup_helper.parser_vpp_stats('xe0', + 'TenGigabitEthernetff/6/0', + output)) + + def test_parser_vpp_stats_no_miss(self): + output = \ + ' Name Idx State ' \ + 'Counter Count \n' \ + 'TenGigabitEthernetff/6/0 1 up ' \ + 'rx packets 23373568\n' \ + ' ' \ + 'rx bytes 1402414080\n' \ + ' ' \ + 'tx packets 20476416\n' \ + ' ' \ + 'tx bytes 1228584960\n' \ + ' ' \ + 'ip4 23373568' + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + self.assertEqual({'xe0': {'packets_dropped': 2897152, + 'packets_fwd': 20476416, + 'packets_in': 23373568}}, + ipsec_approx_setup_helper.parser_vpp_stats('xe0', + 'TenGigabitEthernetff/6/0', + output)) def test_create_ipsec_tunnels(self): vnfd_helper = VnfdHelper( TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out, \ + mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template, \ + mock.patch.object(ipsec_approx_setup_helper, + 'vpp_get_interface_data') as \ + mock_ipsec_approx_setup_helper: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + mock_vat_terminal_exec_cmd_from_template.return_value = self.VPP_INTERFACES_DUMP + mock_ipsec_approx_setup_helper.return_value = self.VPP_INTERFACES_DUMP + sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.create_ipsec_tunnels()) + self.assertGreaterEqual( + mock_vat_terminal_exec_cmd_from_template.call_count, 9) + + def test_create_ipsec_tunnels_cbc_algorithms(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS_CBC_ALGORITHMS ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper) - ipsec_approx_setup_helper.create_ipsec_tunnels() + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out, \ + mock.patch.object(ipsec_approx_setup_helper, + 'find_encrypted_data_interface') as \ + mock_find_encrypted_data_interface, \ + mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template, \ + mock.patch.object(ipsec_approx_setup_helper, + 'vpp_get_interface_data') as \ + mock_ipsec_approx_setup_helper: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + mock_find_encrypted_data_interface.return_value = { + 'dpdk_port_num': 0, + 'driver': 'igb_uio', + 'dst_ip': '192.168.100.1', + 'dst_mac': '90:e2:ba:7c:30:e8', + 'ifname': 'xe0', + 'local_ip': '192.168.100.2', + 'local_mac': '90:e2:ba:7c:41:a8', + 'netmask': '255.255.255.0', + 'network': {}, + 'node_name': 'vnf__1', + 'numa_node': 0, + 'peer_ifname': 'xe0', + 'peer_intf': {'dpdk_port_num': 0, + 'driver': 'igb_uio', + 'dst_ip': '192.168.100.2', + 'dst_mac': '90:e2:ba:7c:41:a8', + 'ifname': 'xe0', + 'local_ip': '192.168.100.1', + 'local_mac': '90:e2:ba:7c:30:e8', + 'netmask': '255.255.255.0', + 'network': {}, + 'node_name': 'tg__0', + 'peer_ifname': 'xe0', + 'peer_name': 'vnf__0', + 'vld_id': 'uplink_0', + 'vpci': '0000:81:00.0'}, + 'peer_name': 'tg__0', + 'vld_id': 'uplink_0', + 'vpci': '0000:ff:06.0', + 'vpp_name': u'TenGigabitEthernetff/6/0', + 'vpp_sw_index': 1} + mock_vat_terminal_exec_cmd_from_template.return_value = self.VPP_INTERFACES_DUMP + mock_ipsec_approx_setup_helper.return_value = self.VPP_INTERFACES_DUMP + sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.create_ipsec_tunnels()) + self.assertGreaterEqual( + mock_vat_terminal_exec_cmd_from_template.call_count, 9) def test_find_raw_data_interface(self): expected = {'dpdk_port_num': 0, @@ -1246,6 +1681,7 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): 'netmask': '255.255.255.0', 'network': {}, 'node_name': 'vnf__0', + 'numa_node': 0, 'peer_ifname': 'xe0', 'peer_intf': {'dpdk_port_num': 0, 'driver': 'igb_uio', @@ -1263,7 +1699,9 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): 'vpci': '0000:81:00.0'}, 'peer_name': 'tg__0', 'vld_id': 'uplink_0', - 'vpci': '0000:ff:06.0'} + 'vpci': '0000:ff:06.0', + 'vpp_name': u'TenGigabitEthernetff/6/0', + 'vpp_sw_index': 1} vnfd_helper = VnfdHelper( TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) ssh_helper = mock.Mock() @@ -1298,6 +1736,7 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): 'netmask': '255.255.255.0', 'network': {}, 'node_name': 'vnf__0', + 'numa_node': 0, 'peer_ifname': 'xe1', 'peer_intf': {'driver': 'igb_uio', 'dst_ip': '1.1.1.1', @@ -1314,7 +1753,9 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): 'vpci': '0000:00:07.0'}, 'peer_name': 'vnf__1', 'vld_id': 'ciphertext', - 'vpci': '0000:ff:07.0'} + 'vpci': '0000:ff:07.0', + 'vpp_name': u'VirtualFunctionEthernetff/7/0', + 'vpp_sw_index': 2} vnfd_helper = VnfdHelper( TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) ssh_helper = mock.Mock() @@ -1325,3 +1766,341 @@ class TestVipsecApproxSetupEnvHelper(unittest.TestCase): scenario_helper) self.assertEqual(expected, ipsec_approx_setup_helper.find_encrypted_data_interface()) + + def test_create_startup_configuration_of_vpp(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsInstance( + ipsec_approx_setup_helper.create_startup_configuration_of_vpp(), + vpp_helpers.VppConfigGenerator) + + def test_add_worker_threads_and_rxqueues(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone( + ipsec_approx_setup_helper.add_worker_threads_and_rxqueues( + vpp_config_generator, 1, 1)) + self.assertEqual( + 'cpu\n{\n corelist-workers 2\n main-core 1\n}\ndpdk\n{\n ' \ + 'dev default\n {\n num-rx-queues 1\n }\n num-mbufs 32768\n}\n', + vpp_config_generator.dump_config()) + + def test_add_worker_threads_and_rxqueues_smt(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_SMT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_SMT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone( + ipsec_approx_setup_helper.add_worker_threads_and_rxqueues( + vpp_config_generator, 1)) + self.assertEqual( + 'cpu\n{\n corelist-workers 2,6\n main-core 1\n}\ndpdk\n{\n ' \ + 'dev default\n {\n num-rx-queues 1\n }\n num-mbufs 32768\n}\n', + vpp_config_generator.dump_config()) + + def test_add_worker_threads_and_rxqueues_with_numa(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone( + ipsec_approx_setup_helper.add_worker_threads_and_rxqueues( + vpp_config_generator, 1, 1)) + self.assertEqual( + 'cpu\n{\n corelist-workers 2\n main-core 1\n}\ndpdk\n{\n ' \ + 'dev default\n {\n num-rx-queues 1\n }\n num-mbufs 32768\n}\n', + vpp_config_generator.dump_config()) + + def test_add_pci_devices(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.add_pci_devices( + vpp_config_generator)) + self.assertEqual( + 'dpdk\n{\n dev 0000:ff:06.0 \n dev 0000:ff:07.0 \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_cryptodev(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev( + vpp_config_generator, 'aesni_gcm', 1)) + self.assertEqual( + 'dpdk\n{\n vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_cryptodev_hw(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS_HW + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev( + vpp_config_generator, 'aesni_gcm', 1)) + self.assertEqual( + 'dpdk\n{\n dev 0000:ff:01.0 \n uio-driver igb_uio\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_cryptodev_smt_used(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out: + mock_get_cpu_layout.return_value = self.CPU_SMT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev( + vpp_config_generator, 'aesni_gcm', 1)) + self.assertEqual( + 'dpdk\n{\n vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_cryptodev_smt_used_hw(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS_HW + scenario_helper.all_options = self.ALL_OPTIONS + vpp_config_generator = vpp_helpers.VppConfigGenerator() + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout: + mock_get_cpu_layout.return_value = self.CPU_SMT + ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_SMT + ipsec_approx_setup_helper._update_vnfd_helper( + ipsec_approx_setup_helper.sys_cores.get_cpu_layout()) + self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev( + vpp_config_generator, 'aesni_gcm', 1)) + self.assertEqual( + 'dpdk\n{\n dev 0000:ff:01.0 \n dev 0000:ff:01.1 \n uio-driver igb_uio\n}\n', + vpp_config_generator.dump_config()) + + def test_initialize_ipsec(self): + vnfd_helper = VnfdHelper( + TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + scenario_helper.all_options = self.ALL_OPTIONS + + ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper, + ssh_helper, + scenario_helper) + + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout, \ + mock.patch.object(ipsec_approx_setup_helper, + 'execute_script_json_out') as \ + mock_execute_script_json_out, \ + mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template, \ + mock.patch.object(ipsec_approx_setup_helper, + 'vpp_get_interface_data') as \ + mock_ipsec_approx_setup_helper: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + mock_execute_script_json_out.return_value = str( + self.VPP_INTERFACES_DUMP).replace("\'", "\"") + mock_vat_terminal_exec_cmd_from_template.return_value = '' + mock_ipsec_approx_setup_helper.return_value = self.VPP_INTERFACES_DUMP + sys_cores = cpu.CpuSysCores(ssh_helper) + ipsec_approx_setup_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + ipsec_approx_setup_helper.update_vpp_interface_data() + ipsec_approx_setup_helper.iface_update_numa() + self.assertIsNone(ipsec_approx_setup_helper.initialize_ipsec()) + self.assertGreaterEqual( + mock_vat_terminal_exec_cmd_from_template.call_count, 9) diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py new file mode 100755 index 000000000..3b226d3f1 --- /dev/null +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py @@ -0,0 +1,652 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import mock +import socket +import threading +import time +import os +import copy + +from yardstick.benchmark.contexts import base as ctx_base +from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper +from yardstick.network_services.vnf_generic.vnf import tg_vcmts_pktgen +from yardstick.common import exceptions + + +NAME = "tg__0" + + +class TestPktgenHelper(unittest.TestCase): + + def test___init__(self): + pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000) + self.assertEqual(pktgen_helper.host, "localhost") + self.assertEqual(pktgen_helper.port, 23000) + self.assertFalse(pktgen_helper.connected) + + def _run_fake_server(self): + server_sock = socket.socket() + server_sock.bind(('localhost', 23000)) + server_sock.listen(0) + client_socket, _ = server_sock.accept() + client_socket.close() + server_sock.close() + + def test__connect(self): + pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000) + self.assertFalse(pktgen_helper._connect()) + server_thread = threading.Thread(target=self._run_fake_server) + server_thread.start() + time.sleep(0.5) + self.assertTrue(pktgen_helper._connect()) + pktgen_helper._sock.close() + server_thread.join() + + @mock.patch('yardstick.network_services.vnf_generic.vnf.tg_vcmts_pktgen.time') + def test_connect(self, *args): + pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000) + pktgen_helper.connected = True + self.assertTrue(pktgen_helper.connect()) + pktgen_helper.connected = False + + pktgen_helper._connect = mock.MagicMock(return_value=True) + self.assertTrue(pktgen_helper.connect()) + self.assertTrue(pktgen_helper.connected) + + pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000) + pktgen_helper._connect = mock.MagicMock(return_value=False) + self.assertFalse(pktgen_helper.connect()) + self.assertFalse(pktgen_helper.connected) + + def test_send_command(self): + pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000) + self.assertFalse(pktgen_helper.send_command("")) + + pktgen_helper.connected = True + pktgen_helper._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.assertFalse(pktgen_helper.send_command("")) + + pktgen_helper._sock = mock.MagicMock() + self.assertTrue(pktgen_helper.send_command("")) + + +class TestVcmtsPktgenSetupEnvHelper(unittest.TestCase): + + PKTGEN_PARAMETERS = "export LUA_PATH=/vcmts/Pktgen.lua;"\ + "export CMK_PROC_FS=/host/proc;"\ + " /pktgen-config/setup.sh 0 4 18:02.0 "\ + "18:02.1 18:02.2 18:02.3 00:00.0 00:00.0 "\ + "00:00.0 00:00.0 imix1_100cms_1ofdm.pcap "\ + "imix1_100cms_1ofdm.pcap imix1_100cms_1ofdm.pcap "\ + "imix1_100cms_1ofdm.pcap imix1_100cms_1ofdm.pcap "\ + "imix1_100cms_1ofdm.pcap imix1_100cms_1ofdm.pcap "\ + "imix1_100cms_1ofdm.pcap" + + OPTIONS = { + "pktgen_values": "/tmp/pktgen_values.yaml", + "tg__0": { + "pktgen_id": 0 + }, + "vcmts_influxdb_ip": "10.80.5.150", + "vcmts_influxdb_port": 8086, + "vcmtsd_values": "/tmp/vcmtsd_values.yaml", + "vnf__0": { + "sg_id": 0, + "stream_dir": "us" + }, + "vnf__1": { + "sg_id": 0, + "stream_dir": "ds" + } + } + + def setUp(self): + vnfd_helper = VnfdHelper( + TestVcmtsPktgen.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + + self.setup_helper = tg_vcmts_pktgen.VcmtsPktgenSetupEnvHelper( + vnfd_helper, ssh_helper, scenario_helper) + + def test_generate_pcap_filename(self): + pcap_file_name = self.setup_helper.generate_pcap_filename(\ + TestVcmtsPktgen.PKTGEN_POD_VALUES[0]['ports'][0]) + self.assertEquals(pcap_file_name, "imix1_100cms_1ofdm.pcap") + + def test_find_port_cfg(self): + port_cfg = self.setup_helper.find_port_cfg(\ + TestVcmtsPktgen.PKTGEN_POD_VALUES[0]['ports'], "port_0") + self.assertIsNotNone(port_cfg) + + port_cfg = self.setup_helper.find_port_cfg(\ + TestVcmtsPktgen.PKTGEN_POD_VALUES[0]['ports'], "port_8") + self.assertIsNone(port_cfg) + + def test_build_pktgen_parameters(self): + parameters = self.setup_helper.build_pktgen_parameters( + TestVcmtsPktgen.PKTGEN_POD_VALUES[0]) + self.assertEquals(parameters, self.PKTGEN_PARAMETERS) + + def test_start_pktgen(self): + self.setup_helper.ssh_helper = mock.MagicMock() + self.setup_helper.start_pktgen(TestVcmtsPktgen.PKTGEN_POD_VALUES[0]) + self.setup_helper.ssh_helper.send_command.assert_called_with( + self.PKTGEN_PARAMETERS) + + def test_setup_vnf_environment(self): + self.assertIsNone(self.setup_helper.setup_vnf_environment()) + +class TestVcmtsPktgen(unittest.TestCase): + + VNFD = {'vnfd:vnfd-catalog': + {'vnfd': + [{ + "benchmark": { + "kpi": [ + "upstream/bits_per_second" + ] + }, + "connection-point": [ + { + "name": "xe0", + "type": "VPORT" + }, + { + "name": "xe1", + "type": "VPORT" + } + ], + "description": "vCMTS Pktgen Kubernetes", + "id": "VcmtsPktgen", + "mgmt-interface": { + "ip": "192.168.24.150", + "key_filename": "/tmp/yardstick_key-a3b663c2", + "user": "root", + "vdu-id": "vcmtspktgen-kubernetes" + }, + "name": "vcmtspktgen", + "short-name": "vcmtspktgen", + "vdu": [ + { + "description": "vCMTS Pktgen Kubernetes", + "external-interface": [], + "id": "vcmtspktgen-kubernetes", + "name": "vcmtspktgen-kubernetes" + } + ], + "vm-flavor": { + "memory-mb": "4096", + "vcpu-count": "4" + } + }] + }} + + PKTGEN_POD_VALUES = [ + { + "num_ports": "4", + "pktgen_id": "0", + "ports": [ + { + "net_pktgen": "18:02.0", + "num_ofdm": "1", + "num_subs": "100", + "port_0": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "18:02.1", + "num_ofdm": "1", + "num_subs": "100", + "port_1": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "18:02.2", + "num_ofdm": "1", + "num_subs": "100", + "port_2": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "18:02.3", + "num_ofdm": "1", + "num_subs": "100", + "port_3": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_4": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_5": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_6": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_7": "", + "traffic_type": "imix1" + } + ] + }, + { + "num_ports": 4, + "pktgen_id": 1, + "ports": [ + { + "net_pktgen": "18:0a.0", + "num_ofdm": "1", + "num_subs": "100", + "port_0": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "18:0a.1", + "num_ofdm": "1", + "num_subs": "100", + "port_1": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "18:0a.2", + "num_ofdm": "1", + "num_subs": "100", + "port_2": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "18:0a.3", + "num_ofdm": "1", + "num_subs": "100", + "port_3": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_4": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_5": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_6": "", + "traffic_type": "imix1" + }, + { + "net_pktgen": "00:00.0", + "num_ofdm": "1", + "num_subs": "100", + "port_7": "", + "traffic_type": "imix1" + } + ] + } + ] + + SCENARIO_CFG = { + "nodes": { + "tg__0": "pktgen0-k8syardstick-a3b663c2", + "vnf__0": "vnf0us-k8syardstick-a3b663c2", + "vnf__1": "vnf0ds-k8syardstick-a3b663c2" + }, + "options": { + "pktgen_values": "/tmp/pktgen_values.yaml", + "tg__0": { + "pktgen_id": 0 + }, + "vcmts_influxdb_ip": "10.80.5.150", + "vcmts_influxdb_port": 8086, + "vcmtsd_values": "/tmp/vcmtsd_values.yaml", + "vnf__0": { + "sg_id": 0, + "stream_dir": "us" + }, + "vnf__1": { + "sg_id": 0, + "stream_dir": "ds" + } + }, + "task_id": "a3b663c2-e616-4777-b6d0-ec2ea7a06f42", + "task_path": "samples/vnf_samples/nsut/cmts", + "tc": "tc_vcmts_k8s_pktgen", + "topology": "k8s_vcmts_topology.yaml", + "traffic_profile": "../../traffic_profiles/fixed.yaml", + "type": "NSPerf" + } + + CONTEXT_CFG = { + "networks": { + "flannel": { + "name": "flannel" + }, + "xe0": { + "name": "xe0" + }, + "xe1": { + "name": "xe1" + } + }, + "nodes": { + "tg__0": { + "VNF model": "../../vnf_descriptors/tg_vcmts_tpl.yaml", + "interfaces": { + "flannel": { + "local_ip": "192.168.24.150", + "local_mac": None, + "network_name": "flannel" + }, + "xe0": { + "local_ip": "192.168.24.150", + "local_mac": None, + "network_name": "xe0" + }, + "xe1": { + "local_ip": "192.168.24.150", + "local_mac": None, + "network_name": "xe1" + } + }, + "ip": "192.168.24.150", + "key_filename": "/tmp/yardstick_key-a3b663c2", + "member-vnf-index": "1", + "name": "pktgen0-k8syardstick-a3b663c2", + "private_ip": "192.168.24.150", + "service_ports": [ + { + "name": "ssh", + "node_port": 60270, + "port": 22, + "protocol": "TCP", + "target_port": 22 + }, + { + "name": "lua", + "node_port": 43619, + "port": 22022, + "protocol": "TCP", + "target_port": 22022 + } + ], + "ssh_port": 60270, + "user": "root", + "vnfd-id-ref": "tg__0" + }, + "vnf__0": { + "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml", + "interfaces": { + "flannel": { + "local_ip": "192.168.100.132", + "local_mac": None, + "network_name": "flannel" + }, + "xe0": { + "local_ip": "192.168.100.132", + "local_mac": None, + "network_name": "xe0" + }, + "xe1": { + "local_ip": "192.168.100.132", + "local_mac": None, + "network_name": "xe1" + } + }, + "ip": "192.168.100.132", + "key_filename": "/tmp/yardstick_key-a3b663c2", + "member-vnf-index": "3", + "name": "vnf0us-k8syardstick-a3b663c2", + "private_ip": "192.168.100.132", + "service_ports": [ + { + "name": "ssh", + "node_port": 57057, + "port": 22, + "protocol": "TCP", + "target_port": 22 + }, + { + "name": "lua", + "node_port": 29700, + "port": 22022, + "protocol": "TCP", + "target_port": 22022 + } + ], + "ssh_port": 57057, + "user": "root", + "vnfd-id-ref": "vnf__0" + }, + "vnf__1": { + "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml", + "interfaces": { + "flannel": { + "local_ip": "192.168.100.134", + "local_mac": None, + "network_name": "flannel" + }, + "xe0": { + "local_ip": "192.168.100.134", + "local_mac": None, + "network_name": "xe0" + }, + "xe1": { + "local_ip": "192.168.100.134", + "local_mac": None, + "network_name": "xe1" + } + }, + "ip": "192.168.100.134", + "key_filename": "/tmp/yardstick_key-a3b663c2", + "member-vnf-index": "4", + "name": "vnf0ds-k8syardstick-a3b663c2", + "private_ip": "192.168.100.134", + "service_ports": [ + { + "name": "ssh", + "node_port": 18581, + "port": 22, + "protocol": "TCP", + "target_port": 22 + }, + { + "name": "lua", + "node_port": 18469, + "port": 22022, + "protocol": "TCP", + "target_port": 22022 + } + ], + "ssh_port": 18581, + "user": "root", + "vnfd-id-ref": "vnf__1" + } + } + } + + PKTGEN_VALUES_PATH = "/tmp/pktgen_values.yaml" + + PKTGEN_VALUES = \ + "serviceAccount: cmk-serviceaccount\n" \ + "images:\n" \ + " vcmts_pktgen: vcmts-pktgen:v18.10\n" \ + "topology:\n" \ + " pktgen_replicas: 8\n" \ + " pktgen_pods:\n" \ + " - pktgen_id: 0\n" \ + " num_ports: 4\n" \ + " ports:\n" \ + " - port_0:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.0\n" \ + " - port_1:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.1\n" \ + " - port_2:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.2\n" \ + " - port_3:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.3\n" \ + " - port_4:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.4\n" \ + " - port_5:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.5\n" \ + " - port_6:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.6\n" \ + " - port_7:\n" \ + " traffic_type: 'imix2'\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " net_pktgen: 8a:02.7\n" + + def setUp(self): + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + self.vcmts_pktgen = tg_vcmts_pktgen.VcmtsPktgen(NAME, vnfd) + self.vcmts_pktgen._start_server = mock.Mock(return_value=0) + self.vcmts_pktgen.resource_helper = mock.MagicMock() + self.vcmts_pktgen.setup_helper = mock.MagicMock() + + def test___init__(self): + self.assertFalse(self.vcmts_pktgen.traffic_finished) + self.assertIsNotNone(self.vcmts_pktgen.setup_helper) + self.assertIsNotNone(self.vcmts_pktgen.resource_helper) + + def test_extract_pod_cfg(self): + pod_cfg = self.vcmts_pktgen.extract_pod_cfg(self.PKTGEN_POD_VALUES, "0") + self.assertIsNotNone(pod_cfg) + self.assertEqual(pod_cfg["pktgen_id"], "0") + pod_cfg = self.vcmts_pktgen.extract_pod_cfg(self.PKTGEN_POD_VALUES, "4") + self.assertIsNone(pod_cfg) + + @mock.patch.object(ctx_base.Context, 'get_context_from_server', + return_value='fake_context') + def test_instantiate_missing_pktgen_values_key(self, *args): + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options'].pop('pktgen_values', None) + with self.assertRaises(KeyError): + self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + @mock.patch.object(ctx_base.Context, 'get_context_from_server', + return_value='fake_context') + def test_instantiate_missing_pktgen_values_file(self, *args): + if os.path.isfile(self.PKTGEN_VALUES_PATH): + os.remove(self.PKTGEN_VALUES_PATH) + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options']['pktgen_values'] = self.PKTGEN_VALUES_PATH + with self.assertRaises(RuntimeError): + self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + @mock.patch.object(ctx_base.Context, 'get_context_from_server', + return_value='fake_context') + def test_instantiate_empty_pktgen_values_file(self, *args): + yaml_sample = open(self.PKTGEN_VALUES_PATH, 'w') + yaml_sample.write("") + yaml_sample.close() + + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options']['pktgen_values'] = self.PKTGEN_VALUES_PATH + with self.assertRaises(RuntimeError): + self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + if os.path.isfile(self.PKTGEN_VALUES_PATH): + os.remove(self.PKTGEN_VALUES_PATH) + + @mock.patch.object(ctx_base.Context, 'get_context_from_server', + return_value='fake_context') + def test_instantiate_invalid_pktgen_id(self, *args): + yaml_sample = open(self.PKTGEN_VALUES_PATH, 'w') + yaml_sample.write(self.PKTGEN_VALUES) + yaml_sample.close() + + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options'][NAME]['pktgen_id'] = 12 + with self.assertRaises(KeyError): + self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + if os.path.isfile(self.PKTGEN_VALUES_PATH): + os.remove(self.PKTGEN_VALUES_PATH) + + @mock.patch.object(ctx_base.Context, 'get_context_from_server', + return_value='fake_context') + def test_instantiate_all_valid(self, *args): + yaml_sample = open(self.PKTGEN_VALUES_PATH, 'w') + yaml_sample.write(self.PKTGEN_VALUES) + yaml_sample.close() + + self.vcmts_pktgen.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG) + self.assertIsNotNone(self.vcmts_pktgen.pod_cfg) + self.assertEqual(self.vcmts_pktgen.pod_cfg["pktgen_id"], "0") + + if os.path.isfile(self.PKTGEN_VALUES_PATH): + os.remove(self.PKTGEN_VALUES_PATH) + + def test_run_traffic_failed_connect(self): + self.vcmts_pktgen.pktgen_helper = mock.MagicMock() + self.vcmts_pktgen.pktgen_helper.connect.return_value = False + with self.assertRaises(exceptions.PktgenActionError): + self.vcmts_pktgen.run_traffic({}) + + def test_run_traffic_successful_connect(self): + self.vcmts_pktgen.pktgen_helper = mock.MagicMock() + self.vcmts_pktgen.pktgen_helper.connect.return_value = True + self.vcmts_pktgen.pktgen_rate = 8.0 + self.assertTrue(self.vcmts_pktgen.run_traffic({})) + self.vcmts_pktgen.pktgen_helper.connect.assert_called_once() + self.vcmts_pktgen.pktgen_helper.send_command.assert_called_with( + 'pktgen.start("all");') diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py new file mode 100755 index 000000000..11e3d6e17 --- /dev/null +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py @@ -0,0 +1,651 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import mock +import copy +import os + +from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh +from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper +from yardstick.network_services.vnf_generic.vnf import vcmts_vnf +from yardstick.common import exceptions + +from influxdb.resultset import ResultSet + +NAME = "vnf__0" + + +class TestInfluxDBHelper(unittest.TestCase): + + def test___init__(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + self.assertEqual(influxdb_helper._vcmts_influxdb_ip, "localhost") + self.assertEqual(influxdb_helper._vcmts_influxdb_port, 8086) + self.assertIsNotNone(influxdb_helper._last_upstream_rx) + self.assertIsNotNone(influxdb_helper._last_values_time) + + def test_start(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + influxdb_helper.start() + self.assertIsNotNone(influxdb_helper._read_client) + self.assertIsNotNone(influxdb_helper._write_client) + + def test__get_last_value_time(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'), + vcmts_vnf.InfluxDBHelper.INITIAL_VALUE) + + influxdb_helper._last_values_time['cpu_value'] = "RANDOM" + self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'), + "RANDOM") + + def test__set_last_value_time(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + influxdb_helper._set_last_value_time('cpu_value', '00:00') + self.assertEqual(influxdb_helper._last_values_time['cpu_value'], + "'00:00'") + + def test__query_measurement(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + influxdb_helper._read_client = mock.MagicMock() + + resulted_generator = mock.MagicMock() + resulted_generator.keys.return_value = [] + influxdb_helper._read_client.query.return_value = resulted_generator + query_result = influxdb_helper._query_measurement('cpu_value') + self.assertIsNone(query_result) + + resulted_generator = mock.MagicMock() + resulted_generator.keys.return_value = ["", ""] + resulted_generator.get_points.return_value = ResultSet({"":""}) + influxdb_helper._read_client.query.return_value = resulted_generator + query_result = influxdb_helper._query_measurement('cpu_value') + self.assertIsNotNone(query_result) + + def test__rw_measurment(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + influxdb_helper._query_measurement = mock.MagicMock() + influxdb_helper._query_measurement.return_value = None + influxdb_helper._rw_measurment('cpu_value', []) + self.assertEqual(len(influxdb_helper._last_values_time), 0) + + entry = { + "type":"type", + "host":"host", + "time":"time", + "id": "1", + "value": "1.0" + } + influxdb_helper._query_measurement.return_value = [entry] + influxdb_helper._write_client = mock.MagicMock() + influxdb_helper._rw_measurment('cpu_value', ["id", "value"]) + self.assertEqual(len(influxdb_helper._last_values_time), 1) + influxdb_helper._write_client.write_points.assert_called_once() + + def test_copy_kpi(self): + influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086) + influxdb_helper._rw_measurment = mock.MagicMock() + influxdb_helper.copy_kpi() + influxdb_helper._rw_measurment.assert_called() + + +class TestVcmtsdSetupEnvHelper(unittest.TestCase): + POD_CFG = { + "cm_crypto": "aes", + "cpu_socket_id": "0", + "ds_core_pool_index": "2", + "ds_core_type": "exclusive", + "net_ds": "1a:02.1", + "net_us": "1a:02.0", + "num_ofdm": "1", + "num_subs": "100", + "power_mgmt": "pm_on", + "qat": "qat_off", + "service_group_config": "", + "sg_id": "0", + "vcmtsd_image": "vcmts-d:perf" + } + + OPTIONS = { + "pktgen_values": "/tmp/pktgen_values.yaml", + "tg__0": { + "pktgen_id": 0 + }, + "vcmts_influxdb_ip": "10.80.5.150", + "vcmts_influxdb_port": 8086, + "vcmtsd_values": "/tmp/vcmtsd_values.yaml", + "vnf__0": { + "sg_id": 0, + "stream_dir": "us" + }, + "vnf__1": { + "sg_id": 0, + "stream_dir": "ds" + } + } + + def setUp(self): + vnfd_helper = VnfdHelper( + TestVcmtsVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + + self.setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper( + vnfd_helper, ssh_helper, scenario_helper) + + def _build_us_parameters(self): + return vcmts_vnf.VcmtsdSetupEnvHelper.BASE_PARAMETERS + " " \ + + " /opt/bin/cmk isolate --conf-dir=/etc/cmk" \ + + " --socket-id=" + str(self.POD_CFG['cpu_socket_id']) \ + + " --pool=shared" \ + + " /vcmts-config/run_upstream.sh " + self.POD_CFG['sg_id'] \ + + " " + self.POD_CFG['ds_core_type'] \ + + " " + str(self.POD_CFG['num_ofdm']) + "ofdm" \ + + " " + str(self.POD_CFG['num_subs']) + "cm" \ + + " " + self.POD_CFG['cm_crypto'] \ + + " " + self.POD_CFG['qat'] \ + + " " + self.POD_CFG['net_us'] \ + + " " + self.POD_CFG['power_mgmt'] + + def test_build_us_parameters(self): + constructed = self._build_us_parameters() + result = self.setup_helper.build_us_parameters(self.POD_CFG) + self.assertEqual(constructed, result) + + def _build_ds_parameters(self): + return vcmts_vnf.VcmtsdSetupEnvHelper.BASE_PARAMETERS + " " \ + + " /opt/bin/cmk isolate --conf-dir=/etc/cmk" \ + + " --socket-id=" + str(self.POD_CFG['cpu_socket_id']) \ + + " --pool=" + self.POD_CFG['ds_core_type'] \ + + " /vcmts-config/run_downstream.sh " + self.POD_CFG['sg_id'] \ + + " " + self.POD_CFG['ds_core_type'] \ + + " " + str(self.POD_CFG['ds_core_pool_index']) \ + + " " + str(self.POD_CFG['num_ofdm']) + "ofdm" \ + + " " + str(self.POD_CFG['num_subs']) + "cm" \ + + " " + self.POD_CFG['cm_crypto'] \ + + " " + self.POD_CFG['qat'] \ + + " " + self.POD_CFG['net_ds'] \ + + " " + self.POD_CFG['power_mgmt'] + + def test_build_ds_parameters(self): + constructed = self._build_ds_parameters() + result = self.setup_helper.build_ds_parameters(self.POD_CFG) + self.assertEqual(constructed, result) + + def test_build_cmd(self): + us_constructed = self._build_us_parameters() + us_result = self.setup_helper.build_cmd('us', self.POD_CFG) + self.assertEqual(us_constructed, us_result) + ds_constructed = self._build_ds_parameters() + ds_result = self.setup_helper.build_cmd('ds', self.POD_CFG) + self.assertEqual(ds_constructed, ds_result) + + def test_run_vcmtsd(self): + us_constructed = self._build_us_parameters() + + vnfd_helper = VnfdHelper( + TestVcmtsVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]) + ssh_helper = mock.MagicMock() + scenario_helper = mock.Mock() + scenario_helper.options = self.OPTIONS + + setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper( + vnfd_helper, ssh_helper, scenario_helper) + + setup_helper.run_vcmtsd('us', self.POD_CFG) + ssh_helper.send_command.assert_called_with(us_constructed) + + def test_setup_vnf_environment(self): + self.assertIsNone(self.setup_helper.setup_vnf_environment()) + +class TestVcmtsVNF(unittest.TestCase): + + VNFD = {'vnfd:vnfd-catalog': + {'vnfd': + [{ + "benchmark": { + "kpi": [ + "upstream/bits_per_second" + ] + }, + "connection-point": [ + { + "name": "xe0", + "type": "VPORT" + }, + { + "name": "xe1", + "type": "VPORT" + } + ], + "description": "vCMTS Upstream-Downstream Kubernetes", + "id": "VcmtsVNF", + "mgmt-interface": { + "ip": "192.168.100.35", + "key_filename": "/tmp/yardstick_key-81dcca91", + "user": "root", + "vdu-id": "vcmtsvnf-kubernetes" + }, + "name": "vcmtsvnf", + "short-name": "vcmtsvnf", + "vdu": [ + { + "description": "vCMTS Upstream-Downstream Kubernetes", + "external-interface": [], + "id": "vcmtsvnf-kubernetes", + "name": "vcmtsvnf-kubernetes" + } + ], + "vm-flavor": { + "memory-mb": "4096", + "vcpu-count": "4" + } + }] + } + } + + POD_CFG = [ + { + "cm_crypto": "aes", + "cpu_socket_id": "0", + "ds_core_pool_index": "2", + "ds_core_type": "exclusive", + "net_ds": "1a:02.1", + "net_us": "1a:02.0", + "num_ofdm": "1", + "num_subs": "100", + "power_mgmt": "pm_on", + "qat": "qat_off", + "service_group_config": "", + "sg_id": "0", + "vcmtsd_image": "vcmts-d:perf" + }, + ] + + SCENARIO_CFG = { + "nodes": { + "tg__0": "pktgen0-k8syardstick-afae18b2", + "vnf__0": "vnf0us-k8syardstick-afae18b2", + "vnf__1": "vnf0ds-k8syardstick-afae18b2" + }, + "options": { + "pktgen_values": "/tmp/pktgen_values.yaml", + "tg__0": { + "pktgen_id": 0 + }, + "vcmts_influxdb_ip": "10.80.5.150", + "vcmts_influxdb_port": 8086, + "vcmtsd_values": "/tmp/vcmtsd_values.yaml", + "vnf__0": { + "sg_id": 0, + "stream_dir": "us" + }, + "vnf__1": { + "sg_id": 0, + "stream_dir": "ds" + } + }, + "task_id": "afae18b2-9902-477f-8128-49afde7c3040", + "task_path": "samples/vnf_samples/nsut/cmts", + "tc": "tc_vcmts_k8s_pktgen", + "topology": "k8s_vcmts_topology.yaml", + "traffic_profile": "../../traffic_profiles/fixed.yaml", + "type": "NSPerf" + } + + CONTEXT_CFG = { + "networks": { + "flannel": { + "name": "flannel" + }, + "xe0": { + "name": "xe0" + }, + "xe1": { + "name": "xe1" + } + }, + "nodes": { + "tg__0": { + "VNF model": "../../vnf_descriptors/tg_vcmts_tpl.yaml", + "interfaces": { + "flannel": { + "local_ip": "192.168.24.110", + "local_mac": None, + "network_name": "flannel" + }, + "xe0": { + "local_ip": "192.168.24.110", + "local_mac": None, + "network_name": "xe0" + }, + "xe1": { + "local_ip": "192.168.24.110", + "local_mac": None, + "network_name": "xe1" + } + }, + "ip": "192.168.24.110", + "key_filename": "/tmp/yardstick_key-afae18b2", + "member-vnf-index": "1", + "name": "pktgen0-k8syardstick-afae18b2", + "private_ip": "192.168.24.110", + "service_ports": [ + { + "name": "ssh", + "node_port": 17153, + "port": 22, + "protocol": "TCP", + "target_port": 22 + }, + { + "name": "lua", + "node_port": 51250, + "port": 22022, + "protocol": "TCP", + "target_port": 22022 + } + ], + "ssh_port": 17153, + "user": "root", + "vnfd-id-ref": "tg__0" + }, + "vnf__0": { + "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml", + "interfaces": { + "flannel": { + "local_ip": "192.168.100.53", + "local_mac": None, + "network_name": "flannel" + }, + "xe0": { + "local_ip": "192.168.100.53", + "local_mac": None, + "network_name": "xe0" + }, + "xe1": { + "local_ip": "192.168.100.53", + "local_mac": None, + "network_name": "xe1" + } + }, + "ip": "192.168.100.53", + "key_filename": "/tmp/yardstick_key-afae18b2", + "member-vnf-index": "3", + "name": "vnf0us-k8syardstick-afae18b2", + "private_ip": "192.168.100.53", + "service_ports": [ + { + "name": "ssh", + "node_port": 34027, + "port": 22, + "protocol": "TCP", + "target_port": 22 + }, + { + "name": "lua", + "node_port": 32580, + "port": 22022, + "protocol": "TCP", + "target_port": 22022 + } + ], + "ssh_port": 34027, + "user": "root", + "vnfd-id-ref": "vnf__0" + }, + "vnf__1": { + "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml", + "interfaces": { + "flannel": { + "local_ip": "192.168.100.52", + "local_mac": None, + "network_name": "flannel" + }, + "xe0": { + "local_ip": "192.168.100.52", + "local_mac": None, + "network_name": "xe0" + }, + "xe1": { + "local_ip": "192.168.100.52", + "local_mac": None, + "network_name": "xe1" + } + }, + "ip": "192.168.100.52", + "key_filename": "/tmp/yardstick_key-afae18b2", + "member-vnf-index": "4", + "name": "vnf0ds-k8syardstick-afae18b2", + "private_ip": "192.168.100.52", + "service_ports": [ + { + "name": "ssh", + "node_port": 58661, + "port": 22, + "protocol": "TCP", + "target_port": 22 + }, + { + "name": "lua", + "node_port": 58233, + "port": 22022, + "protocol": "TCP", + "target_port": 22022 + } + ], + "ssh_port": 58661, + "user": "root", + "vnfd-id-ref": "vnf__1" + }, + } + } + + VCMTSD_VALUES_PATH = "/tmp/vcmtsd_values.yaml" + + VCMTSD_VALUES = \ + "serviceAccount: cmk-serviceaccount\n" \ + "topology:\n" \ + " vcmts_replicas: 16\n" \ + " vcmts_pods:\n" \ + " - service_group_config:\n" \ + " sg_id: 0\n" \ + " net_us: 18:02.0\n" \ + " net_ds: 18:02.1\n" \ + " num_ofdm: 4\n" \ + " num_subs: 300\n" \ + " cm_crypto: aes\n" \ + " qat: qat_off\n" \ + " power_mgmt: pm_on\n" \ + " cpu_socket_id: 0\n" \ + " ds_core_type: exclusive\n" \ + " ds_core_pool_index: 0\n" \ + " vcmtsd_image: vcmts-d:feat" + + VCMTSD_VALUES_INCOMPLETE = \ + "serviceAccount: cmk-serviceaccount\n" \ + "topology:\n" \ + " vcmts_replicas: 16" + + def setUp(self): + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + self.vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd) + + def test___init__(self, *args): + self.assertIsNotNone(self.vnf.setup_helper) + + def test_extract_pod_cfg(self): + pod_cfg = self.vnf.extract_pod_cfg(self.POD_CFG, "0") + self.assertIsNotNone(pod_cfg) + self.assertEqual(pod_cfg['sg_id'], '0') + pod_cfg = self.vnf.extract_pod_cfg(self.POD_CFG, "1") + self.assertIsNone(pod_cfg) + + def test_instantiate_missing_influxdb_info(self): + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options'].pop('vcmts_influxdb_ip', None) + with self.assertRaises(KeyError): + self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + def test_instantiate_missing_vcmtsd_values_file(self): + if os.path.isfile(self.VCMTSD_VALUES_PATH): + os.remove(self.VCMTSD_VALUES_PATH) + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options']['vcmtsd_values'] = self.VCMTSD_VALUES_PATH + with self.assertRaises(RuntimeError): + self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + def test_instantiate_empty_vcmtsd_values_file(self): + yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w') + yaml_sample.write("") + yaml_sample.close() + + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options']['vcmtsd_values'] = self.VCMTSD_VALUES_PATH + with self.assertRaises(RuntimeError): + self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + if os.path.isfile(self.VCMTSD_VALUES_PATH): + os.remove(self.VCMTSD_VALUES_PATH) + + def test_instantiate_missing_vcmtsd_values_key(self): + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options'].pop('vcmtsd_values', None) + with self.assertRaises(KeyError): + self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + def test_instantiate_invalid_vcmtsd_values(self): + yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w') + yaml_sample.write(self.VCMTSD_VALUES_INCOMPLETE) + yaml_sample.close() + + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + with self.assertRaises(KeyError): + self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + if os.path.isfile(self.VCMTSD_VALUES_PATH): + os.remove(self.VCMTSD_VALUES_PATH) + + def test_instantiate_invalid_sg_id(self): + yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w') + yaml_sample.write(self.VCMTSD_VALUES) + yaml_sample.close() + + err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG) + err_scenario_cfg['options'][NAME]['sg_id'] = 8 + with self.assertRaises(exceptions.IncorrectConfig): + self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG) + + if os.path.isfile(self.VCMTSD_VALUES_PATH): + os.remove(self.VCMTSD_VALUES_PATH) + + @mock.patch('yardstick.network_services.vnf_generic.vnf.vcmts_vnf.VnfSshHelper') + def test_instantiate_all_valid(self, ssh, *args): + mock_ssh(ssh) + + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd) + + yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w') + yaml_sample.write(self.VCMTSD_VALUES) + yaml_sample.close() + + vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG) + self.assertEqual(vnf.vcmts_influxdb_ip, "10.80.5.150") + self.assertEqual(vnf.vcmts_influxdb_port, 8086) + + if os.path.isfile(self.VCMTSD_VALUES_PATH): + os.remove(self.VCMTSD_VALUES_PATH) + + def test__update_collectd_options(self): + scenario_cfg = {'options': + {'collectd': + {'interval': 3, + 'plugins': + {'plugin3': {'param': 3}}}, + 'vnf__0': + {'collectd': + {'interval': 2, + 'plugins': + {'plugin3': {'param': 2}, + 'plugin2': {'param': 2}}}}}} + context_cfg = {'nodes': + {'vnf__0': + {'collectd': + {'interval': 1, + 'plugins': + {'plugin3': {'param': 1}, + 'plugin2': {'param': 1}, + 'plugin1': {'param': 1}}}}}} + expected = {'interval': 1, + 'plugins': + {'plugin3': {'param': 1}, + 'plugin2': {'param': 1}, + 'plugin1': {'param': 1}}} + + self.vnf._update_collectd_options(scenario_cfg, context_cfg) + self.assertEqual(self.vnf.setup_helper.collectd_options, expected) + + def test__update_options(self): + options1 = {'interval': 1, + 'param1': 'value1', + 'plugins': + {'plugin3': {'param': 3}, + 'plugin2': {'param': 1}, + 'plugin1': {'param': 1}}} + options2 = {'interval': 2, + 'param2': 'value2', + 'plugins': + {'plugin4': {'param': 4}, + 'plugin2': {'param': 2}, + 'plugin1': {'param': 2}}} + expected = {'interval': 1, + 'param1': 'value1', + 'param2': 'value2', + 'plugins': + {'plugin4': {'param': 4}, + 'plugin3': {'param': 3}, + 'plugin2': {'param': 1}, + 'plugin1': {'param': 1}}} + + vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] + vnf = vcmts_vnf.VcmtsVNF('vnf1', vnfd) + vnf._update_options(options2, options1) + self.assertEqual(options2, expected) + + def test_wait_for_instantiate(self): + self.assertIsNone(self.vnf.wait_for_instantiate()) + + def test_terminate(self): + self.assertIsNone(self.vnf.terminate()) + + def test_scale(self): + self.assertIsNone(self.vnf.scale()) + + def test_collect_kpi(self): + self.vnf.influxdb_helper = mock.MagicMock() + self.vnf.collect_kpi() + self.vnf.influxdb_helper.copy_kpi.assert_called_once() + + def test_start_collect(self): + self.vnf.vcmts_influxdb_ip = "localhost" + self.vnf.vcmts_influxdb_port = 8800 + + self.assertIsNone(self.vnf.start_collect()) + self.assertIsNotNone(self.vnf.influxdb_helper) + + def test_stop_collect(self): + self.assertIsNone(self.vnf.stop_collect()) diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py new file mode 100644 index 000000000..d86dab8ad --- /dev/null +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py @@ -0,0 +1,713 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# Licensed under the Apache License,Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing,software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import mock + +from yardstick.network_services.vnf_generic.vnf import vims_vnf +from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh + + +class TestVimsPcscfVnf(unittest.TestCase): + + VNFD_0 = { + "short-name": "SippVnf", + "vdu": [ + { + "id": "sippvnf-baremetal", + "routing_table": "", + "external-interface": [ + { + "virtual-interface": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vnf__0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "vnf__1": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "vnfd-connection-point-ref": "xe0", + "name": "xe0" + }, + { + "virtual-interface": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vnf__0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "vnf__1": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe1", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "vnfd-connection-point-ref": "xe1", + "name": "xe1" + } + ], + "name": "sippvnf-baremetal", + "description": "Sipp" + } + ], + "description": "ImsbenchSipp", + "mgmt-interface": { + "vdu-id": "sipp-baremetal", + "password": "r00t", + "user": "root", + "ip": "10.80.3.11" + }, + "benchmark": { + "kpi": [ + "packets_in", + "packets_fwd", + "packets_dropped" + ] + }, + "id": "SippVnf", + "name": "SippVnf" + } + + def setUp(self): + self.pcscf_vnf = vims_vnf.VimsPcscfVnf('vnf__0', self.VNFD_0) + + def test___init__(self): + self.assertEqual(self.pcscf_vnf.name, 'vnf__0') + self.assertIsInstance(self.pcscf_vnf.resource_helper, + vims_vnf.VimsResourceHelper) + self.assertIsNone(self.pcscf_vnf._vnf_process) + + def test_wait_for_instantiate(self): + self.assertIsNone(self.pcscf_vnf.wait_for_instantiate()) + + def test__run(self): + self.assertIsNone(self.pcscf_vnf._run()) + + def test_start_collect(self): + self.assertIsNone(self.pcscf_vnf.start_collect()) + + def test_collect_kpi(self): + self.assertIsNone(self.pcscf_vnf.collect_kpi()) + + +class TestVimsHssVnf(unittest.TestCase): + + VNFD_1 = { + "short-name": "SippVnf", + "vdu": [ + { + "id": "sippvnf-baremetal", + "routing_table": "", + "external-interface": [ + { + "virtual-interface": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vnf__0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "vnf__1": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "vnfd-connection-point-ref": "xe0", + "name": "xe0" + }, + { + "virtual-interface": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vnf__0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "vnf__1": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe1", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "vnfd-connection-point-ref": "xe1", + "name": "xe1" + } + ], + "name": "sippvnf-baremetal", + "description": "Sipp" + } + ], + "description": "ImsbenchSipp", + "mgmt-interface": { + "vdu-id": "sipp-baremetal", + "password": "r00t", + "user": "root", + "ip": "10.80.3.11" + }, + "benchmark": { + "kpi": [ + "packets_in", + "packets_fwd", + "packets_dropped" + ] + }, + "id": "SippVnf", + "name": "SippVnf" + } + + SCENARIO_CFG = { + "task_id": "86414e11-5ef5-4426-b175-71baaa00fbd7", + "tc": "tc_vims_baremetal_sipp", + "runner": { + "interval": 1, + "output_config": { + "DEFAULT": { + "debug": "False", + "dispatcher": [ + "influxdb" + ] + }, + "nsb": { + "debug": "False", + "trex_client_lib": "/opt/nsb_bin/trex_client/stl", + "bin_path": "/opt/nsb_bin", + "trex_path": "/opt/nsb_bin/trex/scripts", + "dispatcher": "influxdb" + }, + "dispatcher_influxdb": { + "username": "root", + "target": "http://10.80.3.11:8086", + "db_name": "yardstick", + "timeout": "5", + "debug": "False", + "password": "root", + "dispatcher": "influxdb" + }, + "dispatcher_http": { + "debug": "False", + "dispatcher": "influxdb", + "timeout": "5", + "target": "http://127.0.0.1:8000/results" + }, + "dispatcher_file": { + "debug": "False", + "backup_count": "0", + "max_bytes": "0", + "dispatcher": "influxdb", + "file_path": "/tmp/yardstick.out" + } + }, + "runner_id": 22610, + "duration": 60, + "type": "Vims" + }, + "nodes": { + "vnf__0": "pcscf.yardstick-86414e11", + "vnf__1": "hss.yardstick-86414e11", + "tg__0": "sipp.yardstick-86414e11" + }, + "topology": "vims-topology.yaml", + "type": "NSPerf", + "traffic_profile": "../../traffic_profiles/ipv4_throughput.yaml", + "task_path": "samples/vnf_samples/nsut/vims", + "options": { + "init_reg_max": 5000, + "end_user": 10000, + "reg_cps": 20, + "rereg_cps": 20, + "rereg_step": 10, + "wait_time": 5, + "start_user": 1, + "msgc_cps": 10, + "dereg_step": 10, + "call_cps": 10, + "reg_step": 10, + "init_reg_cps": 50, + "dereg_cps": 20, + "msgc_step": 5, + "call_step": 5, + "hold_time": 15, + "port": 5060, + "run_mode": "nortp" + } + } + + CONTEXT_CFG = { + "nodes": { + "tg__0": { + "ip": "10.80.3.11", + "interfaces": { + "xe0": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vnf__0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "vnf__1": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "xe1": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vnf__0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "vnf__1": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe1", + "local_mac": "90:e2:ba:7c:30:e8" + } + }, + "user": "root", + "password": "r00t", + "VNF model": "../../vnf_descriptors/tg_sipp_vnfd.yaml", + "name": "sipp.yardstick-86414e11", + "vnfd-id-ref": "tg__0", + "member-vnf-index": "1", + "role": "TrafficGen", + "ctx_type": "Node" + }, + "vnf__0": { + "ip": "10.80.3.7", + "interfaces": { + "xe0": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "tg__0": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe1", + "local_mac": "90:e2:ba:7c:30:e8" + } + }, + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + } + }, + "user": "root", + "password": "r00t", + "VNF model": "../../vnf_descriptors/vims_pcscf_vnfd.yaml", + "name": "pcscf.yardstick-86414e11", + "vnfd-id-ref": "vnf__0", + "member-vnf-index": "2", + "role": "VirtualNetworkFunction", + "ctx_type": "Node" + }, + "vnf__1": { + "ip": "10.80.3.7", + "interfaces": { + "xe0": { + "vld_id": "ims_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "tg__0": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "peer_intf": { + "vld_id": "data_network", + "peer_ifname": "xe1", + "dst_mac": "90:e2:ba:7c:30:e8", + "network": {}, + "local_ip": "10.80.3.7", + "peer_intf": { + "vld_id": "ims_network", + "peer_ifname": "xe0", + "dst_mac": "90:e2:ba:7c:41:e8", + "network": {}, + "local_ip": "10.80.3.11", + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:30:e8" + }, + "node_name": "vnf__0", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:a8" + }, + "node_name": "tg__0", + "netmask": "255.255.255.0", + "peer_name": "vnf__1", + "dst_ip": "10.80.3.7", + "ifname": "xe1", + "local_mac": "90:e2:ba:7c:30:e8" + } + }, + "node_name": "vnf__1", + "netmask": "255.255.255.0", + "peer_name": "tg__0", + "dst_ip": "10.80.3.11", + "ifname": "xe0", + "local_mac": "90:e2:ba:7c:41:e8" + } + }, + "user": "root", + "password": "r00t", + "VNF model": "../../vnf_descriptors/vims_hss_vnfd.yaml", + "name": "hss.yardstick-86414e11", + "vnfd-id-ref": "vnf__1", + "member-vnf-index": "3", + "role": "VirtualNetworkFunction", + "ctx_type": "Node" + } + }, + "networks": {} + } + + def setUp(self): + self.hss_vnf = vims_vnf.VimsHssVnf('vnf__1', self.VNFD_1) + + def test___init__(self): + self.assertIsInstance(self.hss_vnf.resource_helper, + vims_vnf.VimsResourceHelper) + self.assertIsNone(self.hss_vnf._vnf_process) + + @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper") + def test_instantiate(self, ssh): + mock_ssh(ssh) + hss_vnf = vims_vnf.VimsHssVnf('vnf__1', self.VNFD_1) + self.assertIsNone(hss_vnf.instantiate(self.SCENARIO_CFG, + self.CONTEXT_CFG)) + + def test_wait_for_instantiate(self): + self.assertIsNone(self.hss_vnf.wait_for_instantiate()) + + def test_start_collect(self): + self.assertIsNone(self.hss_vnf.start_collect()) + + def test_collect_kpi(self): + self.assertIsNone(self.hss_vnf.collect_kpi()) diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py index 597844c72..c3066d7fe 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py @@ -11,13 +11,199 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import ipaddress import unittest import mock +from yardstick.common import exceptions +from yardstick.network_services.helpers import cpu +from yardstick.network_services.vnf_generic.vnf import vpp_helpers from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper from yardstick.network_services.vnf_generic.vnf.vpp_helpers import \ - VppSetupEnvHelper + VppSetupEnvHelper, VppConfigGenerator, VatTerminal + + +class TestVppConfigGenerator(unittest.TestCase): + + def test_add_config_item(self): + test_item = {} + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_config_item(test_item, '/tmp/vpe.log', + ['unix', 'log']) + self.assertEqual({'unix': {'log': '/tmp/vpe.log'}}, test_item) + + def test_add_config_item_str(self): + test_item = {'unix': ''} + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_config_item(test_item, '/tmp/vpe.log', + ['unix', 'log']) + self.assertEqual({'unix': {'log': '/tmp/vpe.log'}}, test_item) + + def test_add_unix_log(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_unix_log() + self.assertEqual('unix\n{\n log /tmp/vpe.log\n}\n', + vpp_config_generator.dump_config()) + + def test_add_unix_cli_listen(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_unix_cli_listen() + self.assertEqual('unix\n{\n cli-listen /run/vpp/cli.sock\n}\n', + vpp_config_generator.dump_config()) + + def test_add_unix_nodaemon(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_unix_nodaemon() + self.assertEqual('unix\n{\n nodaemon \n}\n', + vpp_config_generator.dump_config()) + + def test_add_unix_coredump(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_unix_coredump() + self.assertEqual('unix\n{\n full-coredump \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_dev(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_dev('0000:00:00.0') + self.assertEqual('dpdk\n{\n dev 0000:00:00.0 \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_cryptodev(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_cryptodev(2, '0000:00:00.0') + self.assertEqual( + 'dpdk\n{\n dev 0000:00:01.0 \n dev 0000:00:01.1 \n uio-driver igb_uio\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_sw_cryptodev(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_sw_cryptodev('aesni_gcm', 0, 2) + self.assertEqual( + 'dpdk\n{\n vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_dev_default_rxq(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_dev_default_rxq(1) + self.assertEqual( + 'dpdk\n{\n dev default\n {\n num-rx-queues 1\n }\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_dev_default_rxd(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_dev_default_rxd(2048) + self.assertEqual( + 'dpdk\n{\n dev default\n {\n num-rx-desc 2048\n }\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_dev_default_txd(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_dev_default_txd(2048) + self.assertEqual( + 'dpdk\n{\n dev default\n {\n num-tx-desc 2048\n }\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_log_level(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_log_level('debug') + self.assertEqual('dpdk\n{\n log-level debug\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_socketmem(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_socketmem('1024,1024') + self.assertEqual('dpdk\n{\n socket-mem 1024,1024\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_num_mbufs(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_num_mbufs(32768) + self.assertEqual('dpdk\n{\n num-mbufs 32768\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_uio_driver(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_uio_driver('igb_uio') + self.assertEqual('dpdk\n{\n uio-driver igb_uio\n}\n', + vpp_config_generator.dump_config()) + + def test_add_cpu_main_core(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_cpu_main_core('1,2') + self.assertEqual('cpu\n{\n main-core 1,2\n}\n', + vpp_config_generator.dump_config()) + + def test_add_cpu_corelist_workers(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_cpu_corelist_workers('1,2') + self.assertEqual('cpu\n{\n corelist-workers 1,2\n}\n', + vpp_config_generator.dump_config()) + + def test_add_heapsize(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_heapsize('4G') + self.assertEqual('heapsize 4G\n', vpp_config_generator.dump_config()) + + def test_add_ip6_hash_buckets(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_ip6_hash_buckets(2000000) + self.assertEqual('ip6\n{\n hash-buckets 2000000\n}\n', + vpp_config_generator.dump_config()) + + def test_add_ip6_heap_size(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_ip6_heap_size('4G') + self.assertEqual('ip6\n{\n heap-size 4G\n}\n', + vpp_config_generator.dump_config()) + + def test_add_ip_heap_size(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_ip_heap_size('4G') + self.assertEqual('ip\n{\n heap-size 4G\n}\n', + vpp_config_generator.dump_config()) + + def test_add_statseg_size(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_statseg_size('4G') + self.assertEqual('statseg\n{\n size 4G\n}\n', + vpp_config_generator.dump_config()) + + def test_add_plugin(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_plugin('enable', ['dpdk_plugin.so']) + self.assertEqual( + 'plugins\n{\n plugin [\'dpdk_plugin.so\']\n {\n enable \n }\n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_no_multi_seg(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_no_multi_seg() + self.assertEqual('dpdk\n{\n no-multi-seg \n}\n', + vpp_config_generator.dump_config()) + + def test_add_dpdk_no_tx_checksum_offload(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_dpdk_no_tx_checksum_offload() + self.assertEqual('dpdk\n{\n no-tx-checksum-offload \n}\n', + vpp_config_generator.dump_config()) + + def test_dump_config(self): + vpp_config_generator = VppConfigGenerator() + vpp_config_generator.add_unix_log() + self.assertEqual('unix\n{\n log /tmp/vpe.log\n}\n', + vpp_config_generator.dump_config()) + + def test_pci_dev_check(self): + self.assertTrue(VppConfigGenerator.pci_dev_check('0000:00:00.0')) + + def test_pci_dev_check_error(self): + with self.assertRaises(ValueError) as raised: + VppConfigGenerator.pci_dev_check('0000:00:0.0') + self.assertIn( + 'PCI address 0000:00:0.0 is not in valid format xxxx:xx:xx.x', + str(raised.exception)) class TestVppSetupEnvHelper(unittest.TestCase): @@ -130,6 +316,224 @@ class TestVppSetupEnvHelper(unittest.TestCase): ] } + VNFD_1 = { + "benchmark": { + "kpi": [ + "packets_in", + "packets_fwd", + "packets_dropped" + ] + }, + "connection-point": [ + { + "name": "xe0", + "type": "VPORT" + }, + { + "name": "xe1", + "type": "VPORT" + } + ], + "description": "VPP IPsec", + "id": "VipsecApproxVnf", + "mgmt-interface": { + "ip": "10.10.10.101", + "password": "r00t", + "user": "root", + "vdu-id": "ipsecvnf-baremetal" + }, + "name": "IpsecVnf", + "short-name": "IpsecVnf", + "vdu": [ + { + "description": "VPP Ipsec", + "external-interface": [ + { + "name": "xe0", + "virtual-interface": { + "driver": "igb_uio", + "dst_ip": "192.168.100.1", + "dst_mac": "90:e2:ba:7c:30:e8", + "ifname": "xe0", + "local_ip": "192.168.100.2", + "local_mac": "90:e2:ba:7c:41:a8", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "vnf__0", + "peer_ifname": "xe0", + "peer_intf": { + "dpdk_port_num": 0, + "driver": "igb_uio", + "dst_ip": "192.168.100.2", + "dst_mac": "90:e2:ba:7c:41:a8", + "ifname": "xe0", + "local_ip": "192.168.100.1", + "local_mac": "90:e2:ba:7c:30:e8", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "tg__0", + "peer_ifname": "xe0", + "peer_name": "vnf__0", + "vld_id": "uplink_0", + "vpci": "0000:81:00.0" + }, + "peer_name": "tg__0", + "vld_id": "uplink_0", + "vpci": "0000:ff:06.0" + }, + "vnfd-connection-point-ref": "xe0" + }, + { + "name": "xe1", + "virtual-interface": { + "driver": "igb_uio", + "dst_ip": "1.1.1.2", + "dst_mac": "0a:b1:ec:fd:a2:66", + "ifname": "xe1", + "local_ip": "1.1.1.1", + "local_mac": "4e:90:85:d3:c5:13", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "vnf__0", + "peer_ifname": "xe1", + "peer_intf": { + "driver": "igb_uio", + "dst_ip": "1.1.1.1", + "dst_mac": "4e:90:85:d3:c5:13", + "ifname": "xe1", + "local_ip": "1.1.1.2", + "local_mac": "0a:b1:ec:fd:a2:66", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "vnf__1", + "peer_ifname": "xe1", + "peer_name": "vnf__0", + "vld_id": "ciphertext", + "vpci": "0000:00:07.0" + }, + "peer_name": "vnf__1", + "vld_id": "ciphertext", + "vpci": "0000:ff:07.0" + }, + "vnfd-connection-point-ref": "xe1" + } + ], + "id": "ipsecvnf-baremetal", + "name": "ipsecvnf-baremetal", + "routing_table": [] + } + ] + } + + VNFD_2 = { + "benchmark": { + "kpi": [ + "packets_in", + "packets_fwd", + "packets_dropped" + ] + }, + "connection-point": [ + { + "name": "xe0", + "type": "VPORT" + }, + { + "name": "xe1", + "type": "VPORT" + } + ], + "description": "VPP IPsec", + "id": "VipsecApproxVnf", + "mgmt-interface": { + "ip": "10.10.10.101", + "password": "r00t", + "user": "root", + "vdu-id": "ipsecvnf-baremetal" + }, + "name": "IpsecVnf", + "short-name": "IpsecVnf", + "vdu": [ + { + "description": "VPP Ipsec", + "external-interface": [ + { + "name": "xe0", + "virtual-interface": { + "driver": "igb_uio", + "dst_ip": "192.168.100.1", + "dst_mac": "90:e2:ba:7c:30:e8", + "ifname": "xe0", + "local_ip": "192.168.100.2", + "local_mac": "90:e2:ba:7c:41:a8", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "vnf__0", + "peer_ifname": "xe0", + "peer_intf": { + "dpdk_port_num": 0, + "driver": "igb_uio", + "dst_ip": "192.168.100.2", + "dst_mac": "90:e2:ba:7c:41:a8", + "ifname": "xe0", + "local_ip": "192.168.100.1", + "local_mac": "90:e2:ba:7c:30:e8", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "tg__0", + "peer_ifname": "xe0", + "peer_name": "vnf__0", + "vld_id": "uplink_0", + "vpci": "0000:81:00.0" + }, + "peer_name": "tg__0", + "vld_id": "uplink_0", + "vpci": "0000:ff:06.0" + }, + "vnfd-connection-point-ref": "xe0" + }, + { + "name": "xe1", + "virtual-interface": { + "driver": "igb_uio", + "dst_ip": "1.1.1.2", + "dst_mac": "0a:b1:ec:fd:a2:66", + "ifname": "xe1", + "local_ip": "1.1.1.1", + "local_mac": "4e:90:85:d3:c5:13", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "vnf__0", + "peer_ifname": "xe1", + "peer_intf": { + "driver": "igb_uio", + "dst_ip": "1.1.1.1", + "dst_mac": "4e:90:85:d3:c5:13", + "ifname": "xe1", + "local_ip": "1.1.1.2", + "local_mac": "0a:b1:ec:fd:a2:66", + "netmask": "255.255.255.0", + "network": {}, + "node_name": "vnf__1", + "peer_ifname": "xe1", + "peer_name": "vnf__0", + "vld_id": "ciphertext", + "vpci": "0000:00:07.0" + }, + "peer_name": "vnf__1", + "vld_id": "ciphertext", + "vpci": "0000:ff:07.0" + }, + "vnfd-connection-point-ref": "xe1" + } + ], + "id": "ipsecvnf-baremetal", + "name": "ipsecvnf-baremetal", + "routing_table": [] + } + ] + } + VNFD = { 'vnfd:vnfd-catalog': { 'vnfd': [ @@ -216,6 +620,105 @@ class TestVppSetupEnvHelper(unittest.TestCase): } ] + VPP_INTERFACES_DUMP_MAC_ERR = [ + { + "sw_if_index": 0, + "sup_sw_if_index": 0, + "l2_address_length": 0, + "l2_address": [0, 0, 0, 0, 0, 0, 0, 0], + "interface_name": "local0", + "admin_up_down": 0, + "link_up_down": 0, + "link_duplex": 0, + "link_speed": 0, + "mtu": 0, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + }, + { + "sw_if_index": 1, + "sup_sw_if_index": 1, + "l2_address_length": 6, + "l2_address": [144, 226, 186, 124, 65, 169, 0, 0], + "interface_name": "TenGigabitEthernetff/6/0", + "admin_up_down": 0, + "link_up_down": 0, + "link_duplex": 2, + "link_speed": 32, + "mtu": 9202, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + }, + { + "sw_if_index": 2, + "sup_sw_if_index": 2, + "l2_address_length": 6, + "l2_address": [78, 144, 133, 211, 197, 20, 0, 0], + "interface_name": "VirtualFunctionEthernetff/7/0", + "admin_up_down": 0, + "link_up_down": 0, + "link_duplex": 2, + "link_speed": 32, + "mtu": 9206, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + } + ] + + CPU_LAYOUT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 1, 0]]} + CPU_SMT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 1, 0], + [2, 1, 0, 0, 0, 2, 2, 1], + [3, 1, 0, 0, 0, 3, 3, 1], + [4, 2, 0, 0, 0, 4, 4, 2], + [5, 2, 0, 0, 0, 5, 5, 2], + [6, 3, 0, 0, 0, 6, 6, 3], + [7, 3, 0, 0, 0, 7, 7, 3], + [8, 4, 0, 0, 0, 8, 8, 4], + [9, 5, 0, 1, 0, 0, 0, 0], + [10, 6, 0, 1, 0, 1, 1, 0], + [11, 6, 0, 1, 0, 2, 2, 1], + [12, 7, 0, 1, 0, 3, 3, 1], + [13, 7, 0, 1, 0, 4, 4, 2], + [14, 8, 0, 1, 0, 5, 5, 2], + [15, 8, 0, 1, 0, 6, 6, 3], + [16, 9, 0, 1, 0, 7, 7, 3], + [17, 9, 0, 1, 0, 8, 8, 4]]} + def test_kill_vnf(self): vnfd_helper = VnfdHelper(self.VNFD_0) ssh_helper = mock.Mock() @@ -333,3 +836,772 @@ class TestVppSetupEnvHelper(unittest.TestCase): self.assertIsNone(vpp_setup_env_helper.get_value_by_interface_key( 'xe2', 'vpp-err')) + + def test_vpp_create_ipsec_tunnels(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + self.assertIsNone( + vpp_setup_env_helper.vpp_create_ipsec_tunnels('10.10.10.2', + '10.10.10.1', 'xe0', + 1, 1, mock.Mock(), + 'crypto_key', + mock.Mock(), + 'integ_key', + '20.20.20.0')) + self.assertGreaterEqual(ssh_helper.execute.call_count, 2) + + def test_vpp_create_ipsec_1000_tunnels(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + self.assertIsNone( + vpp_setup_env_helper.vpp_create_ipsec_tunnels('10.10.10.2', + '10.10.10.1', 'xe0', + 1000, 128000, + mock.Mock(), + 'crypto_key', + mock.Mock(), + 'integ_key', + '20.20.20.0')) + self.assertGreaterEqual(ssh_helper.execute.call_count, 2) + + def test_apply_config(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + self.assertIsNone(vpp_setup_env_helper.apply_config(mock.Mock())) + self.assertGreaterEqual(ssh_helper.execute.call_count, 2) + + def test_apply_config_error(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 1, '', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + with self.assertRaises(RuntimeError) as raised: + vpp_setup_env_helper.apply_config(mock.Mock()) + + self.assertIn('Writing config file failed', str(raised.exception)) + + def test_vpp_route_add(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertIsNone( + vpp_setup_env_helper.vpp_route_add('xe0', '10.10.10.1', 24)) + + def test_vpp_route_add_without_index(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertIsNone( + vpp_setup_env_helper.vpp_route_add('xe0', '10.10.10.1', 24, + interface='xe0', + use_sw_index=False)) + + def test_add_arp_on_dut(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertEqual('', vpp_setup_env_helper.add_arp_on_dut('xe0', + '10.10.10.1', + '00:00:00:00:00:00')) + + def test_set_ip(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertEqual('', + vpp_setup_env_helper.set_ip('xe0', '10.10.10.1', + 24)) + + def test_set_interface_state(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertEqual('', + vpp_setup_env_helper.set_interface_state('xe0', + 'up')) + + def test_set_interface_state_error(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + with self.assertRaises(ValueError) as raised: + vpp_setup_env_helper.set_interface_state('xe0', 'error') + self.assertIn('Unexpected interface state: error', + str(raised.exception)) + + def test_set_interface_down_state(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertEqual('', + vpp_setup_env_helper.set_interface_state('xe0', + 'down')) + + def test_vpp_set_interface_mtu(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = '' + self.assertIsNone( + vpp_setup_env_helper.vpp_set_interface_mtu('xe0', 9200)) + + def test_vpp_interfaces_ready_wait(self): + json_output = [self.VPP_INTERFACES_DUMP] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + self.assertIsNone(vpp_setup_env_helper.vpp_interfaces_ready_wait()) + + def test_vpp_interfaces_ready_wait_timeout(self): + json_output = [[ + { + "sw_if_index": 0, + "sup_sw_if_index": 0, + "l2_address_length": 0, + "l2_address": [0, 0, 0, 0, 0, 0, 0, 0], + "interface_name": "xe0", + "admin_up_down": 1, + "link_up_down": 0, + "link_duplex": 0, + "link_speed": 0, + "mtu": 0, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + }]] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + with self.assertRaises(RuntimeError) as raised: + vpp_setup_env_helper.vpp_interfaces_ready_wait(5) + self.assertIn('timeout, not up [\'xe0\']', str(raised.exception)) + + def test_vpp_get_interface_data(self): + json_output = [self.VPP_INTERFACES_DUMP] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + self.assertEqual(json_output[0], + vpp_setup_env_helper.vpp_get_interface_data()) + + def test_vpp_get_interface_data_ifname(self): + json_output = [self.VPP_INTERFACES_DUMP] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + self.assertEqual(json_output[0][2], + vpp_setup_env_helper.vpp_get_interface_data( + 'VirtualFunctionEthernetff/7/0')) + + def test_vpp_get_interface_data_ifname_error(self): + json_output = [self.VPP_INTERFACES_DUMP] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + self.assertEqual({}, vpp_setup_env_helper.vpp_get_interface_data( + 'error')) + + def test_vpp_get_interface_data_ifindex(self): + json_output = [self.VPP_INTERFACES_DUMP] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + self.assertEqual(json_output[0][1], + vpp_setup_env_helper.vpp_get_interface_data(1)) + + def test_vpp_get_interface_data_error(self): + json_output = [self.VPP_INTERFACES_DUMP] + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + + with mock.patch.object(vpp_helpers.VatTerminal, + 'vat_terminal_exec_cmd_from_template') as \ + mock_vat_terminal_exec_cmd_from_template: + mock_vat_terminal_exec_cmd_from_template.return_value = json_output + with self.assertRaises(TypeError) as raised: + vpp_setup_env_helper.vpp_get_interface_data(1.0) + self.assertEqual('', str(raised.exception)) + + def test_update_vpp_interface_data(self): + output = '{}\n{}'.format(self.VPP_INTERFACES_DUMP, + 'dump_interface_table:6019: JSON output ' \ + 'supported only for VPE API calls and dump_stats_table\n' \ + '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \ + 'dump_interface_table error: Misc') + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, output.replace("\'", "\""), '' + ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/vpp/templates' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + self.assertIsNone(vpp_setup_env_helper.update_vpp_interface_data()) + self.assertGreaterEqual(ssh_helper.execute.call_count, 1) + self.assertEqual('TenGigabitEthernetff/6/0', + vpp_setup_env_helper.get_value_by_interface_key( + 'xe0', 'vpp_name')) + self.assertEqual(1, vpp_setup_env_helper.get_value_by_interface_key( + 'xe0', 'vpp_sw_index')) + self.assertEqual('VirtualFunctionEthernetff/7/0', + vpp_setup_env_helper.get_value_by_interface_key( + 'xe1', 'vpp_name')) + self.assertEqual(2, vpp_setup_env_helper.get_value_by_interface_key( + 'xe1', 'vpp_sw_index')) + + def test_update_vpp_interface_data_error(self): + output = '{}\n{}'.format(self.VPP_INTERFACES_DUMP_MAC_ERR, + 'dump_interface_table:6019: JSON output ' \ + 'supported only for VPE API calls and dump_stats_table\n' \ + '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \ + 'dump_interface_table error: Misc') + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, output.replace("\'", "\""), '' + ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/vpp/templates' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + self.assertIsNone(vpp_setup_env_helper.update_vpp_interface_data()) + self.assertGreaterEqual(ssh_helper.execute.call_count, 1) + + def test_iface_update_numa(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '0', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + self.assertIsNone(vpp_setup_env_helper.iface_update_numa()) + self.assertGreaterEqual(ssh_helper.execute.call_count, 2) + self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key( + 'xe0', 'numa_node')) + self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key( + 'xe1', 'numa_node')) + + def test_iface_update_numa_error(self): + vnfd_helper = VnfdHelper(self.VNFD_1) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '-1', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout: + mock_get_cpu_layout.return_value = self.CPU_LAYOUT + sys_cores = cpu.CpuSysCores(ssh_helper) + vpp_setup_env_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + self.assertIsNone(vpp_setup_env_helper.iface_update_numa()) + self.assertGreaterEqual(ssh_helper.execute.call_count, 2) + self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key( + 'xe0', 'numa_node')) + self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key( + 'xe1', 'numa_node')) + + def test_iface_update_without_numa(self): + vnfd_helper = VnfdHelper(self.VNFD_2) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, '-1', '' + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \ + mock_get_cpu_layout: + mock_get_cpu_layout.return_value = self.CPU_SMT + sys_cores = cpu.CpuSysCores(ssh_helper) + vpp_setup_env_helper._update_vnfd_helper( + sys_cores.get_cpu_layout()) + self.assertIsNone(vpp_setup_env_helper.iface_update_numa()) + self.assertGreaterEqual(ssh_helper.execute.call_count, 2) + self.assertIsNone(vpp_setup_env_helper.get_value_by_interface_key( + 'xe0', 'numa_node')) + self.assertIsNone(vpp_setup_env_helper.get_value_by_interface_key( + 'xe1', 'numa_node')) + + def test_execute_script(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + vpp_setup_env_helper.execute_script('dump_interfaces.vat', True, True) + self.assertGreaterEqual(ssh_helper.put_file.call_count, 1) + self.assertGreaterEqual(ssh_helper.execute.call_count, 1) + + def test_execute_script_error(self): + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.side_effect = Exception + + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + with self.assertRaises(Exception) as raised: + vpp_setup_env_helper.execute_script('dump_interfaces.vat', True, + True) + self.assertIn( + 'VAT script execution failed: vpp_api_test json in dump_interfaces.vat script', + str(raised.exception)) + self.assertGreaterEqual(ssh_helper.put_file.call_count, 1) + + def test_execute_script_json_out(self): + json_output = [ + { + "sw_if_index": 0, + "sup_sw_if_index": 0 + }, + { + "l2_address_length": 6, + "l2_address": [144, 226, 186, 124, 65, 168, 0, 0] + }, + { + "interface_name": "VirtualFunctionEthernetff/7/0", + "admin_up_down": 0 + } + ] + output = '{}\n{}'.format(json_output, + 'dump_interface_table:6019: JSON output ' \ + 'supported only for VPE API calls and dump_stats_table\n' \ + '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \ + 'dump_interface_table error: Misc') + vnfd_helper = VnfdHelper(self.VNFD_0) + ssh_helper = mock.Mock() + ssh_helper.execute.return_value = 0, output, '' + ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/vpp/templates' + scenario_helper = mock.Mock() + vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper, + scenario_helper) + self.assertEqual(str(json_output), + vpp_setup_env_helper.execute_script_json_out( + 'dump_interfaces.vat')) + + def test_self_cleanup_vat_json_output(self): + json_output = [ + { + "sw_if_index": 0, + "sup_sw_if_index": 0 + }, + { + "l2_address_length": 6, + "l2_address": [144, 226, 186, 124, 65, 168, 0, 0] + }, + { + "interface_name": "VirtualFunctionEthernetff/7/0", + "admin_up_down": 0 + } + ] + + output = '{}\n{}'.format(json_output, + 'dump_interface_table:6019: JSON output ' \ + 'supported only for VPE API calls and dump_stats_table\n' \ + '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \ + 'dump_interface_table error: Misc') + self.assertEqual(str(json_output), + VppSetupEnvHelper.cleanup_vat_json_output(output, + '/opt/nsb_bin/vpp/templates/dump_interfaces.vat')) + + def test__convert_mac_to_number_list(self): + self.assertEqual([144, 226, 186, 124, 65, 168], + VppSetupEnvHelper._convert_mac_to_number_list( + '90:e2:ba:7c:41:a8')) + + def test_get_vpp_interface_by_mac(self): + mac_address = '90:e2:ba:7c:41:a8' + self.assertEqual({'admin_up_down': 0, + 'interface_name': 'TenGigabitEthernetff/6/0', + 'l2_address': [144, 226, 186, 124, 65, 168, 0, 0], + 'l2_address_length': 6, + 'link_duplex': 2, + 'link_speed': 32, + 'link_up_down': 0, + 'mtu': 9202, + 'sub_default': 0, + 'sub_dot1ad': 0, + 'sub_exact_match': 0, + 'sub_id': 0, + 'sub_inner_vlan_id': 0, + 'sub_inner_vlan_id_any': 0, + 'sub_number_of_tags': 0, + 'sub_outer_vlan_id': 0, + 'sub_outer_vlan_id_any': 0, + 'sup_sw_if_index': 1, + 'sw_if_index': 1, + 'vtr_op': 0, + 'vtr_push_dot1q': 0, + 'vtr_tag1': 0, + 'vtr_tag2': 0}, + VppSetupEnvHelper.get_vpp_interface_by_mac( + self.VPP_INTERFACES_DUMP, mac_address)) + + def test_get_vpp_interface_by_mac_error(self): + mac_address = '90:e2:ba:7c:41:a9' + with self.assertRaises(ValueError) as raised: + VppSetupEnvHelper.get_vpp_interface_by_mac( + [{ + "sw_if_index": 1, + "sup_sw_if_index": 1, + "l2_address_length": 7, + "l2_address": [144, 226, 186, 124, 65, 169, 0, 0], + "interface_name": "TenGigabitEthernetff/6/0", + "admin_up_down": 0, + "link_up_down": 0, + "link_duplex": 2, + "link_speed": 32, + "mtu": 9202, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + }], mac_address) + + self.assertIn('l2_address_length value is not 6.', + str(raised.exception)) + + def test_get_vpp_interface_by_mac_l2_error(self): + mac_address = '90:e2:ba:7c:41:a7' + with self.assertRaises(KeyError) as raised: + VppSetupEnvHelper.get_vpp_interface_by_mac( + [{ + "sw_if_index": 1, + "sup_sw_if_index": 1, + "l2_address_length": 6, + "l2_address_err": [144, 226, 186, 124, 65, 167, 0, 0], + "interface_name": "TenGigabitEthernetff/6/0", + "admin_up_down": 0, + "link_up_down": 0, + "link_duplex": 2, + "link_speed": 32, + "mtu": 9202, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + }], mac_address) + + self.assertIn( + 'key l2_address not found in interface dict.Probably input list ' \ + 'is not parsed from correct VAT json output.', + str(raised.exception)) + + def test_get_vpp_interface_by_mac_l2_length_error(self): + mac_address = '90:e2:ba:7c:41:a6' + with self.assertRaises(KeyError) as raised: + VppSetupEnvHelper.get_vpp_interface_by_mac( + [{ + "sw_if_index": 1, + "sup_sw_if_index": 1, + "l2_address_length_err": 6, + "l2_address": [144, 226, 186, 124, 65, 166, 0, 0], + "interface_name": "TenGigabitEthernetff/6/0", + "admin_up_down": 0, + "link_up_down": 0, + "link_duplex": 2, + "link_speed": 32, + "mtu": 9202, + "sub_id": 0, + "sub_dot1ad": 0, + "sub_number_of_tags": 0, + "sub_outer_vlan_id": 0, + "sub_inner_vlan_id": 0, + "sub_exact_match": 0, + "sub_default": 0, + "sub_outer_vlan_id_any": 0, + "sub_inner_vlan_id_any": 0, + "vtr_op": 0, + "vtr_push_dot1q": 0, + "vtr_tag1": 0, + "vtr_tag2": 0 + }], mac_address) + + self.assertIn( + 'key l2_address_length not found in interface dict. Probably ' \ + 'input list is not parsed from correct VAT json output.', + str(raised.exception)) + + def test_get_prefix_length(self): + start_ip = '10.10.10.0' + end_ip = '10.10.10.127' + ips = [ipaddress.ip_address(ip) for ip in + [str(ipaddress.ip_address(start_ip)), str(end_ip)]] + lowest_ip, highest_ip = min(ips), max(ips) + + self.assertEqual(25, + VppSetupEnvHelper.get_prefix_length(int(lowest_ip), + int(highest_ip), + lowest_ip.max_prefixlen)) + + def test_get_prefix_length_zero_prefix(self): + start_ip = '10.0.0.0' + end_ip = '10.0.0.0' + ips = [ipaddress.ip_address(ip) for ip in + [str(ipaddress.ip_address(start_ip)), str(end_ip)]] + lowest_ip, highest_ip = min(ips), max(ips) + + self.assertEqual(0, + VppSetupEnvHelper.get_prefix_length(int(lowest_ip), + int(highest_ip), + 0)) + + +class TestVatTerminal(unittest.TestCase): + + def test___init___error(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_open.side_effect = exceptions.SSHTimeout + + with self.assertRaises(RuntimeError) as raised: + VatTerminal(ssh_helper, json_param=True) + self.assertIn('Cannot open interactive terminal', + str(raised.exception)) + + def test___init___exec_error(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.side_effect = exceptions.SSHTimeout + VatTerminal(ssh_helper, json_param=True) + + def test_vat_terminal_exec_cmd(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.return_value = str( + {'empty': 'value'}).replace("\'", "\"") + vat_terminal = VatTerminal(ssh_helper, json_param=True) + + self.assertEqual({'empty': 'value'}, + vat_terminal.vat_terminal_exec_cmd( + "hw_interface_set_mtu sw_if_index 1 mtu 9200")) + + def test_vat_terminal_exec_cmd_array(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.return_value = str( + [{'empty': 'value'}]).replace("\'", "\"") + vat_terminal = VatTerminal(ssh_helper, json_param=True) + + self.assertEqual([{'empty': 'value'}], + vat_terminal.vat_terminal_exec_cmd( + "hw_interface_set_mtu sw_if_index 1 mtu 9200")) + + def test_vat_terminal_exec_cmd_without_output(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.return_value = str( + {'empty': 'value'}).replace("\'", "\"") + vat_terminal = VatTerminal(ssh_helper, json_param=False) + + self.assertIsNone(vat_terminal.vat_terminal_exec_cmd( + "hw_interface_set_mtu sw_if_index 1 mtu 9200")) + + def test_vat_terminal_exec_cmd_error(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.return_value = str( + {'empty': 'value'}).replace("\'", "\"") + ssh_helper.interactive_terminal_exec_command.side_effect = exceptions.SSHTimeout + + vat_terminal = VatTerminal(ssh_helper, json_param=True) + + with self.assertRaises(RuntimeError) as raised: + vat_terminal.vat_terminal_exec_cmd( + "hw_interface_set_mtu sw_if_index 1 mtu 9200") + self.assertIn( + 'VPP is not running on node. VAT command hw_interface_set_mtu ' \ + 'sw_if_index 1 mtu 9200 execution failed', + str(raised.exception)) + + def test_vat_terminal_exec_cmd_output_error(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.return_value = str( + 'empty: value').replace("\'", "\"") + + vat_terminal = VatTerminal(ssh_helper, json_param=True) + + with self.assertRaises(RuntimeError) as raised: + vat_terminal.vat_terminal_exec_cmd( + "hw_interface_set_mtu sw_if_index 1 mtu 9200") + self.assertIn( + 'VAT command hw_interface_set_mtu sw_if_index 1 mtu 9200: no JSON data.', + str(raised.exception)) + + def test_vat_terminal_close(self): + ssh_helper = mock.Mock() + vat_terminal = VatTerminal(ssh_helper, json_param=False) + self.assertIsNone(vat_terminal.vat_terminal_close()) + + def test_vat_terminal_close_error(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_exec_command.side_effect = exceptions.SSHTimeout + vat_terminal = VatTerminal(ssh_helper, json_param=False) + with self.assertRaises(RuntimeError) as raised: + vat_terminal.vat_terminal_close() + self.assertIn('Failed to close VAT console', str(raised.exception)) + + def test_vat_terminal_close_vat_error(self): + ssh_helper = mock.Mock() + ssh_helper.interactive_terminal_close.side_effect = exceptions.SSHTimeout + vat_terminal = VatTerminal(ssh_helper, json_param=False) + with self.assertRaises(RuntimeError) as raised: + vat_terminal.vat_terminal_close() + self.assertIn('Cannot close interactive terminal', + str(raised.exception)) + + def test_vat_terminal_exec_cmd_from_template(self): + ssh_helper = mock.Mock() + vat_terminal = VatTerminal(ssh_helper, json_param=False) + + with mock.patch.object(vat_terminal, 'vat_terminal_exec_cmd') as \ + mock_vat_terminal_exec_cmd: + mock_vat_terminal_exec_cmd.return_value = 'empty' + self.assertEqual(['empty'], + vat_terminal.vat_terminal_exec_cmd_from_template( + "hw_interface_set_mtu.vat", sw_if_index=1, + mtu=9200)) |