nxos_pim: Add bfd support (#56908)
* nxos_pim: Add bfd support * Add integration sanity * minor cleanup * bfd T/F now bfd enable/disable
This commit is contained in:
parent
12d656901f
commit
30830a4482
4 changed files with 139 additions and 48 deletions
|
@ -31,6 +31,14 @@ description:
|
|||
- Manages configuration of a Protocol Independent Multicast (PIM) instance.
|
||||
author: Gabriele Gerbino (@GGabriele)
|
||||
options:
|
||||
bfd:
|
||||
description:
|
||||
- Enables BFD on all PIM interfaces.
|
||||
- "Dependency: 'feature bfd'"
|
||||
version_added: "2.9"
|
||||
type: str
|
||||
choices: ['enable', 'disable']
|
||||
|
||||
ssm_range:
|
||||
description:
|
||||
- Configure group ranges for Source Specific Multicast (SSM).
|
||||
|
@ -42,8 +50,9 @@ options:
|
|||
required: true
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
- name: Configure ssm_range
|
||||
- name: Configure ssm_range, enable bfd
|
||||
nxos_pim:
|
||||
bfd: enable
|
||||
ssm_range: "224.0.0.0/8"
|
||||
|
||||
- name: Set to default
|
||||
|
@ -60,7 +69,9 @@ commands:
|
|||
description: commands sent to the device
|
||||
returned: always
|
||||
type: list
|
||||
sample: ["ip pim ssm range 224.0.0.0/8"]
|
||||
sample:
|
||||
- ip pim bfd
|
||||
- ip pim ssm range 224.0.0.0/8
|
||||
'''
|
||||
|
||||
|
||||
|
@ -73,7 +84,8 @@ from ansible.module_utils.network.common.config import CustomNetworkConfig
|
|||
|
||||
|
||||
PARAM_TO_COMMAND_KEYMAP = {
|
||||
'ssm_range': 'ip pim ssm range'
|
||||
'bfd': 'ip pim bfd',
|
||||
'ssm_range': 'ip pim ssm range',
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,15 +94,17 @@ def get_existing(module, args):
|
|||
config = str(get_config(module))
|
||||
|
||||
for arg in args:
|
||||
command = PARAM_TO_COMMAND_KEYMAP[arg]
|
||||
has_command = re.search(r'^{0}\s(?P<value>.*)$'.format(command), config, re.M)
|
||||
if 'ssm_range' in arg:
|
||||
# <value> may be 'n.n.n.n/s', 'none', or 'default'
|
||||
m = re.search(r'ssm range (?P<value>(?:[\s\d.\/]+|none|default))?$', config, re.M)
|
||||
if m:
|
||||
# Remove rsvd SSM range
|
||||
value = m.group('value').replace('232.0.0.0/8', '')
|
||||
existing[arg] = value.split()
|
||||
|
||||
elif 'bfd' in arg and 'ip pim bfd' in config:
|
||||
existing[arg] = 'enable'
|
||||
|
||||
value = ''
|
||||
if has_command:
|
||||
value = has_command.group('value')
|
||||
if value == '232.0.0.0/8':
|
||||
value = '' # remove the reserved value
|
||||
existing[arg] = value.split()
|
||||
return existing
|
||||
|
||||
|
||||
|
@ -98,7 +112,7 @@ def apply_key_map(key_map, table):
|
|||
new_dict = {}
|
||||
for key, value in table.items():
|
||||
new_key = key_map.get(key)
|
||||
if value:
|
||||
if value is not None:
|
||||
new_dict[new_key] = value
|
||||
return new_dict
|
||||
|
||||
|
@ -108,12 +122,20 @@ def get_commands(module, existing, proposed, candidate):
|
|||
proposed_commands = apply_key_map(PARAM_TO_COMMAND_KEYMAP, proposed)
|
||||
|
||||
for key, value in proposed_commands.items():
|
||||
if key == 'ip pim ssm range' and value == 'default':
|
||||
# no cmd needs a value but the actual value does not matter
|
||||
command = 'no ip pim ssm range none'
|
||||
commands.append(command)
|
||||
else:
|
||||
command = '{0} {1}'.format(key, value)
|
||||
command = ''
|
||||
if key == 'ip pim ssm range':
|
||||
if value == 'default':
|
||||
# no cmd needs a value but the actual value does not matter
|
||||
command = 'no ip pim ssm range none'
|
||||
elif value == 'none':
|
||||
command = 'ip pim ssm range none'
|
||||
elif value:
|
||||
command = 'ip pim ssm range {0}'.format(value)
|
||||
elif key == 'ip pim bfd':
|
||||
no_cmd = 'no ' if value == 'disable' else ''
|
||||
command = no_cmd + key
|
||||
|
||||
if command:
|
||||
commands.append(command)
|
||||
|
||||
if commands:
|
||||
|
@ -122,42 +144,52 @@ def get_commands(module, existing, proposed, candidate):
|
|||
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
ssm_range=dict(required=True, type='list'),
|
||||
bfd=dict(required=False, type='str', choices=['enable', 'disable']),
|
||||
ssm_range=dict(required=False, type='list', default=[]),
|
||||
)
|
||||
|
||||
argument_spec.update(nxos_argument_spec)
|
||||
|
||||
module = AnsibleModule(argument_spec=argument_spec,
|
||||
supports_check_mode=True)
|
||||
|
||||
warnings = list()
|
||||
check_args(module, warnings)
|
||||
result = {'changed': False, 'commands': [], 'warnings': warnings}
|
||||
|
||||
ssm_range_list = module.params['ssm_range']
|
||||
for item in ssm_range_list:
|
||||
splitted_ssm_range = item.split('.')
|
||||
if len(splitted_ssm_range) != 4 and item != 'none' and item != 'default':
|
||||
module.fail_json(msg="Valid ssm_range values are multicast addresses "
|
||||
"or the keyword 'none' or the keyword 'default'.")
|
||||
params = module.params
|
||||
args = [k for k in PARAM_TO_COMMAND_KEYMAP.keys() if params[k] is not None]
|
||||
|
||||
args = PARAM_TO_COMMAND_KEYMAP.keys()
|
||||
# SSM syntax check
|
||||
if 'ssm_range' in args:
|
||||
for item in params['ssm_range']:
|
||||
if re.search('none|default', item):
|
||||
break
|
||||
if len(item.split('.')) != 4:
|
||||
module.fail_json(msg="Valid ssm_range values are multicast addresses "
|
||||
"or the keyword 'none' or the keyword 'default'.")
|
||||
|
||||
existing = get_existing(module, args)
|
||||
proposed_args = dict((k, v) for k, v in module.params.items() if k in args)
|
||||
proposed_args = dict((k, v) for k, v in params.items() if k in args)
|
||||
|
||||
proposed = {}
|
||||
for key, value in proposed_args.items():
|
||||
if key == 'ssm_range':
|
||||
if value[0] == 'default':
|
||||
if value and value[0] == 'default':
|
||||
if existing.get(key):
|
||||
proposed[key] = 'default'
|
||||
else:
|
||||
v = sorted(set([str(i) for i in value]))
|
||||
ex = sorted(set([str(i) for i in existing.get(key)]))
|
||||
ex = sorted(set([str(i) for i in existing.get(key, [])]))
|
||||
if v != ex:
|
||||
proposed[key] = ' '.join(str(s) for s in v)
|
||||
|
||||
elif key == 'bfd':
|
||||
if value != existing.get('bfd', 'disable'):
|
||||
proposed[key] = value
|
||||
|
||||
elif value != existing.get(key):
|
||||
proposed[key] = value
|
||||
|
||||
candidate = CustomNetworkConfig(indent=3)
|
||||
get_commands(module, existing, proposed, candidate)
|
||||
|
||||
|
|
|
@ -3,17 +3,24 @@
|
|||
- debug: msg="Using provider={{ connection.transport }}"
|
||||
when: ansible_connection == "local"
|
||||
|
||||
- name: "Setup: Disable feature PIM"
|
||||
- name: "Setup: Disable features"
|
||||
nxos_feature: &disable_feature
|
||||
feature: pim
|
||||
feature: "{{ item }}"
|
||||
provider: "{{ connection }}"
|
||||
state: disabled
|
||||
ignore_errors: yes
|
||||
loop:
|
||||
- pim
|
||||
- bfd
|
||||
|
||||
- name: "Setup: Enable feature PIM"
|
||||
- name: "Setup: Enable features"
|
||||
nxos_feature:
|
||||
feature: pim
|
||||
feature: "{{ item }}"
|
||||
provider: "{{ connection }}"
|
||||
state: enabled
|
||||
loop:
|
||||
- pim
|
||||
- bfd
|
||||
|
||||
- name: "Setup: Configure ssm_range none"
|
||||
nxos_pim: &none
|
||||
|
@ -21,9 +28,10 @@
|
|||
provider: "{{ connection }}"
|
||||
|
||||
- block:
|
||||
- name: Configure ssm_range
|
||||
- name: Initial config from none
|
||||
nxos_pim: &configure
|
||||
ssm_range:
|
||||
bfd: enable
|
||||
ssm_range:
|
||||
- "239.128.1.0/24"
|
||||
- "224.0.0.0/8"
|
||||
provider: "{{ connection }}"
|
||||
|
@ -33,7 +41,7 @@
|
|||
that:
|
||||
- "result.changed == true"
|
||||
|
||||
- name: Check idempotence
|
||||
- name: Initial config idempotence
|
||||
nxos_pim: *configure
|
||||
register: result
|
||||
|
||||
|
@ -43,13 +51,14 @@
|
|||
|
||||
- name: Configure ssm_range default
|
||||
nxos_pim: &conf_default
|
||||
bfd: disable
|
||||
ssm_range: "default"
|
||||
provider: "{{ connection }}"
|
||||
register: result
|
||||
|
||||
- assert: *true
|
||||
|
||||
- name: Check idempotence
|
||||
- name: ssm_range default idempotence
|
||||
nxos_pim: *conf_default
|
||||
register: result
|
||||
|
||||
|
@ -61,14 +70,22 @@
|
|||
|
||||
- assert: *true
|
||||
|
||||
- name: Check idempotence
|
||||
- meta: end_play
|
||||
- name: ssm_range none idempotence
|
||||
nxos_pim: *none
|
||||
register: result
|
||||
|
||||
- assert: *false
|
||||
|
||||
always:
|
||||
- name: "Disable feature PIM"
|
||||
nxos_feature: *disable_feature
|
||||
- name: "Teardown: Disable features"
|
||||
nxos_feature:
|
||||
feature: "{{ item }}"
|
||||
provider: "{{ connection }}"
|
||||
state: disabled
|
||||
ignore_errors: yes
|
||||
loop:
|
||||
- pim
|
||||
- bfd
|
||||
|
||||
- debug: msg="END connection={{ ansible_connection }} nxos_pim sanity test"
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
ip pim bfd
|
||||
ip pim ssm range 127.0.0.0/31
|
||||
|
|
|
@ -43,17 +43,58 @@ class TestNxosPimModule(TestNxosModule):
|
|||
self.mock_load_config.stop()
|
||||
|
||||
def load_fixtures(self, commands=None, device=''):
|
||||
self.get_config.return_value = load_fixture('nxos_pim', 'config.cfg')
|
||||
self.load_config.return_value = None
|
||||
|
||||
def test_nxos_pim(self):
|
||||
set_module_args(dict(ssm_range='232.0.0.0/8'))
|
||||
self.execute_module(changed=True, commands=['ip pim ssm range 232.0.0.0/8'])
|
||||
def test_nxos_pim_1(self):
|
||||
# Add/ Modify
|
||||
self.get_config.return_value = load_fixture('nxos_pim', 'config.cfg')
|
||||
set_module_args(dict(ssm_range='233.0.0.0/8'))
|
||||
self.execute_module(changed=True, commands=[
|
||||
'ip pim ssm range 233.0.0.0/8',
|
||||
])
|
||||
|
||||
def test_nxos_pim_none(self):
|
||||
def test_nxos_pim_2(self):
|
||||
# Remove existing values
|
||||
self.get_config.return_value = load_fixture('nxos_pim', 'config.cfg')
|
||||
set_module_args(dict(bfd='disable', ssm_range='none'))
|
||||
self.execute_module(changed=True, commands=[
|
||||
'no ip pim bfd',
|
||||
'ip pim ssm range none',
|
||||
])
|
||||
|
||||
def test_nxos_pim_3(self):
|
||||
# bfd None (disable)-> enable
|
||||
self.get_config.return_value = None
|
||||
set_module_args(dict(bfd='enable'))
|
||||
self.execute_module(changed=True, commands=['ip pim bfd'])
|
||||
|
||||
# bfd None (disable) -> disable
|
||||
set_module_args(dict(bfd='disable'))
|
||||
self.execute_module(changed=False)
|
||||
|
||||
# ssm None to 'default'
|
||||
set_module_args(dict(ssm_range='default'))
|
||||
self.execute_module(changed=False)
|
||||
|
||||
def test_nxos_pim_4(self):
|
||||
# SSM 'none'
|
||||
self.get_config.return_value = load_fixture('nxos_pim', 'config.cfg')
|
||||
set_module_args(dict(ssm_range='none'))
|
||||
self.execute_module(changed=True, commands=['ip pim ssm range none'])
|
||||
|
||||
def test_nxos_pim_no_change(self):
|
||||
set_module_args(dict(ssm_range='127.0.0.0/31'))
|
||||
def test_nxos_pim_5(self):
|
||||
# SSM 'default'
|
||||
self.get_config.return_value = load_fixture('nxos_pim', 'config.cfg')
|
||||
set_module_args(dict(ssm_range='default'))
|
||||
self.execute_module(changed=True, commands=['no ip pim ssm range none'])
|
||||
|
||||
# SSM 'default' idempotence
|
||||
self.get_config.return_value = None
|
||||
set_module_args(dict(ssm_range='default'))
|
||||
self.execute_module(changed=False)
|
||||
|
||||
def test_nxos_pim_6(self):
|
||||
# Idempotence
|
||||
self.get_config.return_value = load_fixture('nxos_pim', 'config.cfg')
|
||||
set_module_args(dict(bfd='enable', ssm_range='127.0.0.0/31'))
|
||||
self.execute_module(changed=False, commands=[])
|
||||
|
|
Loading…
Reference in a new issue