From 1c10e3cd55296a3f23b108120240a285a55bb733 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:38:19 +1000 Subject: [PATCH 1/8] Add SR-IOV support to nmcli module (#9168) --- .../9168-nmcli-add-sriov-parameter.yml | 2 + plugins/modules/nmcli.py | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 changelogs/fragments/9168-nmcli-add-sriov-parameter.yml diff --git a/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml b/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml new file mode 100644 index 00000000000..44e7967a5d2 --- /dev/null +++ b/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml @@ -0,0 +1,2 @@ +minor_changes: + - nmcli - add ``sriov`` parameter that enables support for SR-IOV settings specified at (https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/settings-sriov.html) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index e2803432a96..95cff53ef2a 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1058,6 +1058,38 @@ You can encode using this Ansible jinja2 expression: V("0s{{ '[YOUR PRE-SHARED KEY]' | ansible.builtin.b64encode }}"). - This is only used when O(vpn.ipsec-enabled=true). type: str + sriov: + description: + - SR-IOV settings + - 'An up-to-date list of supported attributes can be found here: + U(https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/settings-sriov.html).' + type: dict + version_added: 10.0.2 + suboptions: + autoprobe_drivers: + description: + - Whether to autoprobe virtual functions by a compatible driver. + type: int + eswitch_encap_mode: + description: + - Select the eswitch encapsulation support. + type: int + eswitch_inline_mode: + description: + - Select the eswitch inline-mode of the device. + type: int + eswitch_mode: + description: + - Select the eswitch mode of the device. + type: int + total_vfs: + description: Number of virtual functions to create. Consult your NIC documentation for the maximum number of VFs supported. + type: int + vfs: + description: + - Virtual function descriptors in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". + - Multiple VFs can be specified using a comma as separator e.g. "2 mac=00:11:22:33:44:55 spoof-check=true,3 vlan=100". + type: str ''' EXAMPLES = r''' @@ -1687,6 +1719,7 @@ def __init__(self, module): self.wireguard = module.params['wireguard'] self.vpn = module.params['vpn'] self.transport_mode = module.params['transport_mode'] + self.sriov = module.params['sriov'] if self.method4: self.ipv4_method = self.method4 @@ -1952,6 +1985,12 @@ def connection_options(self, detect_change=False): 'infiniband.transport-mode': self.transport_mode, }) + if self.sriov: + for name, value in self.sriov.items(): + options.update({ + '%s' % re.sub('_','-',name): value, + }) + # Convert settings values based on the situation. for setting, value in options.items(): setting_type = self.settings_type(setting) @@ -2607,6 +2646,16 @@ def main(): wireguard=dict(type='dict'), vpn=dict(type='dict'), transport_mode=dict(type='str', choices=['datagram', 'connected']), + sriov=dict(type='list', + elements='dict', + options=dict( + autoprobe_drivers=dict(type='int'), + eswitch_encap_mode=dict(type='int'), + eswitch_inline_mode=dict(type='int'), + eswitch_mode=dict(type='int'), + total_vfs=dict(type='int'), + vfs=dict(type='str'), + )), ), mutually_exclusive=[['never_default4', 'gw4'], ['routes4_extended', 'routes4'], From 7db7604256c934f4831eca9957160b82c05cf550 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:29:21 +1000 Subject: [PATCH 2/8] Add SR-IOV support to nmcli module (#9168) Fixes --- plugins/modules/nmcli.py | 31 ++++++------------------ tests/unit/plugins/modules/test_nmcli.py | 1 + 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index 95cff53ef2a..38de58c07c4 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1064,30 +1064,30 @@ - 'An up-to-date list of supported attributes can be found here: U(https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/settings-sriov.html).' type: dict - version_added: 10.0.2 + version_added: 10.0.0 suboptions: - autoprobe_drivers: + autoprobe-drivers: description: - Whether to autoprobe virtual functions by a compatible driver. type: int - eswitch_encap_mode: + eswitch-encap-mode: description: - Select the eswitch encapsulation support. type: int - eswitch_inline_mode: + eswitch-inline-mode: description: - Select the eswitch inline-mode of the device. type: int - eswitch_mode: + eswitch-mode: description: - Select the eswitch mode of the device. type: int - total_vfs: + total-vfs: description: Number of virtual functions to create. Consult your NIC documentation for the maximum number of VFs supported. type: int vfs: description: - - Virtual function descriptors in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". + - 'Virtual function descriptors in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]".' - Multiple VFs can be specified using a comma as separator e.g. "2 mac=00:11:22:33:44:55 spoof-check=true,3 vlan=100". type: str ''' @@ -1985,12 +1985,6 @@ def connection_options(self, detect_change=False): 'infiniband.transport-mode': self.transport_mode, }) - if self.sriov: - for name, value in self.sriov.items(): - options.update({ - '%s' % re.sub('_','-',name): value, - }) - # Convert settings values based on the situation. for setting, value in options.items(): setting_type = self.settings_type(setting) @@ -2646,16 +2640,7 @@ def main(): wireguard=dict(type='dict'), vpn=dict(type='dict'), transport_mode=dict(type='str', choices=['datagram', 'connected']), - sriov=dict(type='list', - elements='dict', - options=dict( - autoprobe_drivers=dict(type='int'), - eswitch_encap_mode=dict(type='int'), - eswitch_inline_mode=dict(type='int'), - eswitch_mode=dict(type='int'), - total_vfs=dict(type='int'), - vfs=dict(type='str'), - )), + sriov=dict(type='dict'), ), mutually_exclusive=[['never_default4', 'gw4'], ['routes4_extended', 'routes4'], diff --git a/tests/unit/plugins/modules/test_nmcli.py b/tests/unit/plugins/modules/test_nmcli.py index 570b04d56f5..2c724cf3e33 100644 --- a/tests/unit/plugins/modules/test_nmcli.py +++ b/tests/unit/plugins/modules/test_nmcli.py @@ -4384,6 +4384,7 @@ def test_bond_connection_unchanged(mocked_generic_connection_diff_check, capfd): wireguard=dict(type='dict'), vpn=dict(type='dict'), transport_mode=dict(type='str', choices=['datagram', 'connected']), + sriov=dict(type='dict'), ), mutually_exclusive=[['never_default4', 'gw4'], ['routes4_extended', 'routes4'], From 9db16ac55b369ff02a581701ca4480e0bb63c875 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:48:46 +1000 Subject: [PATCH 3/8] Add SR-IOV support to nmcli module (#9168) Add test --- plugins/modules/nmcli.py | 2 +- tests/unit/plugins/modules/test_nmcli.py | 63 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index 38de58c07c4..deb1733ce66 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1088,7 +1088,7 @@ vfs: description: - 'Virtual function descriptors in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]".' - - Multiple VFs can be specified using a comma as separator e.g. "2 mac=00:11:22:33:44:55 spoof-check=true,3 vlan=100". + - Multiple VFs can be specified using a comma as separator e.g. "2 mac=00:11:22:33:44:55 spoof-check=true,3 vlans=100". type: str ''' diff --git a/tests/unit/plugins/modules/test_nmcli.py b/tests/unit/plugins/modules/test_nmcli.py index 2c724cf3e33..da80a9e0736 100644 --- a/tests/unit/plugins/modules/test_nmcli.py +++ b/tests/unit/plugins/modules/test_nmcli.py @@ -357,6 +357,28 @@ ipv6.ignore-auto-routes: no """ +TESTCASE_ETHERNET_ADD_SRIOV_VFS = [ + { + 'type': 'ethernet', + 'conn_name': 'non_existent_nw_device', + 'ifname': 'ethernet_non_existant', + 'sriov': { + 'total-vfs': 16, + 'vfs': '0 spoof-check=true vlans=100' + }, + 'state': 'present', + '_ansible_check_mode': False, + } +] + +TESTCASE_ETHERNET_ADD_SRIOV_VFS_SHOW_OUTPUT = """\ +connection.id: non_existent_nw_device +connection.interface-name: ethernet_non_existant +connection.autoconnect: yes +sriov.total-vfs: 16 +sriov.vfs: 0 spoof-check=true vlans=100 +""" + TESTCASE_ETHERNET_ADD_IPV6_INT_WITH_ROUTE_AND_METRIC = [ { 'type': 'ethernet', @@ -1806,6 +1828,12 @@ def mocked_ethernet_connection_with_ipv6_static_address_multiple_static_routes_c )) +@pytest.fixture +def mocked_ethernet_connection_with_sriov_vfs_create(mocker): + mocker_set(mocker, + execute_return=(0, TESTCASE_ETHERNET_ADD_SRIOV_VFS_SHOW_OUTPUT, "")) + + @pytest.fixture def mocked_ethernet_connection_with_ipv6_static_address_static_route_with_metric_create(mocker): mocker_set(mocker, @@ -3312,6 +3340,41 @@ def test_ethernet_connection_static_ipv6_address_multiple_static_routes_with_met assert results['changed'] +@pytest.mark.parametrize('patch_ansible_module', TESTCASE_ETHERNET_ADD_SRIOV_VFS, indirect=['patch_ansible_module']) +def test_ethernet_connection_sriov_vfs_create( + mocked_ethernet_connection_with_sriov_vfs_create, capfd): + """ + Test : Create ethernet connection with SR-IOV VFs + """ + with pytest.raises(SystemExit): + nmcli.main() + + assert nmcli.Nmcli.execute_command.call_count == 1 + arg_list = nmcli.Nmcli.execute_command.call_args_list + add_args, add_kw = arg_list[0] + + assert add_args[0][0] == '/usr/bin/nmcli' + assert add_args[0][1] == 'con' + assert add_args[0][2] == 'add' + assert add_args[0][3] == 'type' + assert add_args[0][4] == 'ethernet' + assert add_args[0][5] == 'con-name' + assert add_args[0][6] == 'non_existent_nw_device' + + add_args_text = list(map(to_text, add_args[0])) + + for param in ['connection.interface-name', 'ethernet_non_existant', + 'con-name', 'non_existent_nw_device', + 'sriov.total-vfs', '16', + 'sriov.vfs', '0 spoof-check=true vlans=100']: + assert param in add_args_text + + out, err = capfd.readouterr() + results = json.loads(out) + assert not results.get('failed') + assert results['changed'] + + @pytest.mark.parametrize('patch_ansible_module', TESTCASE_ETHERNET_ADD_IPV6_INT_WITH_ROUTE_AND_METRIC, indirect=['patch_ansible_module']) def test_ethernet_connection_static_ipv6_address_static_route_with_metric_create( mocked_ethernet_connection_with_ipv6_static_address_static_route_with_metric_create, capfd): From 0de42c4cc2b8b0efdeebc412639cef8d5b014bd4 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:22:07 +1000 Subject: [PATCH 4/8] Update changelogs/fragments/9168-nmcli-add-sriov-parameter.yml Co-authored-by: Felix Fontein --- changelogs/fragments/9168-nmcli-add-sriov-parameter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml b/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml index 44e7967a5d2..77f28e73bfb 100644 --- a/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml +++ b/changelogs/fragments/9168-nmcli-add-sriov-parameter.yml @@ -1,2 +1,2 @@ minor_changes: - - nmcli - add ``sriov`` parameter that enables support for SR-IOV settings specified at (https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/settings-sriov.html) + - nmcli - add ``sriov`` parameter that enables support for SR-IOV settings (https://github.com/ansible-collections/community.general/pull/9168). From 16ff3d0cf38a98afce08e26722eadeb311a00245 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:22:17 +1000 Subject: [PATCH 5/8] Update plugins/modules/nmcli.py Co-authored-by: Felix Fontein --- plugins/modules/nmcli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index deb1733ce66..87c8d22192f 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1060,7 +1060,7 @@ type: str sriov: description: - - SR-IOV settings + - Allow to configure SR-IOV settings. - 'An up-to-date list of supported attributes can be found here: U(https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/settings-sriov.html).' type: dict From 7ea72dd1cb7f1306e32cbe419153a7cb75e97da3 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:22:27 +1000 Subject: [PATCH 6/8] Update plugins/modules/nmcli.py Co-authored-by: Felix Fontein --- plugins/modules/nmcli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index 87c8d22192f..b63f662833d 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1064,7 +1064,7 @@ - 'An up-to-date list of supported attributes can be found here: U(https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/settings-sriov.html).' type: dict - version_added: 10.0.0 + version_added: 10.1.0 suboptions: autoprobe-drivers: description: From 96c0901994e8a360213f64fe940bc7c0d20817c9 Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:22:37 +1000 Subject: [PATCH 7/8] Update plugins/modules/nmcli.py Co-authored-by: Felix Fontein --- plugins/modules/nmcli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index b63f662833d..297715b08d7 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1087,8 +1087,8 @@ type: int vfs: description: - - 'Virtual function descriptors in the form: "INDEX [ATTR=VALUE[ ATTR=VALUE]...]".' - - Multiple VFs can be specified using a comma as separator e.g. "2 mac=00:11:22:33:44:55 spoof-check=true,3 vlans=100". + - 'Virtual function descriptors in the form: V(INDEX [ATTR=VALUE[ ATTR=VALUE]...]).' + - Multiple VFs can be specified using a comma as separator, for example V(2 mac=00:11:22:33:44:55 spoof-check=true,3 vlans=100). type: str ''' From 9d16b784aa8c685f9d36307bb62d2375987d536d Mon Sep 17 00:00:00 2001 From: Ian Bishop <151477169+ianb-mp@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:49:01 +1000 Subject: [PATCH 8/8] Populate sriov options --- plugins/modules/nmcli.py | 7 +++++++ tests/unit/plugins/modules/test_nmcli.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/modules/nmcli.py b/plugins/modules/nmcli.py index 297715b08d7..4ea67995773 100644 --- a/plugins/modules/nmcli.py +++ b/plugins/modules/nmcli.py @@ -1985,6 +1985,13 @@ def connection_options(self, detect_change=False): 'infiniband.transport-mode': self.transport_mode, }) + if self.type == 'ethernet': + if self.sriov: + for name, value in self.sriov.items(): + options.update({ + 'sriov.%s' % name: value, + }) + # Convert settings values based on the situation. for setting, value in options.items(): setting_type = self.settings_type(setting) diff --git a/tests/unit/plugins/modules/test_nmcli.py b/tests/unit/plugins/modules/test_nmcli.py index da80a9e0736..89e8de6d64d 100644 --- a/tests/unit/plugins/modules/test_nmcli.py +++ b/tests/unit/plugins/modules/test_nmcli.py @@ -364,7 +364,7 @@ 'ifname': 'ethernet_non_existant', 'sriov': { 'total-vfs': 16, - 'vfs': '0 spoof-check=true vlans=100' + 'vfs': '0 spoof-check=true vlans=100', }, 'state': 'present', '_ansible_check_mode': False,