From 9ffc1ef393b56d35e65f8ea48723b903da3d1fe8 Mon Sep 17 00:00:00 2001 From: omula Date: Wed, 14 Jul 2021 08:24:27 +0200 Subject: [PATCH] [nmcli] add runner and runner-hwaddr-policy for network teaming (#2901) * [nmcli] add runner and runner-hwaddr-policy for network teaming * [nmcli] delete extra space * Update plugins/modules/net_tools/nmcli.py * Update plugins/modules/net_tools/nmcli.py * [nmcli] add changelog fragment * Update plugins/modules/net_tools/nmcli.py Co-authored-by: Amin Vakil Co-authored-by: Oriol MULA VALLS Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Amin Vakil --- changelogs/fragments/2901-nmcli_teaming.yml | 2 ++ plugins/modules/net_tools/nmcli.py | 32 ++++++++++++++++++- .../plugins/modules/net_tools/test_nmcli.py | 26 +++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2901-nmcli_teaming.yml diff --git a/changelogs/fragments/2901-nmcli_teaming.yml b/changelogs/fragments/2901-nmcli_teaming.yml new file mode 100644 index 0000000000..4178b9c6f5 --- /dev/null +++ b/changelogs/fragments/2901-nmcli_teaming.yml @@ -0,0 +1,2 @@ +minor_changes: + - nmcli - add ``runner`` and ``runner_hwaddr_policy`` options (https://github.com/ansible-collections/community.general/issues/2901). diff --git a/plugins/modules/net_tools/nmcli.py b/plugins/modules/net_tools/nmcli.py index 7ed515fc75..1750f9f99f 100644 --- a/plugins/modules/net_tools/nmcli.py +++ b/plugins/modules/net_tools/nmcli.py @@ -57,7 +57,7 @@ options: choices: [ bond, bond-slave, bridge, bridge-slave, ethernet, generic, infiniband, ipip, sit, team, team-slave, vlan, vxlan, wifi ] mode: description: - - This is the type of device or network connection that you wish to create for a bond, team or bridge. + - This is the type of device or network connection that you wish to create for a bond or bridge. type: str choices: [ 802.3ad, active-backup, balance-alb, balance-rr, balance-tlb, balance-xor, broadcast ] default: balance-rr @@ -265,6 +265,20 @@ options: frame was received on. type: bool default: yes + runner: + description: + - This is the type of device or network connection that you wish to create for a team. + type: str + choices: [ broadcast, roundrobin, activebackup, loadbalance, lacp ] + default: roundrobin + version_added: 3.4.0 + runner_hwaddr_policy: + description: + - This defines the policy of how hardware addresses of team device and port devices + should be set during the team lifetime. + type: str + choices: [ same_all, by_active, only_active ] + version_added: 3.4.0 vlanid: description: - This is only used with VLAN - VLAN ID in range <0-4095>. @@ -719,6 +733,8 @@ class Nmcli(object): self.hairpin = module.params['hairpin'] self.path_cost = module.params['path_cost'] self.mac = module.params['mac'] + self.runner = module.params['runner'] + self.runner_hwaddr_policy = module.params['runner_hwaddr_policy'] self.vlanid = module.params['vlanid'] self.vlandev = module.params['vlandev'] self.flags = module.params['flags'] @@ -826,6 +842,11 @@ class Nmcli(object): 'bridge.priority': self.priority, 'bridge.stp': self.stp, }) + elif self.type == 'team': + options.update({ + 'team.runner': self.runner, + 'team.runner-hwaddr-policy': self.runner_hwaddr_policy, + }) elif self.type == 'bridge-slave': options.update({ 'connection.slave-type': 'bridge', @@ -1214,6 +1235,11 @@ def main(): ageingtime=dict(type='int', default=300), hairpin=dict(type='bool', default=True), path_cost=dict(type='int', default=100), + # team specific vars + runner=dict(type='str', default='roundrobin', + choices=['broadcast', 'roundrobin', 'activebackup', 'loadbalance', 'lacp']), + # team active-backup runner specific options + runner_hwaddr_policy=dict(type='str', choices=['same_all', 'by_active', 'only_active']), # vlan specific vars vlanid=dict(type='int'), vlandev=dict(type='str'), @@ -1245,6 +1271,10 @@ def main(): # check for issues if nmcli.conn_name is None: nmcli.module.fail_json(msg="Please specify a name for the connection") + # team checks + if nmcli.type == "team": + if nmcli.runner_hwaddr_policy and not nmcli.runner == "activebackup": + nmcli.module.fail_json(msg="Runner-hwaddr-policy is only allowed for runner activebackup") # team-slave checks if nmcli.type == 'team-slave': if nmcli.master is None: diff --git a/tests/unit/plugins/modules/net_tools/test_nmcli.py b/tests/unit/plugins/modules/net_tools/test_nmcli.py index ba526b1d65..63ec60537c 100644 --- a/tests/unit/plugins/modules/net_tools/test_nmcli.py +++ b/tests/unit/plugins/modules/net_tools/test_nmcli.py @@ -279,8 +279,20 @@ ipv4.may-fail: yes ipv6.method: auto ipv6.ignore-auto-dns: no ipv6.ignore-auto-routes: no +team.runner: roundrobin """ +TESTCASE_TEAM_HWADDR_POLICY_FAILS = [ + { + 'type': 'team', + 'conn_name': 'non_existent_nw_device', + 'ifname': 'team0_non_existant', + 'runner_hwaddr_policy': 'by_active', + 'state': 'present', + '_ansible_check_mode': False, + } +] + TESTCASE_TEAM_SLAVE = [ { 'type': 'team-slave', @@ -1053,6 +1065,20 @@ def test_team_connection_unchanged(mocked_team_connection_unchanged, capfd): assert not results['changed'] +@pytest.mark.parametrize('patch_ansible_module', TESTCASE_TEAM_HWADDR_POLICY_FAILS, indirect=['patch_ansible_module']) +def test_team_connection_create_hwaddr_policy_fails(mocked_generic_connection_create, capfd): + """ + Test : Team connection created + """ + with pytest.raises(SystemExit): + nmcli.main() + + out, err = capfd.readouterr() + results = json.loads(out) + assert results.get('failed') + assert results['msg'] == "Runner-hwaddr-policy is only allowed for runner activebackup" + + @pytest.mark.parametrize('patch_ansible_module', TESTCASE_TEAM_SLAVE, indirect=['patch_ansible_module']) def test_create_team_slave(mocked_generic_connection_create, capfd): """