1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

nmcli: Introduce VxLan (#45932)

This work enables to add vxlan via nmcli module

```
  - nmcli:
      type: vxlan
      conn_name: vxlan_test1
      vxlan_id: 16
      vxlan_local: 192.168.1.2
      vxlan_remote: 192.168.1.5
```
ansible 2.8.0

revision 1: Added tests

Signed-off-by: Susant Sahani <susant@redhat.com>
This commit is contained in:
Susant Sahani 2018-10-30 12:47:33 +05:30 committed by ansibot
parent e0f7a522a3
commit 2596ac196f
2 changed files with 146 additions and 4 deletions

View file

@ -53,7 +53,7 @@ options:
description: description:
- This is the type of device or network connection that you wish to create or modify. - This is the type of device or network connection that you wish to create or modify.
- "type C(generic) is added in version 2.5." - "type C(generic) is added in version 2.5."
choices: [ ethernet, team, team-slave, bond, bond-slave, bridge, bridge-slave, vlan, generic ] choices: [ ethernet, team, team-slave, bond, bond-slave, bridge, bridge-slave, vlan, vxlan, generic ]
mode: mode:
description: 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, team or bridge.
@ -174,7 +174,18 @@ options:
egress: egress:
description: description:
- This is only used with VLAN - VLAN egress priority mapping - This is only used with VLAN - VLAN egress priority mapping
vxlan_id:
description:
- This is only used with VXLAN - VXLAN ID.
version_added: "2.8"
vxlan_remote:
description:
- This is only used with VXLAN - VXLAN destination IP address.
version_added: "2.8"
vxlan_local:
description:
- This is only used with VXLAN - VXLAN local IP address.
version_added: "2.8"
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -434,6 +445,14 @@ EXAMPLES = '''
type: ethernet type: ethernet
state: present state: present
# To add VxLan, issue a command as follows:
- nmcli:
type: vxlan
conn_name: vxlan_test1
vxlan_id: 16
vxlan_local: 192.168.1.2
vxlan_remote: 192.168.1.5
# nmcli exits with status 0 if it succeeds and exits with a status greater # nmcli exits with status 0 if it succeeds and exits with a status greater
# than zero when there is a failure. The following list of status codes may be # than zero when there is a failure. The following list of status codes may be
# returned: # returned:
@ -505,7 +524,8 @@ class Nmcli(object):
12: "ADSL", 12: "ADSL",
13: "Bridge", 13: "Bridge",
14: "Generic", 14: "Generic",
15: "Team" 15: "Team",
16: "VxLan",
} }
STATES = { STATES = {
0: "Unknown", 0: "Unknown",
@ -562,6 +582,9 @@ class Nmcli(object):
self.flags = module.params['flags'] self.flags = module.params['flags']
self.ingress = module.params['ingress'] self.ingress = module.params['ingress']
self.egress = module.params['egress'] self.egress = module.params['egress']
self.vxlan_id = module.params['vxlan_id']
self.vxlan_local = module.params['vxlan_local']
self.vxlan_remote = module.params['vxlan_remote']
self.nmcli_bin = self.module.get_bin_path('nmcli', True) self.nmcli_bin = self.module.get_bin_path('nmcli', True)
self.dhcp_client_id = module.params['dhcp_client_id'] self.dhcp_client_id = module.params['dhcp_client_id']
@ -1072,6 +1095,53 @@ class Nmcli(object):
return cmd return cmd
def create_connection_vxlan(self):
cmd = [self.nmcli_bin, 'con', 'add', 'type', 'vxlan', 'con-name']
if self.conn_name is not None:
cmd.append(self.conn_name)
elif self.ifname is not None:
cmd.append(self.ifname)
else:
cmd.append('vxlan%s' % self.vxlanid)
cmd.append('ifname')
if self.ifname is not None:
cmd.append(self.ifname)
elif self.conn_name is not None:
cmd.append(self.conn_name)
else:
cmd.append('vxan%s' % self.vxlanid)
params = {'vxlan.id': self.vxlan_id,
'vxlan.local': self.vxlan_local,
'vxlan.remote': self.vxlan_remote,
'autoconnect': self.bool_to_string(self.autoconnect)
}
for k, v in params.items():
cmd.extend([k, v])
return cmd
def modify_connection_vxlan(self):
cmd = [self.nmcli_bin, 'con', 'mod']
if self.conn_name is not None:
cmd.append(self.conn_name)
elif self.ifname is not None:
cmd.append(self.ifname)
else:
cmd.append('vxlan%s' % self.vxlanid)
params = {'vxlan.id': self.vxlan_id,
'vxlan.local': self.vxlan_local,
'vxlan.remote': self.vxlan_remote,
'autoconnect': self.bool_to_string(self.autoconnect)
}
for k, v in params.items():
cmd.extend([k, v])
return cmd
def create_connection(self): def create_connection(self):
cmd = [] cmd = []
if self.type == 'team': if self.type == 'team':
@ -1117,6 +1187,8 @@ class Nmcli(object):
cmd = self.create_connection_bridge_slave() cmd = self.create_connection_bridge_slave()
elif self.type == 'vlan': elif self.type == 'vlan':
cmd = self.create_connection_vlan() cmd = self.create_connection_vlan()
elif self.type == 'vxlan':
cmd = self.create_connection_vxlan()
elif self.type == 'generic': elif self.type == 'generic':
cmd = self.create_connection_ethernet(conn_type='generic') cmd = self.create_connection_ethernet(conn_type='generic')
@ -1149,6 +1221,8 @@ class Nmcli(object):
cmd = self.modify_connection_bridge_slave() cmd = self.modify_connection_bridge_slave()
elif self.type == 'vlan': elif self.type == 'vlan':
cmd = self.modify_connection_vlan() cmd = self.modify_connection_vlan()
elif self.type == 'vxlan':
cmd = self.modify_connection_vxlan()
elif self.type == 'generic': elif self.type == 'generic':
cmd = self.modify_connection_ethernet(conn_type='generic') cmd = self.modify_connection_ethernet(conn_type='generic')
if cmd: if cmd:
@ -1170,7 +1244,7 @@ def main():
type=dict(required=False, default=None, type=dict(required=False, default=None,
choices=['ethernet', 'team', 'team-slave', 'bond', choices=['ethernet', 'team', 'team-slave', 'bond',
'bond-slave', 'bridge', 'bridge-slave', 'bond-slave', 'bridge', 'bridge-slave',
'vlan', 'generic'], 'vlan', 'vxlan', 'generic'],
type='str'), type='str'),
ip4=dict(required=False, default=None, type='str'), ip4=dict(required=False, default=None, type='str'),
gw4=dict(required=False, default=None, type='str'), gw4=dict(required=False, default=None, type='str'),
@ -1209,6 +1283,10 @@ def main():
flags=dict(required=False, default=None, type='str'), flags=dict(required=False, default=None, type='str'),
ingress=dict(required=False, default=None, type='str'), ingress=dict(required=False, default=None, type='str'),
egress=dict(required=False, default=None, type='str'), egress=dict(required=False, default=None, type='str'),
# vxlan specific vars
vxlan_id=dict(required=False, default=None, type='str'),
vxlan_local=dict(required=False, default=None, type='str'),
vxlan_remote=dict(required=False, default=None, type='str'),
), ),
supports_check_mode=True supports_check_mode=True
) )

View file

@ -52,6 +52,12 @@ TESTCASE_CONNECTION = [
'state': 'absent', 'state': 'absent',
'_ansible_check_mode': True, '_ansible_check_mode': True,
}, },
{
'type': 'vxlan',
'conn_name': 'non_existent_nw_device',
'state': 'absent',
'_ansible_check_mode': True,
},
] ]
TESTCASE_GENERIC = [ TESTCASE_GENERIC = [
@ -131,6 +137,18 @@ TESTCASE_VLAN = [
} }
] ]
TESTCASE_VXLAN = [
{
'type': 'vxlan',
'conn_name': 'non_existent_nw_device',
'ifname': 'vxlan-existent_nw_device',
'vxlan_id': '11',
'vxlan_local': '192.168.225.5',
'vxlan_remote': '192.168.225.6',
'state': 'present',
'_ansible_check_mode': False,
}
]
TESTCASE_ETHERNET_DHCP = [ TESTCASE_ETHERNET_DHCP = [
{ {
@ -436,6 +454,52 @@ def test_mod_vlan_conn(mocked_generic_connection_modify):
assert param in args[0] assert param in args[0]
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_VXLAN, indirect=['patch_ansible_module'])
def test_create_vxlan(mocked_generic_connection_create):
"""
Test if vxlan created
"""
with pytest.raises(SystemExit):
nmcli.main()
assert nmcli.Nmcli.execute_command.call_count == 1
arg_list = nmcli.Nmcli.execute_command.call_args_list
args, kwargs = arg_list[0]
assert args[0][0] == '/usr/bin/nmcli'
assert args[0][1] == 'con'
assert args[0][2] == 'add'
assert args[0][3] == 'type'
assert args[0][4] == 'vxlan'
assert args[0][5] == 'con-name'
assert args[0][6] == 'non_existent_nw_device'
assert args[0][7] == 'ifname'
for param in ['vxlan.local', '192.168.225.5', 'vxlan.remote', '192.168.225.6', 'vxlan.id', '11']:
assert param in args[0]
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_VXLAN, indirect=['patch_ansible_module'])
def test_vxlan_mod(mocked_generic_connection_modify):
"""
Test if vxlan modified
"""
with pytest.raises(SystemExit):
nmcli.main()
assert nmcli.Nmcli.execute_command.call_count == 1
arg_list = nmcli.Nmcli.execute_command.call_args_list
args, kwargs = arg_list[0]
assert args[0][0] == '/usr/bin/nmcli'
assert args[0][1] == 'con'
assert args[0][2] == 'mod'
assert args[0][3] == 'non_existent_nw_device'
for param in ['vxlan.local', '192.168.225.5', 'vxlan.remote', '192.168.225.6', 'vxlan.id', '11']:
assert param in args[0]
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_ETHERNET_DHCP, indirect=['patch_ansible_module']) @pytest.mark.parametrize('patch_ansible_module', TESTCASE_ETHERNET_DHCP, indirect=['patch_ansible_module'])
def test_eth_dhcp_client_id_con_create(mocked_generic_connection_create): def test_eth_dhcp_client_id_con_create(mocked_generic_connection_create):
""" """