From 675f15376f4ff99c16e59c005ac2ef157baf9431 Mon Sep 17 00:00:00 2001 From: Jaganathan Palanisamy <jpalanis@redhat.com> Date: Sun, 11 Nov 2018 12:49:24 -0500 Subject: [PATCH] Derives NUMA aware vSwitches parameters Derives the NUMA aware vSwitches parameters NeutronPhysnetNUMANodesMapping and NeutronTunnelNUMANodes automatically using host introspection. Change-Id: Ia3a55ec158b16485cd3ffa56d4931b73502a1058 Closes-Bug: #1797925 --- tripleo_common/actions/derive_params.py | 6 +- .../tests/actions/test_derive_params.py | 18 ++++-- workbooks/derive_params.yaml | 1 + workbooks/derive_params_formulas.yaml | 55 ++++++++++++++++++- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/tripleo_common/actions/derive_params.py b/tripleo_common/actions/derive_params.py index 562ef7b88..74c61406d 100644 --- a/tripleo_common/actions/derive_params.py +++ b/tripleo_common/actions/derive_params.py @@ -142,6 +142,8 @@ class GetDpdkNicsNumaInfoAction(base.TripleOAction): # with mtu and numa node id for config in self.network_configs: if config.get('type', '') == 'ovs_user_bridge': + bridge_name = config.get('name', '') + addresses = config.get('addresses', []) members = config.get('members', []) dpdk_ifaces, mtu = self.get_dpdk_interfaces(members) for dpdk_iface in dpdk_ifaces: @@ -156,7 +158,9 @@ class GetDpdkNicsNumaInfoAction(base.TripleOAction): dpdk_nic_info = {'name': phy_name, 'numa_node': node, - 'mtu': mtu} + 'mtu': mtu, + 'bridge_name': bridge_name, + 'addresses': addresses} dpdk_nics_numa_info.append(dpdk_nic_info) return dpdk_nics_numa_info diff --git a/tripleo_common/tests/actions/test_derive_params.py b/tripleo_common/tests/actions/test_derive_params.py index acc3c23d8..e2d90c56a 100644 --- a/tripleo_common/tests/actions/test_derive_params.py +++ b/tripleo_common/tests/actions/test_derive_params.py @@ -32,7 +32,8 @@ class GetDpdkNicsNumaInfoActionTest(base.TestCase): "mtu": 8192, "rx_queue": 4}], "name": "br-link", - "type": "ovs_user_bridge"}] + "type": "ovs_user_bridge", + "addresses": [{"ip_netmask": ""}]}] inspect_data = { "numa_topology": { @@ -63,7 +64,9 @@ class GetDpdkNicsNumaInfoActionTest(base.TestCase): } } - expected_result = [{'name': 'ens802f1', 'mtu': 8192, 'numa_node': 1}] + expected_result = [{'bridge_name': 'br-link', 'name': 'ens802f1', + 'mtu': 8192, 'numa_node': 1, + 'addresses': [{'ip_netmask': ''}]}] mock_ctx = mock.MagicMock() action = derive_params.GetDpdkNicsNumaInfoAction(network_configs, @@ -84,7 +87,8 @@ class GetDpdkNicsNumaInfoActionTest(base.TestCase): "members": [{"type": "interface", "name": "nic5"}]}]}], "name": "br-link", - "type": "ovs_user_bridge"}] + "type": "ovs_user_bridge", + "addresses": [{"ip_netmask": "172.16.10.0/24"}]}] inspect_data = { "numa_topology": { "nics": [{"name": "ens802f1", "numa_node": 1}, @@ -113,8 +117,12 @@ class GetDpdkNicsNumaInfoActionTest(base.TestCase): "name": "enp13s0f1"}] } } - expected_result = [{'mtu': 9000, 'numa_node': 1, 'name': 'ens802f0'}, - {'mtu': 9000, 'numa_node': 1, 'name': 'ens802f1'}] + expected_result = [{'bridge_name': 'br-link', 'mtu': 9000, + 'numa_node': 1, 'name': 'ens802f0', + 'addresses': [{'ip_netmask': '172.16.10.0/24'}]}, + {'bridge_name': 'br-link', 'mtu': 9000, + 'numa_node': 1, 'name': 'ens802f1', + 'addresses': [{'ip_netmask': '172.16.10.0/24'}]}] mock_ctx = mock.MagicMock() action = derive_params.GetDpdkNicsNumaInfoAction(network_configs, diff --git a/workbooks/derive_params.yaml b/workbooks/derive_params.yaml index 577191798..c9bdd4aa6 100644 --- a/workbooks/derive_params.yaml +++ b/workbooks/derive_params.yaml @@ -291,6 +291,7 @@ workflows: input: plan: <% $.plan %> role_name: <% $.role_name %> + heat_resource_tree: <% $.heat_resource_tree %> hw_data: <% $.hw_data %> user_inputs: <% $.user_inputs %> publish: diff --git a/workbooks/derive_params_formulas.yaml b/workbooks/derive_params_formulas.yaml index 640d681c4..df172511b 100644 --- a/workbooks/derive_params_formulas.yaml +++ b/workbooks/derive_params_formulas.yaml @@ -12,6 +12,7 @@ workflows: input: - plan - role_name + - heat_resource_tree - hw_data # introspection data - user_inputs - derived_parameters: {} @@ -117,13 +118,65 @@ workflows: publish: sock_mem: <% task().result %> on-success: - - get_dpdk_parameters: <% $.sock_mem %> + - get_neutron_bridge_mappings: <% $.sock_mem %> - set_status_failed_get_sock_mem: <% not $.sock_mem %> on-error: set_status_failed_on_error_get_sock_mem + get_neutron_bridge_mappings: + publish: + neutron_bridge_mappings: <% $.heat_resource_tree.parameters.get('NeutronBridgeMappings', {}).get('default', '') %> + on-success: + - get_phy_nw_bridge_mappings: <% $.neutron_bridge_mappings %> + - get_neutron_network_type: <% not $.neutron_bridge_mappings %> + + # Gets the physical network and ovs bridge mappings + get_phy_nw_bridge_mappings: + publish: + phy_nw_bridge_mappings: <% $.neutron_bridge_mappings.split(',').select(let(mapping => $.split(':')) -> dict($mapping[0] => $mapping[1])).sum() %> + on-success: get_bridge_numa_nodes_mappings + + # Gets the ovs bridge and NUMA nodes mappings + get_bridge_numa_nodes_mappings: + publish: + bridge_numa_nodes_mappings: <% $.dpdk_nics_numa_info.groupBy($.bridge_name).select(dict($[0]=>$[1].select($.numa_node).distinct())).sum() %> + on-success: get_phy_nw_numa_nodes_mappings + + # Gets the physical network and NUMA nodes mappings + get_phy_nw_numa_nodes_mappings: + publish: + phy_nw_numa_nodes_mappings: <% let(br_numa_mappings => bridge_numa_nodes_mappings) -> $.phy_nw_bridge_mappings.items().select(dict($[0]=>$br_numa_mappings.get($[1], []))).sum() %> + on-success: get_neutron_network_type + + get_neutron_network_type: + publish: + neutron_network_type: <% $.heat_resource_tree.parameters.get('NeutronNetworkType', {}).get('default', '') %> + on-success: + - get_tunnel_numa_nodes_mappings: <% 'vxlan' in $.neutron_network_type %> + - get_dpdk_parameters: <% not 'vxlan' in $.neutron_network_type %> + + # Gets the list of NUMA nodes associated to all tunneled networks + # OVS-DPDK on VxLAN tunnel requires Tenant Network IP to be applied on the OVS User Bridge itself. + # With this assumption, if the IP is set on the OVS User Bridge, then OVS-DPDK is used for VxLAN tunnels also. + # Here dpdk_nics_numa_info will have the OVS User Bridges with DPDK ports only. + get_tunnel_numa_nodes_mappings: + publish: + tunnel_numa_nodes_mappings: <% $.dpdk_nics_numa_info.where($.addresses.any($.ip_netmask)).select($.numa_node).distinct() %> + on-success: get_dpdk_parameters + get_dpdk_parameters: publish: dpdk_parameters: <% dict(concat($.role_name, 'Parameters') => dict('OvsPmdCoreList' => $.get('pmd_cpus', ''), 'OvsDpdkCoreList' => $.get('host_cpus', ''), 'OvsDpdkSocketMemory' => $.get('sock_mem', ''))) %> + on-success: + - add_phy_nw_numa_nodes_mappings: <% $.get('phy_nw_numa_nodes_mappings', {}) %> + - add_tunnel_numa_nodes_mappings: <% $.get('tunnel_numa_nodes_mappings', []) %> + + add_phy_nw_numa_nodes_mappings: + publish: + dpdk_parameters: <% $.dpdk_parameters.mergeWith(dict(concat($.role_name, 'Parameters') => dict('NeutronPhysnetNUMANodesMapping' => $.get('phy_nw_numa_nodes_mappings', {})))) %> + + add_tunnel_numa_nodes_mappings: + publish: + dpdk_parameters: <% $.dpdk_parameters.mergeWith(dict(concat($.role_name, 'Parameters') => dict('NeutronTunnelNUMANodes' => $.get('tunnel_numa_nodes_mappings', [])))) %> set_status_failed_get_network_config: publish: