diff --git a/lib/ansible/modules/network/nxos/nxos_ospf_vrf.py b/lib/ansible/modules/network/nxos/nxos_ospf_vrf.py index fbc9e752d60..60a3e6348dc 100644 --- a/lib/ansible/modules/network/nxos/nxos_ospf_vrf.py +++ b/lib/ansible/modules/network/nxos/nxos_ospf_vrf.py @@ -90,6 +90,13 @@ options: description: - Specifies the reference bandwidth used to assign OSPF cost. 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: description: - Setting to C(yes) will suppress routing update on interface. @@ -112,6 +119,7 @@ EXAMPLES = ''' timer_throttle_lsa_hold: 1100 timer_throttle_lsa_max: 3000 vrf: test + bfd: enable state: present ''' @@ -120,8 +128,11 @@ commands: description: commands sent to the device returned: always type: list - sample: ["router ospf 1", "vrf test", "timers throttle lsa 60 1100 3000", - "ospf 1", "timers throttle spf 50 1000 2000", "vrf test"] + sample: + - router ospf 1 + - vrf test + - bfd + - timers throttle lsa 60 1100 3000 ''' import re @@ -146,6 +157,7 @@ PARAM_TO_COMMAND_KEYMAP = { 'timer_throttle_spf_start': 'timers throttle spf', 'timer_throttle_spf_hold': 'timers throttle spf', 'auto_cost': 'auto-cost reference-bandwidth', + 'bfd': 'bfd', 'passive_interface': 'passive-interface default' } PARAM_TO_DEFAULT_KEYMAP = { @@ -156,6 +168,7 @@ PARAM_TO_DEFAULT_KEYMAP = { 'timer_throttle_spf_max': '5000', 'timer_throttle_spf_hold': '1000', 'auto_cost': '40000', + 'bfd': 'disable', 'default_metric': '', 'passive_interface': False, 'router_id': '', @@ -206,6 +219,8 @@ def get_existing(module, args): if 'Gbps' in line: cost = int(cost) * 1000 existing['auto_cost'] = str(cost) + elif 'bfd' in line: + existing['bfd'] = 'enable' elif 'timers throttle lsa' in line: tmp = re.search(r'timers throttle lsa (\S+) (\S+) (\S+)', line) 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) for key, value in proposed_commands.items(): + if key == 'vrf': + continue if value is True: commands.append(key) @@ -284,6 +301,8 @@ def state_present(module, existing, proposed, candidate): else: value = str(int(value) / 1000) command = '{0} {1} Gbps'.format(key, value) + elif key == 'bfd': + command = 'no bfd' if value == 'disable' else 'bfd' else: 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) for key, value in existing_commands.items(): if value and key != 'vrf': + command = None if key == 'passive-interface default': command = 'no {0}'.format(key) elif key == 'timers throttle lsa': @@ -337,6 +357,9 @@ def state_absent(module, existing, proposed, candidate): command = 'no {0}'.format(key) else: command = None + elif key == 'bfd': + if value == 'enable': + command = 'no bfd' else: existing_value = existing_commands.get(key) 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_max=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'), state=dict(choices=['present', 'absent'], default='present', required=False) ) diff --git a/test/integration/targets/nxos_ospf_vrf/tests/common/sanity.yaml b/test/integration/targets/nxos_ospf_vrf/tests/common/sanity.yaml index 423de8b89f4..5cf9ca6d56d 100644 --- a/test/integration/targets/nxos_ospf_vrf/tests/common/sanity.yaml +++ b/test/integration/targets/nxos_ospf_vrf/tests/common/sanity.yaml @@ -7,19 +7,20 @@ # CSCvi74876 Cannot remove default-metric when: imagetag is not search("I7") -- name: "Setup: disable feature OSPF for initial cleanup" +- name: "Setup: disable features for initial cleanup" nxos_feature: - feature: ospf + feature: "{{ item }}" provider: "{{ connection }}" state: disabled + loop: ['ospf', 'bfd'] ignore_errors: yes -- name: "Enable feature OSPF" +- name: "Enable features" nxos_feature: - feature: ospf + feature: "{{ item }}" provider: "{{ connection }}" state: enabled - ignore_errors: yes + loop: ['ospf', 'bfd'] - block: - name: Configure ospf vrf @@ -33,6 +34,7 @@ timer_throttle_lsa_hold: 1100 timer_throttle_lsa_max: 3000 vrf: test + bfd: enable passive_interface: true provider: "{{ connection }}" state: present @@ -60,6 +62,7 @@ default_metric: 1000 log_adjacency: log vrf: default + bfd: disable passive_interface: true provider: "{{ connection }}" state: present @@ -129,11 +132,12 @@ when: def_met_default is defined always: - - name: "Disable feature OSPF" + - name: "Disable features" nxos_feature: - feature: ospf + feature: "{{ item }}" provider: "{{ connection }}" state: disabled + loop: ['ospf', 'bfd'] ignore_errors: yes - debug: msg="END connection={{ ansible_connection }} nxos_ospf_vrf sanity test" diff --git a/test/units/modules/network/nxos/test_nxos_ospf_vrf.py b/test/units/modules/network/nxos/test_nxos_ospf_vrf.py index d907488b2c9..165d1274379 100644 --- a/test/units/modules/network/nxos/test_nxos_ospf_vrf.py +++ b/test/units/modules/network/nxos/test_nxos_ospf_vrf.py @@ -54,6 +54,7 @@ class TestNxosOspfVrfModule(TestNxosModule): timer_throttle_lsa_start=60, timer_throttle_lsa_hold=1100, timer_throttle_lsa_max=3000, + bfd='enable', state='present')) result = self.execute_module(changed=True) self.assertEqual(sorted(result['commands']), @@ -61,9 +62,67 @@ class TestNxosOspfVrfModule(TestNxosModule): 'vrf test', 'timers throttle lsa 60 1100 3000', 'timers throttle spf 50 1000 2000', - 'vrf test'])) + 'bfd', + ])) def test_nxos_ospf_vrf_absent(self): set_module_args(dict(ospf=1, vrf='test', state='absent')) result = self.execute_module(changed=False) 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)