Add new configurations for nxos_vxlan_vtep (#47834)
* add new commands for vxlan * review comments * fix unit test * fix sanity yaml spaces
This commit is contained in:
parent
1b9cf85860
commit
b92556549e
3 changed files with 155 additions and 7 deletions
|
@ -61,6 +61,28 @@ options:
|
||||||
description:
|
description:
|
||||||
- Suppresses advertisement of the NVE loopback address until
|
- Suppresses advertisement of the NVE loopback address until
|
||||||
the overlay has converged.
|
the overlay has converged.
|
||||||
|
global_mcast_group_L3:
|
||||||
|
description:
|
||||||
|
- Global multicast ip prefix for L3 VNIs or the keyword 'default'
|
||||||
|
This is available on NX-OS 9K series running 9.2.x or higher.
|
||||||
|
version_added: "2.8"
|
||||||
|
global_mcast_group_L2:
|
||||||
|
description:
|
||||||
|
- Global multicast ip prefix for L2 VNIs or the keyword 'default'
|
||||||
|
This is available on NX-OS 9K series running 9.2.x or higher.
|
||||||
|
version_added: "2.8"
|
||||||
|
global_suppress_arp:
|
||||||
|
description:
|
||||||
|
- Enables ARP suppression for all VNIs
|
||||||
|
This is available on NX-OS 9K series running 9.2.x or higher.
|
||||||
|
type: bool
|
||||||
|
version_added: "2.8"
|
||||||
|
global_ingress_replication_bgp:
|
||||||
|
description:
|
||||||
|
- Configures ingress replication protocol as bgp for all VNIs
|
||||||
|
This is available on NX-OS 9K series running 9.2.x or higher.
|
||||||
|
type: bool
|
||||||
|
version_added: "2.8"
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- Determines whether the config should be present or not
|
- Determines whether the config should be present or not
|
||||||
|
@ -97,10 +119,16 @@ from ansible.module_utils.network.common.config import CustomNetworkConfig
|
||||||
|
|
||||||
BOOL_PARAMS = [
|
BOOL_PARAMS = [
|
||||||
'shutdown',
|
'shutdown',
|
||||||
'host_reachability'
|
'host_reachability',
|
||||||
|
'global_ingress_replication_bgp',
|
||||||
|
'global_suppress_arp',
|
||||||
]
|
]
|
||||||
PARAM_TO_COMMAND_KEYMAP = {
|
PARAM_TO_COMMAND_KEYMAP = {
|
||||||
'description': 'description',
|
'description': 'description',
|
||||||
|
'global_suppress_arp': 'global suppress-arp',
|
||||||
|
'global_ingress_replication_bgp': 'global ingress-replication protocol bgp',
|
||||||
|
'global_mcast_group_L3': 'global mcast-group L3',
|
||||||
|
'global_mcast_group_L2': 'global mcast-group L2',
|
||||||
'host_reachability': 'host-reachability protocol bgp',
|
'host_reachability': 'host-reachability protocol bgp',
|
||||||
'interface': 'interface',
|
'interface': 'interface',
|
||||||
'shutdown': 'shutdown',
|
'shutdown': 'shutdown',
|
||||||
|
@ -151,6 +179,22 @@ def get_value(arg, config, module):
|
||||||
break
|
break
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
value = ''
|
value = ''
|
||||||
|
elif arg == 'global_mcast_group_L2':
|
||||||
|
for line in config.splitlines():
|
||||||
|
try:
|
||||||
|
if 'global mcast-group' in line and 'L2' in line:
|
||||||
|
value = line.split()[2].strip()
|
||||||
|
break
|
||||||
|
except AttributeError:
|
||||||
|
value = ''
|
||||||
|
elif arg == 'global_mcast_group_L3':
|
||||||
|
for line in config.splitlines():
|
||||||
|
try:
|
||||||
|
if 'global mcast-group' in line and 'L3' in line:
|
||||||
|
value = line.split()[2].strip()
|
||||||
|
break
|
||||||
|
except AttributeError:
|
||||||
|
value = ''
|
||||||
else:
|
else:
|
||||||
if PARAM_TO_COMMAND_KEYMAP[arg] in config:
|
if PARAM_TO_COMMAND_KEYMAP[arg] in config:
|
||||||
value = REGEX.search(config).group('value').strip()
|
value = REGEX.search(config).group('value').strip()
|
||||||
|
@ -194,6 +238,8 @@ def apply_key_map(key_map, table):
|
||||||
def fix_commands(commands, module):
|
def fix_commands(commands, module):
|
||||||
source_interface_command = ''
|
source_interface_command = ''
|
||||||
no_source_interface_command = ''
|
no_source_interface_command = ''
|
||||||
|
no_host_reachability_command = ''
|
||||||
|
host_reachability_command = ''
|
||||||
|
|
||||||
for command in commands:
|
for command in commands:
|
||||||
if 'no source-interface hold-down-time' in command:
|
if 'no source-interface hold-down-time' in command:
|
||||||
|
@ -204,14 +250,28 @@ def fix_commands(commands, module):
|
||||||
no_source_interface_command = command
|
no_source_interface_command = command
|
||||||
elif 'source-interface' in command:
|
elif 'source-interface' in command:
|
||||||
source_interface_command = command
|
source_interface_command = command
|
||||||
|
elif 'no host-reachability' in command:
|
||||||
|
no_host_reachability_command = command
|
||||||
|
elif 'host-reachability' in command:
|
||||||
|
host_reachability_command = command
|
||||||
|
|
||||||
|
if host_reachability_command:
|
||||||
|
commands.pop(commands.index(host_reachability_command))
|
||||||
|
commands.insert(0, host_reachability_command)
|
||||||
|
|
||||||
if source_interface_command:
|
if source_interface_command:
|
||||||
commands.pop(commands.index(source_interface_command))
|
commands.pop(commands.index(source_interface_command))
|
||||||
commands.insert(0, source_interface_command)
|
commands.insert(0, source_interface_command)
|
||||||
|
|
||||||
|
if no_host_reachability_command:
|
||||||
|
commands.pop(commands.index(no_host_reachability_command))
|
||||||
|
commands.append(no_host_reachability_command)
|
||||||
|
|
||||||
if no_source_interface_command:
|
if no_source_interface_command:
|
||||||
commands.pop(commands.index(no_source_interface_command))
|
commands.pop(commands.index(no_source_interface_command))
|
||||||
commands.append(no_source_interface_command)
|
commands.append(no_source_interface_command)
|
||||||
|
|
||||||
|
commands.insert(0, 'terminal dont-ask')
|
||||||
return commands
|
return commands
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,11 +289,19 @@ def state_present(module, existing, proposed, candidate):
|
||||||
elif value == 'default':
|
elif value == 'default':
|
||||||
if existing_commands.get(key):
|
if existing_commands.get(key):
|
||||||
existing_value = existing_commands.get(key)
|
existing_value = existing_commands.get(key)
|
||||||
|
if 'global mcast-group' in key:
|
||||||
|
commands.append('no {0}'.format(key))
|
||||||
|
else:
|
||||||
commands.append('no {0} {1}'.format(key, existing_value))
|
commands.append('no {0} {1}'.format(key, existing_value))
|
||||||
else:
|
else:
|
||||||
if key.replace(' ', '_').replace('-', '_') in BOOL_PARAMS:
|
if key.replace(' ', '_').replace('-', '_') in BOOL_PARAMS:
|
||||||
commands.append('no {0}'.format(key.lower()))
|
commands.append('no {0}'.format(key.lower()))
|
||||||
module.exit_json(commands=commands)
|
module.exit_json(commands=commands)
|
||||||
|
else:
|
||||||
|
if 'L2' in key:
|
||||||
|
commands.append('global mcast-group ' + value + ' L2')
|
||||||
|
elif 'L3' in key:
|
||||||
|
commands.append('global mcast-group ' + value + ' L3')
|
||||||
else:
|
else:
|
||||||
command = '{0} {1}'.format(key, value.lower())
|
command = '{0} {1}'.format(key, value.lower())
|
||||||
commands.append(command)
|
commands.append(command)
|
||||||
|
@ -258,6 +326,10 @@ def main():
|
||||||
interface=dict(required=True, type='str'),
|
interface=dict(required=True, type='str'),
|
||||||
description=dict(required=False, type='str'),
|
description=dict(required=False, type='str'),
|
||||||
host_reachability=dict(required=False, type='bool'),
|
host_reachability=dict(required=False, type='bool'),
|
||||||
|
global_ingress_replication_bgp=dict(required=False, type='bool'),
|
||||||
|
global_suppress_arp=dict(required=False, type='bool'),
|
||||||
|
global_mcast_group_L2=dict(required=False, type='str'),
|
||||||
|
global_mcast_group_L3=dict(required=False, type='str'),
|
||||||
shutdown=dict(required=False, type='bool'),
|
shutdown=dict(required=False, type='bool'),
|
||||||
source_interface=dict(required=False, type='str'),
|
source_interface=dict(required=False, type='str'),
|
||||||
source_interface_hold_down_time=dict(required=False, type='str'),
|
source_interface_hold_down_time=dict(required=False, type='str'),
|
||||||
|
@ -266,7 +338,13 @@ def main():
|
||||||
|
|
||||||
argument_spec.update(nxos_argument_spec)
|
argument_spec.update(nxos_argument_spec)
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
|
mutually_exclusive = [('global_ingress_replication_bgp', 'global_mcast_group_L2')]
|
||||||
|
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=argument_spec,
|
||||||
|
mutually_exclusive=mutually_exclusive,
|
||||||
|
supports_check_mode=True,
|
||||||
|
)
|
||||||
|
|
||||||
warnings = list()
|
warnings = list()
|
||||||
result = {'changed': False, 'commands': [], 'warnings': warnings}
|
result = {'changed': False, 'commands': [], 'warnings': warnings}
|
||||||
|
@ -279,7 +357,6 @@ def main():
|
||||||
existing = get_existing(module, args)
|
existing = get_existing(module, args)
|
||||||
proposed_args = dict((k, v) for k, v in module.params.items()
|
proposed_args = dict((k, v) for k, v in module.params.items()
|
||||||
if v is not None and k in args)
|
if v is not None and k in args)
|
||||||
|
|
||||||
proposed = {}
|
proposed = {}
|
||||||
for key, value in proposed_args.items():
|
for key, value in proposed_args.items():
|
||||||
if key != 'interface':
|
if key != 'interface':
|
||||||
|
|
|
@ -3,6 +3,30 @@
|
||||||
- debug: msg="Using provider={{ connection.transport }}"
|
- debug: msg="Using provider={{ connection.transport }}"
|
||||||
when: ansible_connection == "local"
|
when: ansible_connection == "local"
|
||||||
|
|
||||||
|
- set_fact: global_ingress_replication_bgp="true"
|
||||||
|
when: platform is search('N9K$') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: def_global_ingress_replication_bgp="false"
|
||||||
|
when: platform is search('N9K$') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: global_mcast_group_L3="225.1.1.1"
|
||||||
|
when: platform is search('N9K$') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: def_global_mcast_group_L3="default"
|
||||||
|
when: platform is search('N9K$') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: global_mcast_group_L2="225.1.1.2"
|
||||||
|
when: platform is search('N9K') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: def_global_mcast_group_L2="default"
|
||||||
|
when: platform is search('N9K') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: global_suppress_arp="true"
|
||||||
|
when: platform is search('N9K') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
|
- set_fact: def_global_suppress_arp="false"
|
||||||
|
when: platform is search('N9K') and (major_version is version('9.2', 'ge'))
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: "Apply N7K specific setup config"
|
- name: "Apply N7K specific setup config"
|
||||||
include: targets/nxos_vxlan_vtep/tasks/platform/n7k/setup.yaml
|
include: targets/nxos_vxlan_vtep/tasks/platform/n7k/setup.yaml
|
||||||
|
@ -12,6 +36,7 @@
|
||||||
nxos_config:
|
nxos_config:
|
||||||
commands:
|
commands:
|
||||||
- feature nv overlay
|
- feature nv overlay
|
||||||
|
- nv overlay evpn
|
||||||
match: none
|
match: none
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
|
|
||||||
|
@ -23,6 +48,9 @@
|
||||||
host_reachability: true
|
host_reachability: true
|
||||||
source_interface: Loopback0
|
source_interface: Loopback0
|
||||||
source_interface_hold_down_time: 30
|
source_interface_hold_down_time: 30
|
||||||
|
global_ingress_replication_bgp: "{{ global_ingress_replication_bgp|default(omit) }}"
|
||||||
|
global_suppress_arp: "{{ global_suppress_arp|default(omit) }}"
|
||||||
|
global_mcast_group_L3: "{{ global_mcast_group_L3|default(omit) }}"
|
||||||
shutdown: false
|
shutdown: false
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
register: result
|
register: result
|
||||||
|
@ -46,6 +74,9 @@
|
||||||
host_reachability: false
|
host_reachability: false
|
||||||
source_interface_hold_down_time: default
|
source_interface_hold_down_time: default
|
||||||
source_interface: default
|
source_interface: default
|
||||||
|
global_ingress_replication_bgp: "{{ def_global_ingress_replication_bgp|default(omit) }}"
|
||||||
|
global_suppress_arp: "{{ def_global_suppress_arp|default(omit) }}"
|
||||||
|
global_mcast_group_L3: "{{ def_global_mcast_group_L3|default(omit) }}"
|
||||||
shutdown: true
|
shutdown: true
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
register: result
|
register: result
|
||||||
|
@ -58,6 +89,38 @@
|
||||||
|
|
||||||
- assert: *false
|
- assert: *false
|
||||||
|
|
||||||
|
- name: configure global mcast L2
|
||||||
|
nxos_vxlan_vtep: &gml2
|
||||||
|
interface: nve1
|
||||||
|
host_reachability: true
|
||||||
|
global_mcast_group_L2: "{{ global_mcast_group_L2|default(omit) }}"
|
||||||
|
provider: "{{ connection }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert: *true
|
||||||
|
|
||||||
|
- name: "Conf Idempotence"
|
||||||
|
nxos_vxlan_vtep: *gml2
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert: *false
|
||||||
|
|
||||||
|
- name: reset global mcast L2
|
||||||
|
nxos_vxlan_vtep: &rgml2
|
||||||
|
interface: nve1
|
||||||
|
host_reachability: false
|
||||||
|
global_mcast_group_L2: "{{ def_global_mcast_group_L2|default(omit) }}"
|
||||||
|
provider: "{{ connection }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert: *true
|
||||||
|
|
||||||
|
- name: "reset Idempotence"
|
||||||
|
nxos_vxlan_vtep: *rgml2
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert: *false
|
||||||
|
|
||||||
when: (platform is search('N9K'))
|
when: (platform is search('N9K'))
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
|
@ -134,6 +197,14 @@
|
||||||
include: targets/nxos_vxlan_vtep/tasks/platform/n7k/cleanup.yaml
|
include: targets/nxos_vxlan_vtep/tasks/platform/n7k/cleanup.yaml
|
||||||
when: platform is match('N7K')
|
when: platform is match('N7K')
|
||||||
|
|
||||||
|
- name: "Disable nv overlay evpn"
|
||||||
|
nxos_config:
|
||||||
|
commands:
|
||||||
|
- no nv overlay evpn
|
||||||
|
match: none
|
||||||
|
provider: "{{ connection }}"
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: "Disable feature nv overlay"
|
- name: "Disable feature nv overlay"
|
||||||
nxos_feature:
|
nxos_feature:
|
||||||
feature: nve
|
feature: nve
|
||||||
|
|
|
@ -48,7 +48,7 @@ class TestNxosVxlanVtepVniModule(TestNxosModule):
|
||||||
|
|
||||||
def test_nxos_vxlan_vtep(self):
|
def test_nxos_vxlan_vtep(self):
|
||||||
set_module_args(dict(interface='nve1', description='simple description'))
|
set_module_args(dict(interface='nve1', description='simple description'))
|
||||||
self.execute_module(changed=True, commands=['interface nve1', 'description simple description'])
|
self.execute_module(changed=True, commands=['interface nve1', 'terminal dont-ask', 'description simple description'])
|
||||||
|
|
||||||
def test_nxos_vxlan_vtep_present_no_change(self):
|
def test_nxos_vxlan_vtep_present_no_change(self):
|
||||||
set_module_args(dict(interface='nve1'))
|
set_module_args(dict(interface='nve1'))
|
||||||
|
|
Loading…
Reference in a new issue