nxos_interfaces_ospf: fix passive-interface states & check_mode (#54260)
* nxos_interfaces_ospf: fix passive-interface states & check_mode
This fix addresses issues #41704 and #45343.
The crux of the problem is that `passive-interface` should have been treated as a tri-state value instead of a boolean.
The `no` form of the command disables the passive state on an interface (allows it to form adjacencies and send routing updates). It's essentially an override for `passive-interface default` which enables passive state on all OSPF interfaces.\*
This `no` config will be present in `running-config`.
\**See `router ospf` configuration.*
Since both enable and disable states are explicit configs, the proper way to remove either of these is with the `default` syntax.
Passive-interface config syntax:
```
ip ospf passive-interface # enable (nvgens)
no ip ospf passive-interface # disable (nvgens)
default ip ospf passive-interface # default (removes config, does not nvgen)
```
Code changes:
* `passive_interface` param changed from boolean to string, restricted to `true`,`false`,`default`.
* Several passive-interface specific checks were added because the existing module logic tends to test for true or false and doesn't handle the None case.
* Fixed `check_mode`.
Sanity verified on: N9K,N7K,N3K,N6K
* Fix doc header
* Unit tests for passive-interface
* doc fix #2
* Fix indent for SA
* Remove 'default' keyword, restore bool behavior
* remove changes to sanity
(cherry picked from commit 20fb77c49b
)
This commit is contained in:
parent
a8f5619786
commit
57607ffcd2
3 changed files with 60 additions and 7 deletions
|
@ -66,8 +66,10 @@ options:
|
|||
integer or the keyword 'default'.
|
||||
passive_interface:
|
||||
description:
|
||||
- Setting to true will prevent this interface from receiving
|
||||
HELLO packets.
|
||||
- Enable or disable passive-interface state on this interface.
|
||||
true - (enable) Prevent OSPF from establishing an adjacency or
|
||||
sending routing updates on this interface.
|
||||
false - (disable) Override global 'passive-interface default' for this interface.
|
||||
type: bool
|
||||
message_digest:
|
||||
description:
|
||||
|
@ -176,9 +178,12 @@ def get_value(arg, config, module):
|
|||
value = value_list[3]
|
||||
elif arg == 'passive_interface':
|
||||
has_no_command = re.search(r'\s+no\s+{0}\s*$'.format(command), config, re.M)
|
||||
value = False
|
||||
if has_command and not has_no_command:
|
||||
if has_no_command:
|
||||
value = False
|
||||
elif has_command:
|
||||
value = True
|
||||
else:
|
||||
value = None
|
||||
elif arg in BOOL_PARAMS:
|
||||
value = bool(has_command)
|
||||
else:
|
||||
|
@ -235,6 +240,8 @@ def get_default_commands(existing, proposed, existing_commands, key, module):
|
|||
encryption_type,
|
||||
existing['message_digest_password'])
|
||||
commands.append(command)
|
||||
elif 'passive-interface' in key:
|
||||
commands.append('default ip ospf passive-interface')
|
||||
else:
|
||||
commands.append('no {0} {1}'.format(key, existing_value))
|
||||
return commands
|
||||
|
@ -310,6 +317,11 @@ 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 'ip ospf passive-interface' in key:
|
||||
# cli is present for both enabled or disabled; 'no' will not remove
|
||||
commands.append('default ip ospf passive-interface')
|
||||
continue
|
||||
|
||||
if value:
|
||||
if key.startswith('ip ospf message-digest-key'):
|
||||
if 'options' not in key:
|
||||
|
@ -324,8 +336,7 @@ def state_absent(module, existing, proposed, candidate):
|
|||
encryption_type,
|
||||
existing['message_digest_password'])
|
||||
commands.append(command)
|
||||
elif key in ['ip ospf authentication message-digest',
|
||||
'ip ospf passive-interface']:
|
||||
elif key in ['ip ospf authentication message-digest', 'ip ospf network']:
|
||||
if value:
|
||||
commands.append('no {0}'.format(key))
|
||||
elif key == 'ip router ospf':
|
||||
|
@ -415,6 +426,8 @@ def main():
|
|||
value = 'default'
|
||||
if existing.get(key) or (not existing.get(key) and value):
|
||||
proposed[key] = value
|
||||
elif 'passive_interface' in key and existing.get(key) is None and value is False:
|
||||
proposed[key] = value
|
||||
|
||||
proposed['area'] = normalize_area(proposed['area'], module)
|
||||
if 'hello_interval' in proposed and proposed['hello_interval'] == '10':
|
||||
|
@ -428,7 +441,8 @@ def main():
|
|||
|
||||
if candidate:
|
||||
candidate = candidate.items_text()
|
||||
load_config(module, candidate)
|
||||
if not module.check_mode:
|
||||
load_config(module, candidate)
|
||||
result['changed'] = True
|
||||
result['commands'] = candidate
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
interface Ethernet1/33
|
||||
interface Ethernet1/34
|
||||
ip router ospf 1 area 0.0.0.1
|
||||
ip ospf passive-interface
|
||||
interface Ethernet1/35
|
||||
ip router ospf 1 area 0.0.0.1
|
||||
no ip ospf passive-interface
|
|
@ -54,3 +54,35 @@ class TestNxosInterfaceOspfModule(TestNxosModule):
|
|||
def test_loopback_interface_failed(self):
|
||||
set_module_args(dict(interface='loopback0', ospf=1, area=0, passive_interface=True))
|
||||
self.execute_module(failed=True, changed=False)
|
||||
set_module_args(dict(interface='loopback0', ospf=1, area=0, network='broadcast'))
|
||||
self.execute_module(failed=True, changed=False)
|
||||
|
||||
def test_nxos_interface_ospf_passive(self):
|
||||
# default -> True
|
||||
set_module_args(dict(interface='ethernet1/33', ospf=1, area=1, passive_interface=True))
|
||||
self.execute_module(changed=True, commands=['interface Ethernet1/33',
|
||||
'ip router ospf 1 area 0.0.0.1',
|
||||
'ip ospf passive-interface'])
|
||||
# default -> False
|
||||
set_module_args(dict(interface='ethernet1/33', ospf=1, area=1, passive_interface=False))
|
||||
self.execute_module(changed=True, commands=['interface Ethernet1/33',
|
||||
'ip router ospf 1 area 0.0.0.1',
|
||||
'no ip ospf passive-interface'])
|
||||
# True -> False
|
||||
set_module_args(dict(interface='ethernet1/34', ospf=1, area=1, passive_interface=False))
|
||||
self.execute_module(changed=True, commands=['interface Ethernet1/34',
|
||||
'no ip ospf passive-interface'])
|
||||
# True -> default (absent)
|
||||
set_module_args(dict(interface='ethernet1/34', ospf=1, area=1, state='absent'))
|
||||
self.execute_module(changed=True, commands=['interface Ethernet1/34',
|
||||
'no ip router ospf 1 area 0.0.0.1',
|
||||
'default ip ospf passive-interface'])
|
||||
# False -> True
|
||||
set_module_args(dict(interface='ethernet1/35', ospf=1, area=1, passive_interface=True))
|
||||
self.execute_module(changed=True, commands=['interface Ethernet1/35',
|
||||
'ip ospf passive-interface'])
|
||||
# False -> default (absent)
|
||||
set_module_args(dict(interface='ethernet1/35', ospf=1, area=1, state='absent'))
|
||||
self.execute_module(changed=True, commands=['interface Ethernet1/35',
|
||||
'no ip router ospf 1 area 0.0.0.1',
|
||||
'default ip ospf passive-interface'])
|
||||
|
|
Loading…
Reference in a new issue