nxos_ospf_vrf: Add 'bfd' support (#57425)
* nxos_ospf_vrf: Add 'bfd' support * Add default to bfd doc hdr * bfd T/F now bfd enable/disable
This commit is contained in:
parent
30830a4482
commit
727a6b405a
3 changed files with 97 additions and 10 deletions
|
@ -90,6 +90,13 @@ options:
|
||||||
description:
|
description:
|
||||||
- Specifies the reference bandwidth used to assign OSPF cost.
|
- Specifies the reference bandwidth used to assign OSPF cost.
|
||||||
Valid values are an integer, in Mbps, or the keyword 'default'.
|
Valid values are an integer, in Mbps, or the keyword 'default'.
|
||||||
|
bfd:
|
||||||
|
description:
|
||||||
|
- Enables BFD on all OSPF interfaces.
|
||||||
|
- "Dependency: 'feature bfd'"
|
||||||
|
version_added: "2.9"
|
||||||
|
type: str
|
||||||
|
choices: ['enable', 'disable']
|
||||||
passive_interface:
|
passive_interface:
|
||||||
description:
|
description:
|
||||||
- Setting to C(yes) will suppress routing update on interface.
|
- Setting to C(yes) will suppress routing update on interface.
|
||||||
|
@ -112,6 +119,7 @@ EXAMPLES = '''
|
||||||
timer_throttle_lsa_hold: 1100
|
timer_throttle_lsa_hold: 1100
|
||||||
timer_throttle_lsa_max: 3000
|
timer_throttle_lsa_max: 3000
|
||||||
vrf: test
|
vrf: test
|
||||||
|
bfd: enable
|
||||||
state: present
|
state: present
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -120,8 +128,11 @@ commands:
|
||||||
description: commands sent to the device
|
description: commands sent to the device
|
||||||
returned: always
|
returned: always
|
||||||
type: list
|
type: list
|
||||||
sample: ["router ospf 1", "vrf test", "timers throttle lsa 60 1100 3000",
|
sample:
|
||||||
"ospf 1", "timers throttle spf 50 1000 2000", "vrf test"]
|
- router ospf 1
|
||||||
|
- vrf test
|
||||||
|
- bfd
|
||||||
|
- timers throttle lsa 60 1100 3000
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -146,6 +157,7 @@ PARAM_TO_COMMAND_KEYMAP = {
|
||||||
'timer_throttle_spf_start': 'timers throttle spf',
|
'timer_throttle_spf_start': 'timers throttle spf',
|
||||||
'timer_throttle_spf_hold': 'timers throttle spf',
|
'timer_throttle_spf_hold': 'timers throttle spf',
|
||||||
'auto_cost': 'auto-cost reference-bandwidth',
|
'auto_cost': 'auto-cost reference-bandwidth',
|
||||||
|
'bfd': 'bfd',
|
||||||
'passive_interface': 'passive-interface default'
|
'passive_interface': 'passive-interface default'
|
||||||
}
|
}
|
||||||
PARAM_TO_DEFAULT_KEYMAP = {
|
PARAM_TO_DEFAULT_KEYMAP = {
|
||||||
|
@ -156,6 +168,7 @@ PARAM_TO_DEFAULT_KEYMAP = {
|
||||||
'timer_throttle_spf_max': '5000',
|
'timer_throttle_spf_max': '5000',
|
||||||
'timer_throttle_spf_hold': '1000',
|
'timer_throttle_spf_hold': '1000',
|
||||||
'auto_cost': '40000',
|
'auto_cost': '40000',
|
||||||
|
'bfd': 'disable',
|
||||||
'default_metric': '',
|
'default_metric': '',
|
||||||
'passive_interface': False,
|
'passive_interface': False,
|
||||||
'router_id': '',
|
'router_id': '',
|
||||||
|
@ -206,6 +219,8 @@ def get_existing(module, args):
|
||||||
if 'Gbps' in line:
|
if 'Gbps' in line:
|
||||||
cost = int(cost) * 1000
|
cost = int(cost) * 1000
|
||||||
existing['auto_cost'] = str(cost)
|
existing['auto_cost'] = str(cost)
|
||||||
|
elif 'bfd' in line:
|
||||||
|
existing['bfd'] = 'enable'
|
||||||
elif 'timers throttle lsa' in line:
|
elif 'timers throttle lsa' in line:
|
||||||
tmp = re.search(r'timers throttle lsa (\S+) (\S+) (\S+)', line)
|
tmp = re.search(r'timers throttle lsa (\S+) (\S+) (\S+)', line)
|
||||||
existing['timer_throttle_lsa_start'] = tmp.group(1)
|
existing['timer_throttle_lsa_start'] = tmp.group(1)
|
||||||
|
@ -244,6 +259,8 @@ def state_present(module, existing, proposed, candidate):
|
||||||
existing_commands = apply_key_map(PARAM_TO_COMMAND_KEYMAP, existing)
|
existing_commands = apply_key_map(PARAM_TO_COMMAND_KEYMAP, existing)
|
||||||
|
|
||||||
for key, value in proposed_commands.items():
|
for key, value in proposed_commands.items():
|
||||||
|
if key == 'vrf':
|
||||||
|
continue
|
||||||
if value is True:
|
if value is True:
|
||||||
commands.append(key)
|
commands.append(key)
|
||||||
|
|
||||||
|
@ -284,6 +301,8 @@ def state_present(module, existing, proposed, candidate):
|
||||||
else:
|
else:
|
||||||
value = str(int(value) / 1000)
|
value = str(int(value) / 1000)
|
||||||
command = '{0} {1} Gbps'.format(key, value)
|
command = '{0} {1} Gbps'.format(key, value)
|
||||||
|
elif key == 'bfd':
|
||||||
|
command = 'no bfd' if value == 'disable' else 'bfd'
|
||||||
else:
|
else:
|
||||||
command = '{0} {1}'.format(key, value.lower())
|
command = '{0} {1}'.format(key, value.lower())
|
||||||
|
|
||||||
|
@ -304,6 +323,7 @@ def state_absent(module, existing, proposed, candidate):
|
||||||
existing_commands = apply_key_map(PARAM_TO_COMMAND_KEYMAP, existing)
|
existing_commands = apply_key_map(PARAM_TO_COMMAND_KEYMAP, existing)
|
||||||
for key, value in existing_commands.items():
|
for key, value in existing_commands.items():
|
||||||
if value and key != 'vrf':
|
if value and key != 'vrf':
|
||||||
|
command = None
|
||||||
if key == 'passive-interface default':
|
if key == 'passive-interface default':
|
||||||
command = 'no {0}'.format(key)
|
command = 'no {0}'.format(key)
|
||||||
elif key == 'timers throttle lsa':
|
elif key == 'timers throttle lsa':
|
||||||
|
@ -337,6 +357,9 @@ def state_absent(module, existing, proposed, candidate):
|
||||||
command = 'no {0}'.format(key)
|
command = 'no {0}'.format(key)
|
||||||
else:
|
else:
|
||||||
command = None
|
command = None
|
||||||
|
elif key == 'bfd':
|
||||||
|
if value == 'enable':
|
||||||
|
command = 'no bfd'
|
||||||
else:
|
else:
|
||||||
existing_value = existing_commands.get(key)
|
existing_value = existing_commands.get(key)
|
||||||
command = 'no {0} {1}'.format(key, existing_value)
|
command = 'no {0} {1}'.format(key, existing_value)
|
||||||
|
@ -367,6 +390,7 @@ def main():
|
||||||
timer_throttle_spf_hold=dict(required=False, type='str'),
|
timer_throttle_spf_hold=dict(required=False, type='str'),
|
||||||
timer_throttle_spf_max=dict(required=False, type='str'),
|
timer_throttle_spf_max=dict(required=False, type='str'),
|
||||||
auto_cost=dict(required=False, type='str'),
|
auto_cost=dict(required=False, type='str'),
|
||||||
|
bfd=dict(required=False, type='str', choices=['enable', 'disable']),
|
||||||
passive_interface=dict(required=False, type='bool'),
|
passive_interface=dict(required=False, type='bool'),
|
||||||
state=dict(choices=['present', 'absent'], default='present', required=False)
|
state=dict(choices=['present', 'absent'], default='present', required=False)
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,19 +7,20 @@
|
||||||
# CSCvi74876 Cannot remove default-metric
|
# CSCvi74876 Cannot remove default-metric
|
||||||
when: imagetag is not search("I7")
|
when: imagetag is not search("I7")
|
||||||
|
|
||||||
- name: "Setup: disable feature OSPF for initial cleanup"
|
- name: "Setup: disable features for initial cleanup"
|
||||||
nxos_feature:
|
nxos_feature:
|
||||||
feature: ospf
|
feature: "{{ item }}"
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
state: disabled
|
state: disabled
|
||||||
|
loop: ['ospf', 'bfd']
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: "Enable feature OSPF"
|
- name: "Enable features"
|
||||||
nxos_feature:
|
nxos_feature:
|
||||||
feature: ospf
|
feature: "{{ item }}"
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
state: enabled
|
state: enabled
|
||||||
ignore_errors: yes
|
loop: ['ospf', 'bfd']
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: Configure ospf vrf
|
- name: Configure ospf vrf
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
timer_throttle_lsa_hold: 1100
|
timer_throttle_lsa_hold: 1100
|
||||||
timer_throttle_lsa_max: 3000
|
timer_throttle_lsa_max: 3000
|
||||||
vrf: test
|
vrf: test
|
||||||
|
bfd: enable
|
||||||
passive_interface: true
|
passive_interface: true
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
state: present
|
state: present
|
||||||
|
@ -60,6 +62,7 @@
|
||||||
default_metric: 1000
|
default_metric: 1000
|
||||||
log_adjacency: log
|
log_adjacency: log
|
||||||
vrf: default
|
vrf: default
|
||||||
|
bfd: disable
|
||||||
passive_interface: true
|
passive_interface: true
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
state: present
|
state: present
|
||||||
|
@ -129,11 +132,12 @@
|
||||||
when: def_met_default is defined
|
when: def_met_default is defined
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: "Disable feature OSPF"
|
- name: "Disable features"
|
||||||
nxos_feature:
|
nxos_feature:
|
||||||
feature: ospf
|
feature: "{{ item }}"
|
||||||
provider: "{{ connection }}"
|
provider: "{{ connection }}"
|
||||||
state: disabled
|
state: disabled
|
||||||
|
loop: ['ospf', 'bfd']
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
|
||||||
- debug: msg="END connection={{ ansible_connection }} nxos_ospf_vrf sanity test"
|
- debug: msg="END connection={{ ansible_connection }} nxos_ospf_vrf sanity test"
|
||||||
|
|
|
@ -54,6 +54,7 @@ class TestNxosOspfVrfModule(TestNxosModule):
|
||||||
timer_throttle_lsa_start=60,
|
timer_throttle_lsa_start=60,
|
||||||
timer_throttle_lsa_hold=1100,
|
timer_throttle_lsa_hold=1100,
|
||||||
timer_throttle_lsa_max=3000,
|
timer_throttle_lsa_max=3000,
|
||||||
|
bfd='enable',
|
||||||
state='present'))
|
state='present'))
|
||||||
result = self.execute_module(changed=True)
|
result = self.execute_module(changed=True)
|
||||||
self.assertEqual(sorted(result['commands']),
|
self.assertEqual(sorted(result['commands']),
|
||||||
|
@ -61,9 +62,67 @@ class TestNxosOspfVrfModule(TestNxosModule):
|
||||||
'vrf test',
|
'vrf test',
|
||||||
'timers throttle lsa 60 1100 3000',
|
'timers throttle lsa 60 1100 3000',
|
||||||
'timers throttle spf 50 1000 2000',
|
'timers throttle spf 50 1000 2000',
|
||||||
'vrf test']))
|
'bfd',
|
||||||
|
]))
|
||||||
|
|
||||||
def test_nxos_ospf_vrf_absent(self):
|
def test_nxos_ospf_vrf_absent(self):
|
||||||
set_module_args(dict(ospf=1, vrf='test', state='absent'))
|
set_module_args(dict(ospf=1, vrf='test', state='absent'))
|
||||||
result = self.execute_module(changed=False)
|
result = self.execute_module(changed=False)
|
||||||
self.assertEqual(result['commands'], [])
|
self.assertEqual(result['commands'], [])
|
||||||
|
|
||||||
|
def test_bfd_1(self):
|
||||||
|
self.get_config.return_value = 'router ospf 1\n bfd\nrouter ospf 2'
|
||||||
|
# enable -> disable
|
||||||
|
set_module_args(dict(
|
||||||
|
ospf=1,
|
||||||
|
bfd='disable',
|
||||||
|
))
|
||||||
|
self.execute_module(changed=True, commands=[
|
||||||
|
'router ospf 1',
|
||||||
|
'no bfd',
|
||||||
|
])
|
||||||
|
|
||||||
|
# disable -> enable
|
||||||
|
set_module_args(dict(
|
||||||
|
ospf=2,
|
||||||
|
bfd='enable',
|
||||||
|
))
|
||||||
|
self.execute_module(changed=True, commands=[
|
||||||
|
'router ospf 2',
|
||||||
|
'bfd',
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_bfd_2(self):
|
||||||
|
# enable idempotence
|
||||||
|
self.get_config.return_value = 'router ospf 1\n bfd\nrouter ospf 2'
|
||||||
|
set_module_args(dict(
|
||||||
|
ospf=1,
|
||||||
|
bfd='enable',
|
||||||
|
))
|
||||||
|
self.execute_module(changed=False)
|
||||||
|
|
||||||
|
# disable idempotence
|
||||||
|
set_module_args(dict(
|
||||||
|
ospf=2,
|
||||||
|
bfd='disable',
|
||||||
|
))
|
||||||
|
self.execute_module(changed=False)
|
||||||
|
|
||||||
|
def test_bfd_3(self):
|
||||||
|
# absent tests
|
||||||
|
self.get_config.return_value = 'router ospf 1\n bfd\nrouter ospf 2'
|
||||||
|
set_module_args(dict(
|
||||||
|
ospf=1,
|
||||||
|
state='absent'
|
||||||
|
))
|
||||||
|
self.execute_module(changed=True, commands=[
|
||||||
|
'router ospf 1',
|
||||||
|
'no bfd',
|
||||||
|
])
|
||||||
|
|
||||||
|
# absent w/bfd disable
|
||||||
|
set_module_args(dict(
|
||||||
|
ospf=2,
|
||||||
|
state='absent'
|
||||||
|
))
|
||||||
|
self.execute_module(changed=False)
|
||||||
|
|
Loading…
Reference in a new issue