From 79a4aa7a22e928ab91d071b3371ba916bd597248 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Wed, 29 May 2024 15:01:03 +0530 Subject: [PATCH 01/13] OSPFv2_interfaces - Add Enterprise SONiC resource module --- .../network/sonic/argspec/facts/facts.py | 1 + .../argspec/ospfv2_interfaces/__init__.py | 0 .../ospfv2_interfaces/ospfv2_interfaces.py | 100 ++ .../config/ospfv2_interfaces/__init__.py | 0 .../ospfv2_interfaces/ospfv2_interfaces.py | 773 +++++++++ .../module_utils/network/sonic/facts/facts.py | 2 + .../sonic/facts/ospfv2_interfaces/__init__.py | 0 .../ospfv2_interfaces/ospfv2_interfaces.py | 197 +++ plugins/modules/sonic_facts.py | 1 + plugins/modules/sonic_ospfv2_interfaces.py | 748 +++++++++ .../sonic_ospfv2_interfaces/defaults/main.yml | 368 +++++ .../sonic_ospfv2_interfaces/meta/main.yml | 5 + .../tasks/cleanup_tests.yaml | 31 + .../sonic_ospfv2_interfaces/tasks/main.yml | 17 + .../tasks/preparation_tests.yaml | 32 + .../tasks/tasks_template.yaml | 22 + tests/regression/test.yaml | 1 + .../fixtures/sonic_ospfv2_interfaces.yaml | 1428 +++++++++++++++++ .../sonic/test_sonic_ospfv2_interfaces.py | 96 ++ 19 files changed, 3822 insertions(+) create mode 100644 plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/__init__.py create mode 100644 plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py create mode 100644 plugins/module_utils/network/sonic/config/ospfv2_interfaces/__init__.py create mode 100644 plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py create mode 100644 plugins/module_utils/network/sonic/facts/ospfv2_interfaces/__init__.py create mode 100644 plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py create mode 100644 plugins/modules/sonic_ospfv2_interfaces.py create mode 100644 tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml create mode 100644 tests/regression/roles/sonic_ospfv2_interfaces/meta/main.yml create mode 100644 tests/regression/roles/sonic_ospfv2_interfaces/tasks/cleanup_tests.yaml create mode 100644 tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml create mode 100644 tests/regression/roles/sonic_ospfv2_interfaces/tasks/preparation_tests.yaml create mode 100644 tests/regression/roles/sonic_ospfv2_interfaces/tasks/tasks_template.yaml create mode 100644 tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml create mode 100644 tests/unit/modules/network/sonic/test_sonic_ospfv2_interfaces.py diff --git a/plugins/module_utils/network/sonic/argspec/facts/facts.py b/plugins/module_utils/network/sonic/argspec/facts/facts.py index e63700cc9..a3637fe7b 100644 --- a/plugins/module_utils/network/sonic/argspec/facts/facts.py +++ b/plugins/module_utils/network/sonic/argspec/facts/facts.py @@ -33,6 +33,7 @@ def __init__(self, **kwargs): 'bgp_as_paths', 'bgp_communities', 'bgp_ext_communities', + 'ospfv2_interfaces', 'mclag', 'prefix_lists', 'vlan_mapping', diff --git a/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/__init__.py b/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py new file mode 100644 index 000000000..efba81959 --- /dev/null +++ b/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py @@ -0,0 +1,100 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2024 Dell Inc. or its subsidiaries. All Rights Reserved +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the resource +# module builder playbook. +# +# Do not edit this file manually. +# +# Changes to this file will be over written +# by the resource module builder. +# +# Changes should be made in the model used to +# generate this file or in the resource module +# builder template. +# +############################################# + +""" +The arg spec for the sonic_ospfv2_interfaces module +""" +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +class Ospfv2_interfacesArgs(object): # pylint: disable=R0903 + """The arg spec for the sonic_ospfv2_interfaces module + """ + + def __init__(self, **kwargs): + pass + + argument_spec = { + 'config': { + 'elements': 'dict', + 'options': { + 'bfd': { + 'options': { + 'bfd_profile': {'type': 'str'}, + 'enable': {'required': True, 'type': 'bool'} + }, + 'type': 'dict' + }, + 'name': {'required': True, 'type': 'str'}, + 'network': { + 'choices': ['broadcast', 'point_to_point'], + 'type': 'str' + }, + 'ospf_attributes': { + 'elements': 'dict', + 'mutually_exclusive': [['dead_interval', 'hello_multiplier']], + 'options': { + 'address': {'type': 'str'}, + 'area_id': {'type': 'str'}, + 'auth_pwd': { + 'options': { + 'encrypted': {'type': 'bool'}, + 'pwd': {'no_log': True, 'required': True, 'type': 'str'} + }, + 'type': 'dict' + }, + 'authentication_type': { + 'choices': ['MD5HMAC', 'NONE', 'TEXT'], + 'type': 'str' + }, + 'cost': {'type': 'int'}, + 'dead_interval': {'type': 'int'}, + 'hello_interval': {'type': 'int'}, + 'hello_multiplier': {'type': 'int'}, + 'message_digest_pwd': { + 'elements': 'dict', + 'options': { + 'encrypted': {'type': 'bool'}, + 'key_id': {'required': True, 'type': 'int'}, + 'pwd': {'no_log': True, 'type': 'str'} + }, + 'type': 'list' + }, + 'mtu_ignore': {'type': 'bool'}, + 'priority': {'type': 'int'}, + 'retransmit_interval': {'type': 'int'}, + 'transmit_delay': {'type': 'int'} + }, + 'type': 'list' + } + }, + 'type': 'list' + }, + 'state': { + 'choices': ['merged', 'deleted', 'replaced', 'overridden'], + 'default': 'merged', + 'type': 'str' + } + } # pylint: disable=C0301 diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/__init__.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py new file mode 100644 index 000000000..45777a1b2 --- /dev/null +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -0,0 +1,773 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2024 Dell Inc. or its subsidiaries. All Rights Reserved +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The sonic_ospfv2_interfaces class +It is in this file where the current configuration (as dict) +is compared to the provided configuration (as dict) and the command set +necessary to bring the current configuration to it's desired end-state is +created +""" +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from copy import deepcopy +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, +) +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.facts import Facts +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.sonic import ( + to_request, + edit_config +) +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.utils import ( + update_states, + get_diff, + remove_empties_from_list +) +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.formatted_diff_utils import ( + get_new_config, + get_formatted_config_diff, + __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF +) +from ansible.module_utils.connection import ConnectionError + +PATCH = 'patch' +DELETE = 'delete' +DEFAULT_ADDRESS = '0.0.0.0' + +TEST_KEYS = [ + {'config': {'name': ''}}, + {'ospf_attributes': {'address': ''}}, + {'message_digest_pwd': {'key_id': ''}} +] + +TEST_KEYS_delete_diff = [ + {'config': {'name': ''}}, + {'ospf_attributes': {'address': ''}}, + {'message_digest_pwd': {'key_id': ''}} +] +TEST_KEYS_overridden_diff = [ + {'config': {'name': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}}, + {'ospf_attributes': {'address': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}}, + {'message_digest_pwd': {'key_id': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}} +] + +ospf_int_attributes = { + 'bfd': { + 'enable': '/if-addresses={}/enable-bfd', + 'bfd_profile': '/if-addresses={}/enable-bfd/config/bfd-profile' + }, + 'network': '/if-addresses={}/config/network-type', + 'ospf_attributes': { + 'address': '/if-addresses={}', + 'area_id': '/if-addresses={}/config/area-id', + 'auth_pwd': '/if-addresses={}/config/authentication-key', + 'authentication_type': '/if-addresses={}/config/authentication-type', + 'cost': '/if-addresses={}/config/metric', + 'dead_interval': '/if-addresses={}/config/dead-interval', + 'hello_interval': '/if-addresses={}/config/hello-interval', + 'hello_multiplier': '/if-addresses={}/config/dead-interval-minimal', + 'message_digest_pwd': '/if-addresses={}/md-authentications/md-authentication={}', + 'mtu_ignore': '/if-addresses={}/config/mtu-ignore', + 'priority': '/if-addresses={}/config/priority', + 'retransmit_interval': '/if-addresses={}/config/retransmission-interval', + 'transmit_delay': '/if-addresses={}/config/transmit-delay' + } + +} + + +class Ospfv2_interfaces(ConfigBase): + """ + The sonic_ospfv2_interfaces class + """ + + gather_subset = [ + '!all', + '!min', + ] + + gather_network_resources = [ + 'ospfv2_interfaces', + ] + + def __init__(self, module): + super(Ospfv2_interfaces, self).__init__(module) + + def get_ospfv2_interfaces_facts(self): + """ Get the 'facts' (the current configuration) + + :rtype: A dictionary + :returns: The current configuration as a dictionary + """ + facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources) + ospfv2_interfaces_facts = facts['ansible_network_resources'].get('ospfv2_interfaces') + if not ospfv2_interfaces_facts: + return [] + return ospfv2_interfaces_facts + + def execute_module(self): + """ Execute the module + + :rtype: A dictionary + :returns: The result from module execution + """ + result = {'changed': False} + warnings = list() + commands = list() + + existing_ospfv2_interfaces_facts = self.get_ospfv2_interfaces_facts() + commands, requests = self.set_config(existing_ospfv2_interfaces_facts) + if commands and len(requests) > 0: + if not self._module.check_mode: + try: + edit_config(self._module, to_request(self._module, requests)) + except ConnectionError as exc: + self._module.fail_json(msg=str(exc), code=exc.code) + result['changed'] = True + + result['before'] = existing_ospfv2_interfaces_facts + old_config = existing_ospfv2_interfaces_facts + result['commands'] = commands + + changed_ospfv2_interfaces_facts = self.get_ospfv2_interfaces_facts() + + result['before'] = existing_ospfv2_interfaces_facts + if result['changed']: + result['after'] = changed_ospfv2_interfaces_facts + + new_config = changed_ospfv2_interfaces_facts + old_config = existing_ospfv2_interfaces_facts + if self._module.check_mode: + result.pop('after', None) + new_commands = deepcopy(commands) + self._add_default_address(new_commands) + self._add_default_address(new_config) + self._add_default_address(old_config) + + if self._module.params['state'] == 'overridden': + new_config = get_new_config(new_commands, old_config, TEST_KEYS_overridden_diff) + else: + new_config = get_new_config(new_commands, old_config, TEST_KEYS_delete_diff) + self._add_default_address(new_config) + self.sort_lists_in_config(new_config) + new_config = self._get_generated_config(new_commands, new_config, self._module.params['state']) + self._strip_default_address(new_config) + self._strip_default_address(old_config) + result['after(generated)'] = remove_empties_from_list(new_config) + + if self._module._diff: + self._add_default_address(old_config) + self._add_default_address(new_config) + self.sort_lists_in_config(old_config) + self.sort_lists_in_config(new_config) + result['diff'] = get_formatted_config_diff(old_config, new_config, self._module._verbosity) + self._strip_default_address(old_config) + self._strip_default_address(new_config) + + result['warnings'] = warnings + return result + + def set_config(self, existing_ospfv2_interfaces_facts): + """ Collect the configuration from the args passed to the module, + collect the current configuration (as a dict from facts) + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + want = self._module.params['config'] + have = existing_ospfv2_interfaces_facts + new_want = deepcopy(want) + new_have = deepcopy(have) + new_want = remove_empties_from_list(want) + new_have = remove_empties_from_list(have) + self._add_default_address(new_want) + self._add_default_address(new_have) + self.sort_lists_in_config(new_want) + self.sort_lists_in_config(new_have) + resp = self.set_state(new_want, new_have) + return to_list(resp) + + def set_state(self, want, have): + """ Select the appropriate function based on the state provided + + :param want: the desired configuration as a dictionary + :param have: the current configuration as a dictionary + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands, requests = [], [] + state = self._module.params['state'] + + if state == 'overridden': + commands, requests = self._state_overridden(want, have) + elif state == 'deleted': + commands, requests = self._state_deleted(want, have) + elif state == 'merged': + commands, requests = self._state_merged(want, have) + elif state == 'replaced': + commands, requests = self._state_replaced(want, have) + + return commands, requests + + def _state_replaced(self, want, have): + """ The command generator when state is replaced + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands, requests = [], [] + add_config, del_config = self._get_replaced_config(want, have) + if del_config: + del_commands, del_requests = self.get_delete_ospf_interfaces_commands_requests(del_config, have, False) + if len(del_requests) > 0: + self._strip_default_address(del_commands) + commands.extend(update_states(del_commands, 'deleted')) + requests.extend(del_requests) + + if add_config: + mod_requests = self.get_create_ospf_interfaces_requests(add_config, []) + if len(mod_requests) > 0: + self._strip_default_address(add_config) + commands.extend(update_states(add_config, 'replaced')) + requests.extend(mod_requests) + + return commands, requests + + def _state_overridden(self, want, have): + """ The command generator when state is overridden + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands, requests = [], [] + diff = get_diff(want, have, TEST_KEYS) + diff2 = get_diff(have, want, TEST_KEYS) + if diff or diff2: + del_commands, del_requests = self.get_delete_ospf_interfaces_commands_requests(have, have, True) + if len(del_requests) > 0: + self._strip_default_address(del_commands) + commands.extend(update_states(del_commands, 'deleted')) + requests.extend(del_requests) + mod_requests = self.get_create_ospf_interfaces_requests(want, []) + if len(mod_requests) > 0: + self._strip_default_address(want) + commands.extend(update_states(want, 'overridden')) + requests.extend(mod_requests) + return commands, requests + + def _state_merged(self, want, have): + """ The command generator when state is merged + + :rtype: A list + :returns: the commands necessary to merge the provided into + the current configuration + """ + commands = get_diff(want, have) + requests = self.get_create_ospf_interfaces_requests(commands, have) + + if commands and len(requests) > 0: + self._strip_default_address(commands) + commands = update_states(commands, "merged") + else: + commands = [] + + return commands, requests + + def _state_deleted(self, want, have): + """ The command generator when state is deleted + + :rtype: A list + :returns: the commands necessary to remove the current configuration + of the provided objects + """ + commands, requests = [], [] + is_delete_all = False + + if not want: + commands = have + is_delete_all = True + else: + commands = want + + del_commands, requests = self.get_delete_ospf_interfaces_commands_requests(commands, have, is_delete_all) + + if del_commands and len(requests) > 0: + self._strip_default_address(del_commands) + commands = update_states(del_commands, "deleted") + else: + commands = [] + + return commands, requests + + def _get_replaced_config(self, want, have): + add_config, del_config = [], [] + for conf in want: + intf_name = conf.get('name') + have_conf = next((cfg for cfg in have if cfg['name'] == intf_name), None) + if not have_conf: + add_config.append(conf) + else: + add_cfg, del_cfg = {}, {} + for attr in ospf_int_attributes: + if attr in conf: + if attr not in have_conf: + add_cfg[attr] = conf[attr] + else: + if attr == "bfd": + for bfd_attr in ['enable', 'bfd_profile']: + if bfd_attr not in have_conf: + add_cfg.setdefault(attr, {}) + add_cfg[attr][bfd_attr] = conf[attr][bfd_attr] + elif conf[attr][bfd_attr] != have_conf[attr][bfd_attr]: + add_cfg.setdefault(attr, {}) + del_cfg.setdefault(attr, {}) + add_cfg[attr][bfd_attr] = conf[attr][bfd_attr] + del_cfg[attr][bfd_attr] = have_conf[attr][bfd_attr] + elif attr == "network": + if conf[attr] != have_conf[attr]: + add_cfg[attr] = conf[attr] + del_cfg[attr] = have_conf[attr] + else: + # attr = 'ospf_attributes' + ospf_attr = conf.get(attr, []) + match_ospf_attr = have_conf.get(attr, []) + if not ospf_attr and match_ospf_attr: + del_cfg[attr] = match_ospf_attr + elif ospf_attr and not match_ospf_attr: + add_cfg[attr] = ospf_attr + elif ospf_attr and match_ospf_attr: + for ospf_list in ospf_attr: + address = ospf_list.get('address') + match_ospf_list = next((list for list in match_ospf_attr if list.get('address') == address), None) + if not match_ospf_list: + add_cfg[attr] = ospf_attr + else: + add_ospf_attr, del_ospf_attr = self._get_replaced_config_for_ospf_attributes(ospf_list, match_ospf_list) + if add_ospf_attr: + add_ospf_attr['address'] = address + add_cfg.setdefault(attr, []) + add_cfg[attr].append(add_ospf_attr) + if del_ospf_attr: + del_ospf_attr['address'] = address + del_cfg.setdefault(attr, []) + del_cfg[attr].append(del_ospf_attr) + elif attr in have_conf: + del_cfg[attr] = have_conf[attr] + if add_cfg: + add_cfg['name'] = intf_name + add_config.append(add_cfg) + if del_cfg: + del_cfg['name'] = intf_name + del_config.append(del_cfg) + return add_config, del_config + + def _get_replaced_config_for_ospf_attributes(self, want, have): + add_config, del_config = {}, {} + attr = 'ospf_attributes' + for ospf_attr in ospf_int_attributes[attr]: + if ospf_attr == 'hello_multiplier': + if ospf_attr in want: + if ospf_attr not in have: + add_config[ospf_attr] = want[ospf_attr] + if 'dead_interval' in have: + del_config['dead_interval'] = have['dead_interval'] + elif want[ospf_attr] != have[ospf_attr]: + add_config[ospf_attr] = want[ospf_attr] + del_config[ospf_attr] = have[ospf_attr] + elif ospf_attr in have: + del_config[ospf_attr] = have[ospf_attr] + continue + if ospf_attr == 'dead_interval': + if ospf_attr in want: + if ospf_attr not in have: + add_config[ospf_attr] = want[ospf_attr] + if 'hello_interval' in have: + del_config['hello_interval'] = have['hello_interval'] + elif want[ospf_attr] != have[ospf_attr]: + add_config[ospf_attr] = want[ospf_attr] + del_config[ospf_attr] = have[ospf_attr] + elif ospf_attr in have: + del_config[ospf_attr] = have[ospf_attr] + continue + if ospf_attr in want: + if ospf_attr not in have: + add_config[ospf_attr] = want[ospf_attr] + elif want[ospf_attr] != have[ospf_attr]: + if ospf_attr != 'message_digest_pwd': + if want[ospf_attr] != have[ospf_attr]: + add_config[ospf_attr] = want[ospf_attr] + del_config[ospf_attr] = have[ospf_attr] + else: + have_mdkeys = have[ospf_attr] + conf_mdkeys = want[ospf_attr] + add_mdkeys, del_mdkeys = [], [] + for conf_key in conf_mdkeys: + match_key = next((key for key in have_mdkeys if key['key_id'] == conf_key['key_id']), None) + if match_key: + if match_key['pwd'] != conf_key['pwd']: + add_mdkeys.append(conf_key) + del_mdkeys.append(match_key) + else: + add_mdkeys.append(conf_key) + if add_mdkeys: + add_config[ospf_attr] = add_mdkeys + if del_mdkeys: + del_config[ospf_attr] = del_mdkeys + elif attr in have: + del_config[ospf_attr] = have[ospf_attr] + + return add_config, del_config + + def get_create_ospf_interfaces_requests(self, commands, have): + requests = [] + bfd_dict = {} + if not commands: + return requests + + for cmd in commands: + payload = {} + bfd_dict = {} + name = cmd.get('name') + match = next((item for item in have if item['name'] == cmd['name']), None) + intf_name, sub_intf = self.get_ospf_if_and_subif(name) + ospf_path = self.get_ospf_uri(intf_name, sub_intf) + ospf_attr_configs = [] + for attr in cmd: + if attr == 'name': + continue + if attr == 'ospf_attributes': + for ospf_list in cmd.get(attr, []): + ospf_attr_dict = {} + ospf_md_configs_list = [] + address = ospf_list.get('address') + area_id = ospf_list.get('area_id') + if address and area_id and match: + for match_attr in match.get('ospf_attributes', []): + match_address = match_attr.get('address') + match_area_id = match_attr.get('area_id') + if match_address and match_area_id and match_address == address and match_area_id != area_id: + path = ospf_path + ospf_int_attributes['ospf_attributes']['area_id'].format(address) + requests.append({'path': path, 'method': DELETE}) + break + + self.update_dict(ospf_list, ospf_attr_dict, 'area_id', 'area-id') + self.update_dict(ospf_list, ospf_attr_dict, 'authentication_type', 'authentication-type') + self.update_dict(ospf_list, ospf_attr_dict, 'cost', 'metric') + self.update_dict(ospf_list, ospf_attr_dict, 'dead_interval', 'dead-interval') + self.update_dict(ospf_list, ospf_attr_dict, 'hello_interval', 'hello-interval') + self.update_dict(ospf_list, ospf_attr_dict, 'hello_multiplier', 'hello-multiplier') + if 'hello-multiplier' in ospf_attr_dict: + ospf_attr_dict['dead-interval-minimal'] = True + self.update_dict(ospf_list, ospf_attr_dict, 'mtu_ignore', 'mtu-ignore') + self.update_dict(ospf_list, ospf_attr_dict, 'priority', 'priority') + self.update_dict(ospf_list, ospf_attr_dict, 'retransmit_interval', 'retransmission-interval') + self.update_dict(ospf_list, ospf_attr_dict, 'transmit_delay', 'transmit-delay') + + if 'auth_pwd' in ospf_list: + self.update_dict(ospf_list['auth_pwd'], ospf_attr_dict, 'pwd', 'authentication-key') + self.update_dict(ospf_list['auth_pwd'], ospf_attr_dict, 'encrypted', 'authentication-key-encrypted') + + if 'message_digest_pwd' in ospf_list: + for mdkeys in ospf_list['message_digest_pwd']: + md_config = {} + self.update_dict(mdkeys, md_config, 'key_id', 'authentication-key-id') + if md_config: + md_config.setdefault('config', {}) + self.update_dict(mdkeys, md_config['config'], 'key_id', 'authentication-key-id') + self.update_dict(mdkeys, md_config['config'], 'encrypted', 'authentication-key-encrypted') + self.update_dict(mdkeys, md_config['config'], 'pwd', 'authentication-md5-key') + if md_config: + ospf_md_configs_list.append(md_config) + + if ospf_attr_dict: + ospf_attr_dict = {'config': ospf_attr_dict} + if ospf_md_configs_list: + ospf_attr_dict['md-authentications'] = {'md-authentication': ospf_md_configs_list} + if ospf_attr_dict: + ospf_attr_dict.setdefault('config', {}) + self.update_dict(ospf_list, ospf_attr_dict['config'], 'address', 'address') + self.update_dict(ospf_list, ospf_attr_dict, 'address', 'address') + ospf_attr_configs.append(ospf_attr_dict) + elif attr == "bfd": + self.update_dict(cmd[attr], bfd_dict, 'enable', 'enabled') + self.update_dict(cmd[attr], bfd_dict, 'bfd_profile', 'bfd-profile') + elif attr == "network": + network_type = cmd.get('network') + if network_type: + network_type = "openconfig-ospf-types:" + network_type.upper() + "_NETWORK" + ospf_default = False + for ospf_list in ospf_attr_configs: + if ospf_list['address'] == DEFAULT_ADDRESS: + ospf_list.setdefault('config', {}) + ospf_list['config']['network-type'] = network_type + ospf_default = True + break + if not ospf_default: + ospf_attr_dict = { + 'address' : DEFAULT_ADDRESS, + 'config' : {'address' : DEFAULT_ADDRESS, 'network-type' : network_type} + } + ospf_attr_configs.append(ospf_attr_dict) + + if ospf_attr_configs: + payload = { + "openconfig-ospfv2-ext:ospfv2": { + "if-addresses": ospf_attr_configs + } + } + requests.append({'path': ospf_path, 'method': PATCH, 'data': payload}) + if bfd_dict: + payload = { + 'openconfig-ospfv2-ext:ospfv2': { + "if-addresses": [{ + 'address': '0.0.0.0', + 'enable-bfd': {'config': bfd_dict} + }] + } + } + requests.append({'path': ospf_path, 'method': PATCH, 'data': payload}) + return requests + + def get_delete_ospf_interfaces_commands_requests(self, commands, have, is_delete_all): + commands_del, requests = [], [] + if not commands: + return commands_del, requests + + for cmd in commands: + del_cmd = {} + name = cmd.get('name') + intf_name, sub_intf = self.get_ospf_if_and_subif(name) + ospf_path = self.get_ospf_uri(intf_name, sub_intf) + match_have = next((cfg for cfg in have if cfg['name'] == name), None) + if match_have: + if is_delete_all or len(cmd) == 1: + commands_del.append(match_have) + requests.append({'path': ospf_path, 'method': DELETE}) + continue + for attr in cmd: + if attr == 'name': + continue + if attr == "bfd": + if "enable" in cmd.get(attr, {}) and "enable" in match_have.get(attr, {}): + path = ospf_path + ospf_int_attributes['bfd']['enable'].format(DEFAULT_ADDRESS) + requests.append({'path': path, 'method': DELETE}) + del_cmd.setdefault(attr, {}) + del_cmd[attr]['enable'] = match_have[attr]['enable'] + if "bfd_profile" in match_have.get(attr, {}): + del_cmd[attr]['bfd_profile'] = match_have[attr]['bfd_profile'] + elif "bfd_profile" in cmd.get(attr, {}) and "bfd_profile" in match_have.get(attr, {}): + path = ospf_path + ospf_int_attributes['bfd']['bfd_profile'].format(DEFAULT_ADDRESS) + requests.append({'path': path, 'method': DELETE}) + del_cmd.setdefault(attr, {}) + del_cmd[attr]['bfd_profile'] = match_have[attr]['bfd_profile'] + elif attr == 'network' and "network" in cmd.get(attr, {}) and "network" in match_have.get(attr, {}): + path = ospf_path + ospf_int_attributes['network'].format(DEFAULT_ADDRESS) + requests.append({'path': path, 'method': DELETE}) + del_cmd[attr] = match_have[attr] + elif attr == 'ospf_attributes': + match_ospf_attrs = match_have.get('ospf_attributes', []) + if match_ospf_attrs: + ospf_attrs = cmd.get('ospf_attributes', []) + if ospf_attrs is not None: + if not ospf_attrs: + # Delete all attributes in have + del_ospf_attrs, del_requests = self.get_delete_ospf_attributes_commands_requests(match_ospf_attrs, None, ospf_path) + requests.extend(del_requests) + if del_ospf_attrs: + del_cmd[attr] = del_ospf_attrs + else: + # Delete specific attributes in have + del_ospf_attrs, del_requests = self.get_delete_ospf_attributes_commands_requests(match_ospf_attrs, ospf_attrs, ospf_path) + requests.extend(del_requests) + if del_ospf_attrs: + del_cmd[attr] = del_ospf_attrs + if del_cmd: + del_cmd['name'] = name + commands_del.append(del_cmd) + return commands_del, requests + + def get_delete_ospf_attributes_commands_requests(self, match_ospf_attrs, ospf_attrs, ospf_path=''): + commands, requests = [], [] + if ospf_attrs: + for o_attr in ospf_attrs: + del_ospf_attr = {} + address = o_attr.get('address') + if address: + m_attr = next((cfg for cfg in match_ospf_attrs if cfg['address'] == address), None) + if m_attr: + if len(o_attr) == 1: + cmd, requests_to_delete = self.get_delete_all_ospf_attributes_per_address_commands_requests(m_attr, ospf_path) + requests.extend(requests_to_delete) + if cmd: + cmd['address'] = address + del_ospf_attr = cmd + commands.append(del_ospf_attr) + continue + for attr in o_attr: + if attr not in ('message_digest_pwd', 'address'): + if attr in m_attr and o_attr[attr] is not None and m_attr[attr] is not None: + requests.append({ + 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(address), + 'method': DELETE + }) + del_ospf_attr[attr] = m_attr[attr] + elif attr == 'message_digest_pwd': + if o_attr.get(attr) is None: + del_mkeys = [] + for key in m_attr.get(attr, []): + requests.append({ + 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address'], key['key_id']), + 'method': DELETE + }) + del_mkeys.append(key) + if del_mkeys: + del_ospf_attr[attr] = del_mkeys + + else: + del_mkeys = [] + for key in o_attr[attr]: + match_key = next((cfg for cfg in m_attr.get(attr, []) if cfg['key_id'] == key['key_id']), None) + if match_key: + requests.append({ + 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(address, key['key_id']), + 'method': DELETE + }) + del_mkeys.append(match_key) + if del_mkeys: + del_ospf_attr[attr] = del_mkeys + if del_ospf_attr: + del_ospf_attr['address'] = address + commands.append(del_ospf_attr) + else: + for m_attr in match_ospf_attrs: + cmd, requests_to_delete = self.get_delete_all_ospf_attributes_per_address_commands_requests(m_attr, ospf_path) + requests.extend(requests_to_delete) + if cmd: + cmd['address'] = m_attr['address'] + commands.append(cmd) + + return commands, requests + + def get_delete_all_ospf_attributes_per_address_commands_requests(self, m_attr, ospf_path): + commands, requests = {}, [] + for attr in m_attr: + if attr not in ('message_digest_pwd', 'address'): + requests.append({ + 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address']), + 'method': DELETE + }) + commands[attr] = m_attr[attr] + elif attr == 'message_digest_pwd': + del_mkeys = [] + for key in m_attr.get(attr, []): + requests.append({ + 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address'], key['key_id']), + 'method': DELETE + }) + del_mkeys.append(key) + if del_mkeys: + commands[attr] = del_mkeys + return commands, requests + + def sort_lists_in_config(self, config): + """ Sort the lists in the config """ + if config: + config.sort(key=lambda x: x['name']) + for cfg in config: + if cfg.get('ospf_attributes', []): + cfg['ospf_attributes'].sort(key=lambda x: x['address']) + for ospf_attr in cfg.get('ospf_attributes', []): + if ospf_attr.get('message_digest_pwd', []): + ospf_attr['message_digest_pwd'].sort(key=lambda x: x['key_id']) + + def _strip_default_address(self, conf): + if conf: + for cfg in conf: + for ospf_attr in cfg.get('ospf_attributes', []): + if ospf_attr.get('address') == DEFAULT_ADDRESS: + del ospf_attr['address'] + + def _add_default_address(self, conf): + if conf: + for cfg in conf: + for ospf_attr in cfg.get('ospf_attributes', []): + if not ospf_attr.get('address'): + ospf_attr['address'] = DEFAULT_ADDRESS + + def get_ospf_intf_uri(self, intf_name, sub_intf=0): + intf_name = intf_name.replace('/', '%2f') + ospf_intf_uri = "/data/openconfig-interfaces:interfaces/interface={}".format(intf_name) + if intf_name.startswith("Vlan"): + ospf_intf_uri += "/openconfig-vlan:routed-vlan" + else: + ospf_intf_uri += "/subinterfaces/subinterface={}".format(sub_intf) + return ospf_intf_uri + + def get_ospf_uri(self, intf_name, sub_intf=0): + ospf_uri = self.get_ospf_intf_uri(intf_name, sub_intf) + ospf_uri += "/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2" + return ospf_uri + + def get_ospf_if_and_subif(self, intf_name): + return intf_name.split(".") if "." in intf_name else (intf_name, 0) + + def update_dict(self, src, dest, src_key, dest_key, value=False): + if not value: + if src.get(src_key) is not None: + dest[dest_key] = src[src_key] + elif src: + dest.update(value) + + def _get_generated_config(self, want, new_config, state): + if state == 'merged': + for cmd in want: + name = cmd.get('name') + match = next((cfg for cfg in new_config if cfg['name'] == name), None) + if match: + match_ospf_attr = match.get('ospf_attributes', []) + cmd_ospf_attr = cmd.get('ospf_attributes', []) + for o_attr in cmd_ospf_attr: + m_attr = next((a for a in match_ospf_attr if a.get('address') == o_attr.get('address')), None) + if m_attr: + if 'dead_interval' in o_attr: + m_attr.pop('hello_multiplier', None) + if 'hello_multiplier' in o_attr: + m_attr.pop('dead_interval', None) + return new_config + else: + new_generated_config = [] + for cmd in new_config: + cmd_ospf_attr = cmd.get('ospf_attributes', []) + ospf_attr = [] + for o_attr in cmd_ospf_attr: + if len(o_attr) > 1: + md_keys = [] + o_md_keys = o_attr.get('message_digest_pwd', []) + if o_md_keys: + for key in o_md_keys: + if len(key) > 1: + md_keys.append(key) + if not md_keys: + o_attr.pop('message_digest_pwd', None) + else: + o_attr['message_digest_pwd'] = md_keys + if len(o_attr) > 1: + ospf_attr.append(o_attr) + if ospf_attr: + cmd['ospf_attributes'] = ospf_attr + else: + cmd.pop('ospf_attributes', None) + if len(cmd) > 1: + new_generated_config.append(cmd) + return new_generated_config diff --git a/plugins/module_utils/network/sonic/facts/facts.py b/plugins/module_utils/network/sonic/facts/facts.py index c614d2129..0c84bd936 100644 --- a/plugins/module_utils/network/sonic/facts/facts.py +++ b/plugins/module_utils/network/sonic/facts/facts.py @@ -30,6 +30,7 @@ from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.bgp_ext_communities.bgp_ext_communities import ( Bgp_ext_communitiesFacts, ) +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.ospfv2_interfaces.ospfv2_interfaces import Ospfv2_interfacesFacts from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.mclag.mclag import MclagFacts from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.prefix_lists.prefix_lists import Prefix_listsFacts from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.vlan_mapping.vlan_mapping import Vlan_mappingFacts @@ -83,6 +84,7 @@ bgp_as_paths=Bgp_as_pathsFacts, bgp_communities=Bgp_communitiesFacts, bgp_ext_communities=Bgp_ext_communitiesFacts, + ospfv2_interfaces=Ospfv2_interfacesFacts, mclag=MclagFacts, prefix_lists=Prefix_listsFacts, vlan_mapping=Vlan_mappingFacts, diff --git a/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/__init__.py b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py new file mode 100644 index 000000000..de6898868 --- /dev/null +++ b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py @@ -0,0 +1,197 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2024 Dell Inc. or its subsidiaries. All Rights Reserved +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The sonic ospfv2_interfaces fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +from copy import deepcopy + +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.argspec.ospfv2_interfaces.ospfv2_interfaces import Ospfv2_interfacesArgs + +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.sonic import ( + to_request, + edit_config +) +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.utils import ( + remove_empties_from_list +) +from ansible.module_utils.connection import ConnectionError + + +class Ospfv2_interfacesFacts(object): + """ The sonic ospfv2_interfaces fact class + """ + + def __init__(self, module, subspec='config', options='options'): + self._module = module + self.argument_spec = Ospfv2_interfacesArgs.argument_spec + spec = deepcopy(self.argument_spec) + if subspec: + if options: + facts_argument_spec = spec[subspec][options] + else: + facts_argument_spec = spec[subspec] + else: + facts_argument_spec = spec + + self.generated_spec = utils.generate_dict(facts_argument_spec) + + def populate_facts(self, connection, ansible_facts, data=None): + """ Populate the facts for ospfv2_interfaces + :param connection: the device connection + :param ansible_facts: Facts dictionary + :param data: previously collected conf + :rtype: dictionary + :returns: facts + """ + objs = [] + + all_ospfv2_interface_configs = {} + if not data: + all_ospfv2_interface_configs = self.get_ospfv2_interfaces() + + for ospfv2_interface_config in all_ospfv2_interface_configs: + if ospfv2_interface_config: + obj = self.render_config(self.generated_spec, ospfv2_interface_config) + if obj: + objs.append(obj) + + ansible_facts['ansible_network_resources'].pop('ospfv2_interfaces', None) + facts = {} + if objs: + params = utils.validate_config(self.argument_spec, {'config': objs}) + facts['ospfv2_interfaces'] = remove_empties_from_list(params['config']) + + ansible_facts['ansible_network_resources'].update(facts) + return ansible_facts + + def render_config(self, spec, conf): + """ + Render config as dictionary structure and delete keys + from spec for null values + + :param spec: The facts tree, generated from the argspec + :param conf: The configuration + :rtype: dictionary + :returns: The generated config + """ + return conf + + def get_ospfv2_interfaces(self): + """Get all OSPFv2 interfaces available in chassis""" + request = [{"path": "data/openconfig-interfaces:interfaces", "method": "GET"}] + + try: + response = edit_config(self._module, to_request(self._module, request)) + except ConnectionError as exc: + self._module.fail_json(msg=str(exc), code=exc.code) + ospf_configs = [] + + if "openconfig-interfaces:interfaces" in response[0][1]: + interfaces = response[0][1].get("openconfig-interfaces:interfaces", {}) + if interfaces.get('interface'): + interfaces = interfaces['interface'] + for interface in interfaces: + intf_name = interface.get('name') + if intf_name == "eth0": + continue + + ospf = None + ospf_config = {} + + if interface.get('openconfig-vlan:routed-vlan'): + ospf = interface.get('openconfig-vlan:routed-vlan', {}) + else: + ospf = interface.get('subinterfaces', {}).get('subinterface', [{}])[0] + + if ospf: + ipv4 = ospf.get('openconfig-if-ip:ipv4', {}) + if ipv4: + ospf_int = ipv4.get('openconfig-ospfv2-ext:ospfv2', {}) + if ospf_int: + ospf_attributes = [] + for address in ospf_int.get('if-addresses', []): + attr = {} + addr = address.get('address') + bfd = address.get('enable-bfd') + if bfd: + cfg = bfd.get('config') + if cfg: + bfd_cfg = {} + self.update_dict(bfd_cfg, 'enable', cfg.get('enabled')) + self.update_dict(bfd_cfg, 'bfd_profile', cfg.get('bfd-profile')) + self.update_dict(ospf_config, 'bfd', bfd_cfg) + config = address.get('config') + md_authentications = address.get('md-authentications') + if config: + self.update_dict(attr, 'area_id', config.get('area-id')) + self.update_dict(attr, 'authentication_type', config.get('authentication-type')) + self.update_dict(attr, 'cost', config.get('metric')) + self.update_dict(attr, 'hello_interval', config.get('hello-interval')) + self.update_dict(attr, 'mtu_ignore', config.get('mtu-ignore')) + self.update_dict(attr, 'priority', config.get('priority')) + self.update_dict(attr, 'retransmit_interval', config.get('retransmission-interval')) + self.update_dict(attr, 'transmit_delay', config.get('transmit-delay')) + + if 'authentication-key' in config: + attr['auth_pwd'] = {} + self.update_dict(attr['auth_pwd'], 'pwd', config.get('authentication-key')) + self.update_dict(attr['auth_pwd'], 'encrypted', config.get('authentication-key-encrypted')) + + if 'dead-interval-minimal' in config: + dead_interval_minimal = config.get('dead-interval-minimal') + if dead_interval_minimal: + self.update_dict(attr, 'hello_multiplier', config.get('hello-multiplier')) + else: + self.update_dict(attr, 'dead_interval', config.get('dead-interval')) + elif 'dead-interval' in config: + self.update_dict(attr, 'dead_interval', config.get('dead-interval')) + + if 'network-type' in config: + network = "broadcast" if 'BROADCAST' in config['network-type'] else "point_to_point" + ospf_config['network'] = network + + if md_authentications: + md_keys = [] + for md_auth in md_authentications.get('md-authentication', []): + md_config = md_auth.get('config', {}) + if md_config: + md_key = {} + self.update_dict(md_key, 'key_id', md_config.get('authentication-key-id')) + self.update_dict(md_key, 'pwd', md_config.get('authentication-md5-key')) + self.update_dict(md_key, 'encrypted', md_config.get('authentication-key-encrypted')) + if md_key: + md_keys.append(md_key) + + self.update_dict(attr, 'message_digest_pwd', md_keys) + if attr: + if addr != '0.0.0.0': + attr['address'] = addr + ospf_attributes.append(attr) + + self.update_dict(ospf_config, 'ospf_attributes', ospf_attributes) + if ospf_config: + ospf_config['name'] = intf_name + ospf_configs.append(ospf_config) + + return ospf_configs + + def update_dict(self, dict, key, value, parent_key=None): + if value is not None and value not in [{}, [], ()]: + if parent_key: + dict.setdefault(parent_key, {}) + dict[parent_key][key] = value + else: + dict[key] = value diff --git a/plugins/modules/sonic_facts.py b/plugins/modules/sonic_facts.py index 95cb58682..bd62c8ce1 100644 --- a/plugins/modules/sonic_facts.py +++ b/plugins/modules/sonic_facts.py @@ -65,6 +65,7 @@ - bgp_as_paths - bgp_communities - bgp_ext_communities + - ospfv2_interfaces - mclag - prefix_lists - vlan_mapping diff --git a/plugins/modules/sonic_ospfv2_interfaces.py b/plugins/modules/sonic_ospfv2_interfaces.py new file mode 100644 index 000000000..5dc4153f5 --- /dev/null +++ b/plugins/modules/sonic_ospfv2_interfaces.py @@ -0,0 +1,748 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2024 Dell Inc. or its subsidiaries. All Rights Reserved +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the resource +# module builder playbook. +# +# Do not edit this file manually. +# +# Changes to this file will be over written +# by the resource module builder. +# +# Changes should be made in the model used to +# generate this file or in the resource module +# builder template. +# +############################################# + +""" +The module file for sonic_ospfv2_interfaces +""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = """ +--- +module: sonic_ospfv2_interfaces +version_added: '3.0.0' +notes: +- Supports C(check_mode). +short_description: Configure OSPFv2 interface mode protocol settings on SONiC. +description: + - This module provides configuration management of OSPFv2 interface mode parameters on devices running SONiC. + - Configure VRF instance before configuring OSPF in a VRF. + - Configure OSPF instance before configuring OSPF in interfaces. +author: "Santhosh kumar T (@santhosh-kt)" +options: + config: + description: + - Specifies the OSPFv2 interface mode related configuration. + type: list + elements: dict + suboptions: + name: + required: True + type: str + description: + - Full name of the interface, i.e. Ethernet1. + ospf_attributes: + description: + - Configure OSPFv2 attributes based on Interface IPv4 address. + - In case if IP address is not specified, default value will be set. + - I(dead_interval) and I(hello_multiplier) are mutually exclusive. + type: list + elements: dict + suboptions: + address: + description: + - Interface IPv4 address to be set. + - If no address is set, default value is considered. + type: str + area_id: + description: + - OSPFv2 Area ID of the network (A.B.C.D or 0 to 4294967295). + type: str + authentication_type: + description: + - Enable OSPFv2 authentication and its type. + - C(MD5HMAC) - Enable Message digest authentication type. + - C(NONE) - Enable null authentication. + - C(TEXT) - Enable plain text authentication. + type: str + choices: + - 'MD5HMAC' + - 'NONE' + - 'TEXT' + auth_pwd: + description: + - Configure OSPFv2 plain text authentication type password. + - Authentication key shall be max 8 charater long. + type: dict + suboptions: + pwd: + description: + - Configure authentication password. + - Plain text passwords i.e. password with encrypted=False will be encrypted in running-config, so idempotency will + not be maintained and every time the output will come as changed=True. + type: str + required: true + encrypted: + description: + - Indicates whether the password is encrypted text. + type: bool + cost: + description: + - Configure OSPFv2 interface cost (1 to 65535). + type: int + dead_interval: + description: + - Configure OSPFv2 adjacency dead interval (1 to 65535). + type: int + hello_multiplier: + description: + - Minimal 1s dead-interval with fast sub-second hellos. + - Number of Hellos to send each second (1 to 10). + type: int + hello_interval: + description: + - Configure OSPFv2 neighbour hello interval (1 to 65535). + type: int + message_digest_pwd: + description: + - Configure OSPFv2 message digest keys and passwords. + - Uses MD5 algorithm. + type: list + elements: dict + suboptions: + key_id: + description: + - Configure OSPFv2 message digest key ID (1 to 255). + type: int + required: True + pwd: + description: + - Configure OSPFv2 message digest password. + - Plain text passwords i.e. password with encrypted=False will be encrypted in running-config, so idempotency will + not be maintained and every time the output will come as changed=True. + type: str + encrypted: + description: + - Indicates whether the password is encrypted text. + type: bool + mtu_ignore: + description: + - Disable OSPFv2 MTU mismatch detection. + type: bool + priority: + description: + - Configure OSPFv2 adjacency router priority (0 to 255). + type: int + retransmit_interval: + description: + - Configure OSPFv2 retransmit interval (2 to 65535). + type: int + transmit_delay: + description: + - Configure OSPFv2 transmit delay (1 to 65535). + type: int + bfd: + description: + - Configure OSPFv2 interface BFD. + type: dict + suboptions: + enable: + description: + - Enable BFD support for OSPFv2. + type: bool + required: true + bfd_profile: + description: + - Configure BFD profile. + type: str + network: + description: + - Configure OSPFv2 interface network type + type: str + choices: + - broadcast + - point_to_point + state: + description: + - Specifies the operation to be performed on the OSPFv2 interfaces configured on the device. + - In case of merged, the input configuration will be merged with the existing OSPFv2 interfaces configuration on the device. + - In case of deleted, the existing OSPFv2 interfaces configuration will be removed from the device. + - In case of overridden, all the existing OSPFv2 interfaces configuration will be deleted and the specified input configuration will be installed. + - In case of replaced, the existing OSPFv2 interface configuration on the device will be replaced by the configuration in the playbook for + each interface group configured by the playbook. + type: str + default: merged + choices: ['merged', 'deleted', 'replaced', 'overridden'] +""" +EXAMPLES = """ +# Using deleted + +# Before state: +# ------------- +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile2 +# ip ospf cost 30 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network point-to-point +# ip ospf priority 20 +# ip ospf authentication null 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1/Ml24vwe6RSjUUqI+54BdDyDL0eKUezJw= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +# ip ospf authentication null 10.19.119.1 +# ip ospf message-digest-key 10 md5 U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ= encrypted 10.19.119.1 +#! +#interface Eth1/2 +# ip ospf bfd +# ip ospf network point-to-point +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + - name: Delete the OSPFv2_interface configurations + sonic_ospfv2_interfaces: + config: + - name: 'Eth1/1' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 30 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'NONE' + auth_pwd: + pwd: 'pass2' + - address: '10.19.119.1' + bfd: + enable: True + bfd_profile: 'profile2' + network: point_to_point + - name: 'Eth1/2' + bfd: + enable: True + - name: 'Eth1/3' + state: deleted + +# After state: +# ------------ +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +#! +#interface Eth1/2 +# ip ospf network point-to-point +#! +#interface Eth1/3 +#! +#sonic# + + +# Using deleted + +# Before state: +# ------------- +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile2 +# ip ospf cost 30 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network point-to-point +# ip ospf priority 20 +# ip ospf authentication null 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1/Ml24vwe6RSjUUqI+54BdDyDL0eKUezJw= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +# ip ospf authentication null 10.19.119.1 +# ip ospf message-digest-key 10 md5 U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ= encrypted 10.19.119.1 +#! +#interface Eth1/2 +# ip ospf bfd +# ip ospf network point-to-point +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + - name: Delete the OSPFv2_interface configurations + sonic_ospfv2_interfaces: + config: + - name: 'Eth1/1' + - name: 'Eth1/2' + bfd: + enable: True + - name: 'Eth1/3' + state: deleted + +# After state: +# ------------ +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +#! +#interface Eth1/2 +# ip ospf network point-to-point +#! +#interface Eth1/3 +#! +#sonic# + + +# Using merged + +# Before state: +# ------------- +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +#! +#sonic# + + - name: Add the OSPFv2_interface configurations + sonic_ospfv2_interfaces: + config: + - name: 'Eth1/1' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'password' + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: broadcast + - name: 'Eth1/3' + ospf_attributes: + - area_id: '3.3.3.3' + address: '10.19.120.2' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'password' + hello_multiplier: 5 + bfd: + enable: True + network: point_to_point + state: merged + +# After state: +# ------------ +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile1 +# ip ospf cost 20 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication message-digest 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1+ozJSEI69XJb2KR9Pu1Sa3Ou6ujTRalbQ= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + +# Using merged + +# Before state: +# ------------- +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile1 +# ip ospf cost 20 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication message-digest 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1+ozJSEI69XJb2KR9Pu1Sa3Ou6ujTRalbQ= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + - name: Add the OSPFv2_interface configurations + sonic_ospfv2_interfaces: + config: + - name: 'Eth1/1' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 30 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'NONE' + auth_pwd: + pwd: 'pass2' + - address: '10.19.119.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' + encrypted: True + bfd: + enable: True + bfd_profile: 'profile2' + network: point_to_point + - name: 'Eth1/2' + bfd: + enable: True + network: point_to_point + state: merged + +# After state: +# ------------ +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile2 +# ip ospf cost 30 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network point-to-point +# ip ospf priority 20 +# ip ospf authentication null 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1/Ml24vwe6RSjUUqI+54BdDyDL0eKUezJw= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +# ip ospf authentication null 10.19.119.1 +# ip ospf message-digest-key 10 md5 U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ= encrypted 10.19.119.1 +#! +#interface Eth1/2 +# ip ospf bfd +# ip ospf network point-to-point +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + +# Using replaced + +# Before state: +# ------------- +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile1 +# ip ospf cost 20 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication message-digest 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1+ozJSEI69XJb2KR9Pu1Sa3Ou6ujTRalbQ= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + - name: Replace the OSPFv2_interface configurations + sonic_ospfv2_interfaces: + config: + - name: 'Eth1/3' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 30 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'NONE' + auth_pwd: + pwd: 'pass2' + - address: '10.19.119.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' + encrypted: True + bfd: + enable: True + bfd_profile: 'profile2' + network: broadcast + state: replaced + +# After state: +# ------------ +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile1 +# ip ospf cost 20 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication message-digest 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1+ozJSEI69XJb2KR9Pu1Sa3Ou6ujTRalbQ= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile2 +# ip ospf cost 30 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication null 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX186k2R2hUXaDloW8hfkApn5Zx5hCQy9usc= encrypted 10.10.120.1 +# ip ospf authentication null 10.19.119.1 +# ip ospf message-digest-key 10 md5 U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ= encrypted 10.19.119.1 +#! +#sonic# + + +# Using overridden + +# Before state: +# ------------- +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile1 +# ip ospf cost 20 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication message-digest 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX1+ozJSEI69XJb2KR9Pu1Sa3Ou6ujTRalbQ= encrypted 10.10.120.1 +# ip ospf dead-interval minimal hello-multiplier 5 10.10.120.1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +# ip ospf bfd +# ip ospf network point-to-point +# ip ospf area 3.3.3.3 10.19.120.2 +# ip ospf authentication message-digest 10.19.120.2 +# ip ospf authentication-key U2FsdGVkX19HqGCcf2pzGur9MDnb0VzLNRvoFij3Os0= encrypted 10.19.120.2 +# ip ospf dead-interval minimal hello-multiplier 5 10.19.120.2 +#! +#sonic# + + - name: Override the OSPFv2_interface configurations + sonic_ospfv2_interfaces: + config: + - name: 'Eth1/3' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 30 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'NONE' + auth_pwd: + pwd: 'pass2' + - address: '10.19.119.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' + encrypted: True + bfd: + enable: True + bfd_profile: 'profile2' + network: broadcast + state: overridden + +# After state: +# ------------ +# +#sonic# show running-configuration interface +#! +#interface Eth1/1 +#! +#interface Eth1/2 +#! +#interface Eth1/3 +# ip ospf area 2.2.2.2 +# ip ospf bfd +# ip ospf bfd profile profile2 +# ip ospf cost 30 +# ip ospf dead-interval 40 +# ip ospf hello-interval 10 +# ip ospf mtu-ignore +# ip ospf network broadcast +# ip ospf priority 20 +# ip ospf authentication null 10.10.120.1 +# ip ospf authentication-key U2FsdGVkX186k2R2hUXaDloW8hfkApn5Zx5hCQy9usc= encrypted 10.10.120.1 +# ip ospf authentication null 10.19.119.1 +# ip ospf message-digest-key 10 md5 U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ= encrypted 10.19.119.1 +#! +#sonic# + + +""" +RETURN = """ +before: + description: The configuration prior to the model invocation. + returned: always + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +after: + description: The resulting configuration model invocation. + returned: when changed + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +after(generated): + description: The generated configuration model invocation. + returned: when C(check_mode) + type: list + sample: > + The configuration returned will always be in the same format + of the parameters above. +commands: + description: The set of commands pushed to the remote device. + returned: always + type: list + sample: ['command 1', 'command 2', 'command 3'] +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.argspec.ospfv2_interfaces.ospfv2_interfaces import Ospfv2_interfacesArgs +from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.config.ospfv2_interfaces.ospfv2_interfaces import Ospfv2_interfaces + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule(argument_spec=Ospfv2_interfacesArgs.argument_spec, + supports_check_mode=True) + + result = Ospfv2_interfaces(module).execute_module() + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml new file mode 100644 index 000000000..db3767574 --- /dev/null +++ b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml @@ -0,0 +1,368 @@ +--- +ansible_connection: httpapi +module_name: ospfv2_interfaces + +po1: "PortChannel100" +po2: "PortChannel101" + +vlan1: "Vlan100" +vlan2: "Vlan101" + +lo1: "Loopback100" + +preparations_tests: + lag_interfaces: + - name: "{{ po1 }}" + - name: "{{ po2 }}" + vlans: + - vlan_id: 100 + - vlan_id: 101 + init_loopback: + - "interface {{ lo1 }}" + delete_port_configurations: + - name: "{{ interface7 }}" + - name: "{{ interface8 }}" + init_ospf: + - router ospf + delete_ospf: + - no router ospf + +tests: + - name: test_case_01 + description: Add OSPFv2 interface configurations for Ethernet interfaces + state: merged + input: + - name: "{{ interface7 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: broadcast + - name: "{{ interface8 }}" + ospf_attributes: + - area_id: '3.3.3.3' + address: '10.19.120.2' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + network: point_to_point + - name: test_case_02 + description: Add OSPFv2 interface configurations for Lag interfaces + state: merged + input: + - name: "{{ po1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 15 + retransmit_interval: 100 + transmit_delay: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - key_id: 20 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + network: broadcast + bfd: + enable: True + bfd_profile: 'profile1' + - name: "{{ po2 }}" + ospf_attributes: + - area_id: '3.3.3.3' + address: '10.19.120.2' + authentication_type: 'TEXT' + - name: test_case_03 + description: Add OSPFv2 interface configurations for Vlan and Loopback interfaces + state: merged + input: + - name: "{{ vlan1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - name: "{{ vlan2 }}" + bfd: + enable: True + bfd_profile: 'profile2' + network: broadcast + - name: "{{ lo1 }}" + network: point_to_point + - name: test_case_04 + description: Add OSPFv2 interface configurations + state: merged + input: + - name: "{{ po1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 15 + - address: '10.10.120.1' + mtu_ignore: True + authentication_type: 'TEXT' + message_digest_pwd: + - key_id: 30 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + network: point_to_point + bfd: + enable: True + bfd_profile: 'profile2' + - name: "{{ interface7 }}" + ospf_attributes: + - area_id: '4.4.4.4' + cost: 15 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - name: "{{ vlan2 }}" + bfd: + enable: True + bfd_profile: 'profile2' + network: broadcast + ospf_attributes: + - area_id: '1.1.1.1' + address: '10.19.120.2' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 2 + - area_id: '2.2.2.2' + address: '10.19.120.3' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 2 + - name: "{{ lo1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: point_to_point + - name: test_case_del_01 + description: Delete OSPFv2 interface configurations + state: deleted + input: + - name: "{{ lo1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: broadcast + - name: "{{ interface7 }}" + ospf_attributes: [] + bfd: + enable: True + - name: "{{ vlan1 }}" + ospf_attributes: + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - name: "{{ po1 }}" + ospf_attributes: + - address: '10.10.120.1' + network: broadcast + - name: test_case_del_02 + description: Delete OSPFv2 interface configurations for interfaces default address + state: deleted + input: + - name: "{{ po1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 15 + - name: "{{ vlan1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + hello_multiplier: 2 + - name: test_case_del_03 + description: Delete entire OSPFv2 for an interface. + state: deleted + input: + - name: "{{ interface7 }}" + - name: "{{ vlan2 }}" + - name: "{{ po2 }}" + - name: test_case_05 + description: Add OSPFv2 interface configurations for interface level + state: merged + input: + - name: "{{ interface7 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + - area_id: '4.4.4.4' + address: '10.10.120.10' + cost: 15 + hello_multiplier: 2 + - address: '10.10.120.2' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + bfd: + enable: True + bfd_profile: 'profile1' + network: broadcast + - name: "{{ vlan1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - name: test_case_replace_01 + description: Replace existing OSPFv2 interface configurations for interface level + state: replaced + input: + - name: "{{ vlan1 }}" + ospf_attributes: + - area_id: '3.3.3.3' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + - name: "{{ lo1 }}" + network: point_to_point + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + - name: test_case_replace_02 + description: Replace OSPFv2 interface configurations + state: replaced + input: + - name: "{{ vlan1 }}" + ospf_attributes: + - area_id: '3.3.3.3' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + - name: "{{ interface8 }}" + network: point_to_point + - name: "{{ po1 }}" + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - name: test_case_overridden_01 + description: Override entire OSPFv2 interface configurations + state: overridden + input: + - name: "{{ po2 }}" + ospf_attributes: + - area_id: '3.3.3.3' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: broadcast + - name: "{{ vlan1 }}" + ospf_attributes: + - area_id: '3.3.3.3' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + - name: test_case_delete_all + description: Delete entire OSPFv2 interface configurations + state: deleted + input: [] diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/meta/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/meta/main.yml new file mode 100644 index 000000000..d0ceaf6f5 --- /dev/null +++ b/tests/regression/roles/sonic_ospfv2_interfaces/meta/main.yml @@ -0,0 +1,5 @@ +--- +collections: + - dellemc.enterprise_sonic +dependencies: + - { role: common } diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/tasks/cleanup_tests.yaml b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/cleanup_tests.yaml new file mode 100644 index 000000000..4187251bf --- /dev/null +++ b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/cleanup_tests.yaml @@ -0,0 +1,31 @@ +--- +- name: Delete OSPFv2 interfaces configurations + dellemc.enterprise_sonic.sonic_ospfv2_interfaces: + config: [] + state: deleted + ignore_errors: yes + +- name: "Delete ospf" + vars: + ansible_connection: network_cli + sonic_config: + commands: "{{ preparations_tests.delete_ospf }}" + ignore_errors: yes + +- name: Delete test VLANs + dellemc.enterprise_sonic.sonic_vlans: + config: "{{ preparations_tests.vlans }}" + state: deleted + ignore_errors: yes + +- name: Delete test lag interfaces + dellemc.enterprise_sonic.sonic_lag_interfaces: + config: "{{ preparations_tests.lag_interfaces }}" + state: deleted + ignore_errors: yes + +- name: Delete test Loopbacks + dellemc.enterprise_sonic.sonic_vlans: + config: "{{ preparations_tests.vlans }}" + state: deleted + ignore_errors: yes diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml new file mode 100644 index 000000000..95c12d043 --- /dev/null +++ b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml @@ -0,0 +1,17 @@ +--- +- ansible.builtin.debug: + msg: "sonic_ospfv2 interfaces Test started ..." + +- name: "Preparations test, creates VLANs" + ansible.builtin.include_tasks: preparation_tests.yaml + +- name: "Test {{ module_name }} started" + ansible.builtin.include_tasks: tasks_template.yaml + loop: "{{ tests }}" + +- name: "Cleanup of {{ module_name }}" + ansible.builtin.include_tasks: cleanup_tests.yaml + +- name: Display all variables/facts known for a host + ansible.builtin.debug: + var: hostvars[inventory_hostname].ansible_facts.test_reports diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/tasks/preparation_tests.yaml b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/preparation_tests.yaml new file mode 100644 index 000000000..566aa2882 --- /dev/null +++ b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/preparation_tests.yaml @@ -0,0 +1,32 @@ +--- +- name: Delete old OSPFv2 interfaces configurations + dellemc.enterprise_sonic.sonic_ospfv2_interfaces: + config: [] + state: deleted + ignore_errors: yes + +- name: "initialize ospf" + vars: + ansible_connection: network_cli + sonic_config: + commands: "{{ preparations_tests.init_ospf }}" + ignore_errors: yes + +- name: "initialize init_loopback" + vars: + ansible_connection: network_cli + sonic_config: + commands: "{{ preparations_tests.init_loopback }}" + ignore_errors: yes + +- name: Create VLANs + dellemc.enterprise_sonic.sonic_vlans: + config: "{{ preparations_tests.vlans }}" + state: merged + ignore_errors: yes + +- name: Create lag interfaces + dellemc.enterprise_sonic.sonic_lag_interfaces: + config: "{{ preparations_tests.lag_interfaces }}" + state: merged + ignore_errors: yes diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/tasks/tasks_template.yaml b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/tasks_template.yaml new file mode 100644 index 000000000..d71e3300d --- /dev/null +++ b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/tasks_template.yaml @@ -0,0 +1,22 @@ +--- +- name: "{{ item.name }} , {{ item.description }}" + dellemc.enterprise_sonic.sonic_ospfv2_interfaces: + config: "{{ item.input }}" + state: "{{ item.state }}" + register: action_task_output + ignore_errors: yes + +- ansible.builtin.import_role: + name: common + tasks_from: action.facts.report.yaml + +- name: "{{ item.name }} , {{ item.description }} Idempotent" + dellemc.enterprise_sonic.sonic_ospfv2_interfaces: + config: "{{ item.input }}" + state: "{{ item.state }}" + register: idempotent_task_output + ignore_errors: yes + +- ansible.builtin.import_role: + name: common + tasks_from: idempotent.facts.report.yaml diff --git a/tests/regression/test.yaml b/tests/regression/test.yaml index 4347df99c..0ce5f2500 100644 --- a/tests/regression/test.yaml +++ b/tests/regression/test.yaml @@ -26,6 +26,7 @@ - sonic_bgp_af - sonic_bgp_neighbors - sonic_bgp_neighbors_af + - sonic_ospfv2_interfaces - sonic_dhcp_snooping - sonic_vlan_mapping - sonic_vrfs diff --git a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml new file mode 100644 index 000000000..c7fae66a4 --- /dev/null +++ b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml @@ -0,0 +1,1428 @@ +--- +merged_01: + module_args: + config: + - name: 'Eth1/5' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: broadcast + - name: 'PortChannel100' + ospf_attributes: + - area_id: '3.3.3.3' + address: '10.19.120.2' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + network: point_to_point + - name: 'Vlan100' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + state: merged + existing_ospfv2_config: + - path: 'data/openconfig-interfaces:interfaces' + response: + code: 200 + value: + openconfig-interfaces:interfaces: + interface: + - name: 'Eth1/5' + subinterfaces: + subinterface: + - index: 0 + - name: 'PortChannel100' + subinterfaces: + subinterface: + - index: 0 + - name: 'Vlan100' + openconfig-vlan:routed-vlan: + expected_config_requests: + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + hello-interval: 10 + metric: 20 + mtu-ignore: true + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + priority: 20 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '10.19.120.2' + config: + address: '10.19.120.2' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + area-id: '3.3.3.3' + - address: '0.0.0.0' + config: + address: '0.0.0.0' + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + enabled: true + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + hello-multiplier: 2 + dead-interval-minimal: true + metric: 20 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + +merged_02: + module_args: + config: + - name: 'PortChannel100' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 15 + - address: '10.10.120.1' + mtu_ignore: True + authentication_type: 'TEXT' + message_digest_pwd: + - key_id: 30 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + network: point_to_point + bfd: + enable: True + bfd_profile: 'profile2' + - name: 'Eth1/6' + ospf_attributes: + - area_id: '4.4.4.4' + cost: 15 + hello_multiplier: 2 + - address: '10.10.120.1' + authentication_type: 'NONE' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - name: 'Vlan100' + bfd: + enable: True + bfd_profile: 'profile2' + network: broadcast + ospf_attributes: + - area_id: '1.1.1.1' + address: '10.19.120.2' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 2 + - area_id: '2.2.2.2' + address: '10.19.120.3' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 2 + - name: 'Loopback100' + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + priority: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + bfd: + enable: True + bfd_profile: 'profile1' + network: point_to_point + state: merged + existing_ospfv2_config: + - path: 'data/openconfig-interfaces:interfaces' + response: + code: 200 + value: + openconfig-interfaces:interfaces: + interface: + - name: 'Eth1/5' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + dead-interval-minimal: false + hello-interval: 10 + metric: 20 + mtu-ignore: true + priority: 20 + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - name: 'Eth1/6' + subinterfaces: + subinterface: + - index: 0 + - name: 'PortChannel100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + dead-interval-minimal: true + hello-multiplier: 5 + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '3.3.3.3' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + - name: 'Vlan100' + openconfig-vlan:routed-vlan: + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 20 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'Loopback100' + subinterfaces: + subinterface: + - index: 0 + expected_config_requests: + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '4.4.4.4' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 15 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + area-id: '2.2.2.2' + dead-interval: 40 + hello-interval: 10 + mtu-ignore: true + metric: 20 + priority: 20 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 15 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'TEXT' + mtu-ignore: true + md-authentications: + md-authentication: + - authentication-key-id: 30 + config: + authentication-key-id: 30 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + bfd-profile: 'profile2' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + - address: '10.19.120.2' + config: + address: '10.19.120.2' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + area-id: '1.1.1.1' + - address: '10.19.120.3' + config: + address: '10.19.120.3' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + area-id: '2.2.2.2' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + bfd-profile: 'profile2' + enabled: true + +deleted_01: + module_args: + config: + - name: 'Eth1/5' + - name: 'Eth1/6' + ospf_attributes: + - area_id: '4.4.4.4' + cost: 15 + hello_multiplier: 5 + - address: '10.10.120.1' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + - name: 'PortChannel100' + ospf_attributes: + - address: '0.0.0.0' + - address: '10.19.120.2' + - name: 'Vlan100' + bfd: + enable: True + network: 'broadcast' + ospf_attributes: + - address: '10.10.120.1' + message_digest_pwd: + - key_id: 10 + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + state: deleted + existing_ospfv2_config: + - path: 'data/openconfig-interfaces:interfaces' + response: + code: 200 + value: + openconfig-interfaces:interfaces: + interface: + - name: 'Eth1/5' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + dead-interval-minimal: false + hello-interval: 10 + metric: 20 + mtu-ignore: true + priority: 20 + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - name: 'Eth1/6' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '4.4.4.4' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 15 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'PortChannel100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + dead-interval-minimal: true + hello-multiplier: 5 + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '3.3.3.3' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'TEXT' + mtu-ignore: true + md-authentications: + md-authentication: + - authentication-key-id: 30 + config: + authentication-key-id: 30 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'Vlan100' + openconfig-vlan:routed-vlan: + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 20 + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile2' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '1.1.1.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - address: '10.19.120.3' + config: + address: '10.19.120.3' + area-id: '2.2.2.2' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - name: 'Loopback100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + hello-interval: 10 + dead-interval-minimal: false + dead-interval: 40 + mtu-ignore: true + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + expected_config_requests: + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/metric' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/md-authentications/md-authentication=10' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/metric' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/priority' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/enable-bfd' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/md-authentications/md-authentication=10' + method: 'delete' + +deleted_02: + module_args: + config: + state: deleted + existing_ospfv2_config: + - path: 'data/openconfig-interfaces:interfaces' + response: + code: 200 + value: + openconfig-interfaces:interfaces: + interface: + - name: 'Eth1/5' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + dead-interval-minimal: false + hello-interval: 10 + metric: 20 + mtu-ignore: true + priority: 20 + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - name: 'Eth1/6' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '4.4.4.4' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 15 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'PortChannel100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + dead-interval-minimal: true + hello-multiplier: 5 + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '3.3.3.3' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'TEXT' + mtu-ignore: true + md-authentications: + md-authentication: + - authentication-key-id: 30 + config: + authentication-key-id: 30 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'Vlan100' + openconfig-vlan:routed-vlan: + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 20 + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile2' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '1.1.1.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - address: '10.19.120.3' + config: + address: '10.19.120.3' + area-id: '2.2.2.2' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - name: 'Loopback100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + hello-interval: 10 + dead-interval-minimal: false + dead-interval: 40 + mtu-ignore: true + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + expected_config_requests: + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + +replaced_01: + module_args: + config: + - name: 'Eth1/5' + bfd: + bfd_profile: 'profile1' + enable: True + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + priority: 20 + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + - name: 'Loopback100' + network: broadcast + bfd: + bfd_profile: 'profile3' + enable: True + - name: 'Vlan100' + ospf_attributes: + - address: '10.10.120.2' + area_id: '1.1.1.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 2 + - address: '10.10.120.3' + area_id: '2.2.2.2' + network: broadcast + state: replaced + existing_ospfv2_config: + - path: 'data/openconfig-interfaces:interfaces' + response: + code: 200 + value: + openconfig-interfaces:interfaces: + interface: + - name: 'Eth1/5' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + dead-interval-minimal: false + hello-interval: 10 + metric: 20 + mtu-ignore: true + priority: 20 + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - name: 'Eth1/6' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '4.4.4.4' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 15 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'PortChannel100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + dead-interval-minimal: true + hello-multiplier: 5 + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '3.3.3.3' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'TEXT' + mtu-ignore: true + md-authentications: + md-authentication: + - authentication-key-id: 30 + config: + authentication-key-id: 30 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'Vlan100' + openconfig-vlan:routed-vlan: + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 20 + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile2' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '1.1.1.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - address: '10.19.120.3' + config: + address: '10.19.120.3' + area-id: '2.2.2.2' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - name: 'Loopback100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + hello-interval: 10 + dead-interval-minimal: false + dead-interval: 40 + mtu-ignore: true + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + expected_config_requests: + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/dead-interval' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/metric' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/hello-interval' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/mtu-ignore' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/priority' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/enable-bfd' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile3' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '10.10.120.2' + config: + address: '10.10.120.2' + area-id: '1.1.1.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - address: '10.10.120.3' + config: + address: '10.10.120.3' + area-id: '2.2.2.2' + +overridden_01: + module_args: + config: + - name: 'Eth1/5' + bfd: + bfd_profile: 'profile1' + enable: True + ospf_attributes: + - area_id: '2.2.2.2' + cost: 20 + hello_interval: 10 + dead_interval: 40 + mtu_ignore: True + priority: 20 + - address: '10.10.120.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 5 + - name: 'Loopback100' + network: broadcast + bfd: + bfd_profile: 'profile3' + enable: True + - name: 'Vlan100' + ospf_attributes: + - address: '10.10.120.2' + area_id: '1.1.1.1' + authentication_type: 'MD5HMAC' + auth_pwd: + pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True + hello_multiplier: 2 + - address: '10.10.120.3' + area_id: '2.2.2.2' + network: broadcast + state: overridden + existing_ospfv2_config: + - path: 'data/openconfig-interfaces:interfaces' + response: + code: 200 + value: + openconfig-interfaces:interfaces: + interface: + - name: 'Eth1/5' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + dead-interval-minimal: false + hello-interval: 10 + metric: 20 + mtu-ignore: true + priority: 20 + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - name: 'Eth1/6' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '4.4.4.4' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 15 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'PortChannel100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + dead-interval-minimal: true + hello-multiplier: 5 + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '3.3.3.3' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'TEXT' + mtu-ignore: true + md-authentications: + md-authentication: + - authentication-key-id: 30 + config: + authentication-key-id: 30 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - name: 'Vlan100' + openconfig-vlan:routed-vlan: + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval-minimal: true + hello-multiplier: 2 + metric: 20 + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile2' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'NONE' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-id: 10 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + - address: '10.19.120.2' + config: + address: '10.19.120.2' + area-id: '1.1.1.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - address: '10.19.120.3' + config: + address: '10.19.120.3' + area-id: '2.2.2.2' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - name: 'Loopback100' + subinterfaces: + subinterface: + - index: 0 + openconfig-if-ip:ipv4: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + metric: 20 + priority: 20 + hello-interval: 10 + dead-interval-minimal: false + dead-interval: 40 + mtu-ignore: true + network-type: 'openconfig-ospf-types:POINT_TO_POINT_NETWORK' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + expected_config_requests: + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + area-id: '2.2.2.2' + dead-interval: 40 + hello-interval: 10 + metric: 20 + mtu-ignore: true + priority: 20 + - address: '10.10.120.1' + config: + address: '10.10.120.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 5 + dead-interval-minimal: true + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile1' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + enable-bfd: + config: + enabled: true + bfd-profile: 'profile3' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '0.0.0.0' + config: + address: '0.0.0.0' + network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' + - address: '10.10.120.2' + config: + address: '10.10.120.2' + area-id: '1.1.1.1' + authentication-type: 'MD5HMAC' + authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication-key-encrypted: true + hello-multiplier: 2 + dead-interval-minimal: true + - address: '10.10.120.3' + config: + address: '10.10.120.3' + area-id: '2.2.2.2' diff --git a/tests/unit/modules/network/sonic/test_sonic_ospfv2_interfaces.py b/tests/unit/modules/network/sonic/test_sonic_ospfv2_interfaces.py new file mode 100644 index 000000000..c36f199c7 --- /dev/null +++ b/tests/unit/modules/network/sonic/test_sonic_ospfv2_interfaces.py @@ -0,0 +1,96 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible_collections.dellemc.enterprise_sonic.tests.unit.compat.mock import ( + patch, +) +from ansible_collections.dellemc.enterprise_sonic.plugins.modules import ( + sonic_ospfv2_interfaces, +) +from ansible_collections.dellemc.enterprise_sonic.tests.unit.modules.utils import ( + set_module_args, +) +from .sonic_module import TestSonicModule + + +class TestSonicOspfv2InterfacesModule(TestSonicModule): + module = sonic_ospfv2_interfaces + + @classmethod + def setUpClass(cls): + cls.mock_facts_edit_config = patch( + "ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.facts.ospfv2_interfaces.ospfv2_interfaces.edit_config" + ) + cls.mock_config_edit_config = patch( + "ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.config.ospfv2_interfaces.ospfv2_interfaces.edit_config" + ) + cls.mock_bgp_utils_edit_config = patch( + "ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.bgp_utils.edit_config" + ) + cls.mock_get_interface_naming_mode = patch( + "ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.utils.get_device_interface_naming_mode" + ) + cls.fixture_data = cls.load_fixtures('sonic_ospfv2_interfaces.yaml') + + def setUp(self): + super(TestSonicOspfv2InterfacesModule, self).setUp() + self.facts_edit_config = self.mock_facts_edit_config.start() + self.config_edit_config = self.mock_config_edit_config.start() + self.utils_edit_config = self.mock_bgp_utils_edit_config.start() + + self.facts_edit_config.side_effect = self.facts_side_effect + self.config_edit_config.side_effect = self.config_side_effect + self.utils_edit_config.side_effect = self.facts_side_effect + + self.get_interface_naming_mode = self.mock_get_interface_naming_mode.start() + self.get_interface_naming_mode.return_value = 'standard' + + def tearDown(self): + super(TestSonicOspfv2InterfacesModule, self).tearDown() + self.mock_facts_edit_config.stop() + self.mock_config_edit_config.stop() + self.mock_bgp_utils_edit_config.stop() + self.mock_get_interface_naming_mode.stop() + + def test_sonic_ospfv2_interfaces_merged_01(self): + set_module_args(self.fixture_data['merged_01']['module_args']) + self.initialize_facts_get_requests(self.fixture_data['merged_01']['existing_ospfv2_config']) + self.initialize_config_requests(self.fixture_data['merged_01']['expected_config_requests']) + result = self.execute_module(changed=True) + self.validate_config_requests() + + def test_sonic_ospfv2_interfaces_merged_02(self): + set_module_args(self.fixture_data['merged_02']['module_args']) + self.initialize_facts_get_requests(self.fixture_data['merged_02']['existing_ospfv2_config']) + self.initialize_config_requests(self.fixture_data['merged_02']['expected_config_requests']) + result = self.execute_module(changed=True) + self.validate_config_requests() + + def test_sonic_ospfv2_interfaces_deleted_01(self): + set_module_args(self.fixture_data['deleted_01']['module_args']) + self.initialize_facts_get_requests(self.fixture_data['deleted_01']['existing_ospfv2_config']) + self.initialize_config_requests(self.fixture_data['deleted_01']['expected_config_requests']) + result = self.execute_module(changed=True) + self.validate_config_requests() + + def test_sonic_ospfv2_interfaces_deleted_02(self): + set_module_args(self.fixture_data['deleted_02']['module_args']) + self.initialize_facts_get_requests(self.fixture_data['deleted_02']['existing_ospfv2_config']) + self.initialize_config_requests(self.fixture_data['deleted_02']['expected_config_requests']) + result = self.execute_module(changed=True) + self.validate_config_requests() + + def test_sonic_ospfv2_interfaces_replaced_01(self): + set_module_args(self.fixture_data['replaced_01']['module_args']) + self.initialize_facts_get_requests(self.fixture_data['replaced_01']['existing_ospfv2_config']) + self.initialize_config_requests(self.fixture_data['replaced_01']['expected_config_requests']) + result = self.execute_module(changed=True) + self.validate_config_requests() + + def test_sonic_ospfv2_interfaces_overridden_01(self): + set_module_args(self.fixture_data['overridden_01']['module_args']) + self.initialize_facts_get_requests(self.fixture_data['overridden_01']['existing_ospfv2_config']) + self.initialize_config_requests(self.fixture_data['overridden_01']['expected_config_requests']) + result = self.execute_module(changed=True) + self.validate_config_requests() From 1f486842abd4ea343050e6182966462d1bc2afe7 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Wed, 12 Jun 2024 20:58:28 +0530 Subject: [PATCH 02/13] Addressing review changes --- .../ospfv2_interfaces/ospfv2_interfaces.py | 8 +- .../ospfv2_interfaces/ospfv2_interfaces.py | 163 ++++++++--------- .../ospfv2_interfaces/ospfv2_interfaces.py | 28 ++- plugins/modules/sonic_ospfv2_interfaces.py | 72 ++++---- .../sonic_ospfv2_interfaces/defaults/main.yml | 66 +++---- .../fixtures/sonic_ospfv2_interfaces.yaml | 168 +++++++++++------- 6 files changed, 257 insertions(+), 248 deletions(-) diff --git a/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py index efba81959..681275cd9 100644 --- a/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/argspec/ospfv2_interfaces/ospfv2_interfaces.py @@ -58,10 +58,10 @@ def __init__(self, **kwargs): 'options': { 'address': {'type': 'str'}, 'area_id': {'type': 'str'}, - 'auth_pwd': { + 'authentication': { 'options': { 'encrypted': {'type': 'bool'}, - 'pwd': {'no_log': True, 'required': True, 'type': 'str'} + 'password': {'no_log': True, 'required': True, 'type': 'str'} }, 'type': 'dict' }, @@ -73,12 +73,12 @@ def __init__(self, **kwargs): 'dead_interval': {'type': 'int'}, 'hello_interval': {'type': 'int'}, 'hello_multiplier': {'type': 'int'}, - 'message_digest_pwd': { + 'md_authentication': { 'elements': 'dict', 'options': { 'encrypted': {'type': 'bool'}, 'key_id': {'required': True, 'type': 'int'}, - 'pwd': {'no_log': True, 'type': 'str'} + 'md5key': {'no_log': True, 'type': 'str'} }, 'type': 'list' }, diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index 45777a1b2..9ff7bf416 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -44,18 +44,13 @@ TEST_KEYS = [ {'config': {'name': ''}}, {'ospf_attributes': {'address': ''}}, - {'message_digest_pwd': {'key_id': ''}} + {'md_authentication': {'key_id': ''}} ] -TEST_KEYS_delete_diff = [ - {'config': {'name': ''}}, - {'ospf_attributes': {'address': ''}}, - {'message_digest_pwd': {'key_id': ''}} -] TEST_KEYS_overridden_diff = [ {'config': {'name': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}}, {'ospf_attributes': {'address': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}}, - {'message_digest_pwd': {'key_id': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}} + {'md_authentication': {'key_id': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}} ] ospf_int_attributes = { @@ -67,13 +62,13 @@ 'ospf_attributes': { 'address': '/if-addresses={}', 'area_id': '/if-addresses={}/config/area-id', - 'auth_pwd': '/if-addresses={}/config/authentication-key', + 'authentication': '/if-addresses={}/config/authentication-key', 'authentication_type': '/if-addresses={}/config/authentication-type', 'cost': '/if-addresses={}/config/metric', 'dead_interval': '/if-addresses={}/config/dead-interval', 'hello_interval': '/if-addresses={}/config/hello-interval', 'hello_multiplier': '/if-addresses={}/config/dead-interval-minimal', - 'message_digest_pwd': '/if-addresses={}/md-authentications/md-authentication={}', + 'md_authentication': '/if-addresses={}/md-authentications/md-authentication={}', 'mtu_ignore': '/if-addresses={}/config/mtu-ignore', 'priority': '/if-addresses={}/config/priority', 'retransmit_interval': '/if-addresses={}/config/retransmission-interval', @@ -145,7 +140,6 @@ def execute_module(self): new_config = changed_ospfv2_interfaces_facts old_config = existing_ospfv2_interfaces_facts if self._module.check_mode: - result.pop('after', None) new_commands = deepcopy(commands) self._add_default_address(new_commands) self._add_default_address(new_config) @@ -154,7 +148,7 @@ def execute_module(self): if self._module.params['state'] == 'overridden': new_config = get_new_config(new_commands, old_config, TEST_KEYS_overridden_diff) else: - new_config = get_new_config(new_commands, old_config, TEST_KEYS_delete_diff) + new_config = get_new_config(new_commands, old_config, TEST_KEYS) self._add_default_address(new_config) self.sort_lists_in_config(new_config) new_config = self._get_generated_config(new_commands, new_config, self._module.params['state']) @@ -163,13 +157,7 @@ def execute_module(self): result['after(generated)'] = remove_empties_from_list(new_config) if self._module._diff: - self._add_default_address(old_config) - self._add_default_address(new_config) - self.sort_lists_in_config(old_config) - self.sort_lists_in_config(new_config) result['diff'] = get_formatted_config_diff(old_config, new_config, self._module._verbosity) - self._strip_default_address(old_config) - self._strip_default_address(new_config) result['warnings'] = warnings return result @@ -207,26 +195,24 @@ def set_state(self, want, have): commands, requests = [], [] state = self._module.params['state'] - if state == 'overridden': - commands, requests = self._state_overridden(want, have) + if state == 'overridden' or state == 'replaced': + commands, requests = self._state_replaced_or_overridden(want, have) elif state == 'deleted': commands, requests = self._state_deleted(want, have) elif state == 'merged': commands, requests = self._state_merged(want, have) - elif state == 'replaced': - commands, requests = self._state_replaced(want, have) return commands, requests - def _state_replaced(self, want, have): - """ The command generator when state is replaced + def _state_replaced_or_overridden(self, want, have): + """ The command generator when state is replaced or overridden :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands, requests = [], [] - add_config, del_config = self._get_replaced_config(want, have) + add_config, del_config = self._get_replaced_overridden_config(want, have) if del_config: del_commands, del_requests = self.get_delete_ospf_interfaces_commands_requests(del_config, have, False) if len(del_requests) > 0: @@ -238,34 +224,11 @@ def _state_replaced(self, want, have): mod_requests = self.get_create_ospf_interfaces_requests(add_config, []) if len(mod_requests) > 0: self._strip_default_address(add_config) - commands.extend(update_states(add_config, 'replaced')) + commands.extend(update_states(add_config, self._module.params['state'])) requests.extend(mod_requests) return commands, requests - def _state_overridden(self, want, have): - """ The command generator when state is overridden - - :rtype: A list - :returns: the commands necessary to migrate the current configuration - to the desired configuration - """ - commands, requests = [], [] - diff = get_diff(want, have, TEST_KEYS) - diff2 = get_diff(have, want, TEST_KEYS) - if diff or diff2: - del_commands, del_requests = self.get_delete_ospf_interfaces_commands_requests(have, have, True) - if len(del_requests) > 0: - self._strip_default_address(del_commands) - commands.extend(update_states(del_commands, 'deleted')) - requests.extend(del_requests) - mod_requests = self.get_create_ospf_interfaces_requests(want, []) - if len(mod_requests) > 0: - self._strip_default_address(want) - commands.extend(update_states(want, 'overridden')) - requests.extend(mod_requests) - return commands, requests - def _state_merged(self, want, have): """ The command generator when state is merged @@ -278,7 +241,7 @@ def _state_merged(self, want, have): if commands and len(requests) > 0: self._strip_default_address(commands) - commands = update_states(commands, "merged") + commands = update_states(commands, 'merged') else: commands = [] @@ -304,14 +267,15 @@ def _state_deleted(self, want, have): if del_commands and len(requests) > 0: self._strip_default_address(del_commands) - commands = update_states(del_commands, "deleted") + commands = update_states(del_commands, 'deleted') else: commands = [] return commands, requests - def _get_replaced_config(self, want, have): + def _get_replaced_overridden_config(self, want, have): add_config, del_config = [], [] + state = self._module.params['state'] for conf in want: intf_name = conf.get('name') have_conf = next((cfg for cfg in have if cfg['name'] == intf_name), None) @@ -324,7 +288,7 @@ def _get_replaced_config(self, want, have): if attr not in have_conf: add_cfg[attr] = conf[attr] else: - if attr == "bfd": + if attr == 'bfd': for bfd_attr in ['enable', 'bfd_profile']: if bfd_attr not in have_conf: add_cfg.setdefault(attr, {}) @@ -334,7 +298,7 @@ def _get_replaced_config(self, want, have): del_cfg.setdefault(attr, {}) add_cfg[attr][bfd_attr] = conf[attr][bfd_attr] del_cfg[attr][bfd_attr] = have_conf[attr][bfd_attr] - elif attr == "network": + elif attr == 'network': if conf[attr] != have_conf[attr]: add_cfg[attr] = conf[attr] del_cfg[attr] = have_conf[attr] @@ -343,7 +307,8 @@ def _get_replaced_config(self, want, have): ospf_attr = conf.get(attr, []) match_ospf_attr = have_conf.get(attr, []) if not ospf_attr and match_ospf_attr: - del_cfg[attr] = match_ospf_attr + del_cfg.setdefault(attr, []) + del_cfg[attr].append({'address': match_ospf_attr['address']}) elif ospf_attr and not match_ospf_attr: add_cfg[attr] = ospf_attr elif ospf_attr and match_ospf_attr: @@ -362,6 +327,12 @@ def _get_replaced_config(self, want, have): del_ospf_attr['address'] = address del_cfg.setdefault(attr, []) del_cfg[attr].append(del_ospf_attr) + for match_ospf_list in match_ospf_attr: + address = match_ospf_list.get('address') + ospf_list = next((list for list in ospf_attr if list.get('address') == address), None) + if not ospf_list: + del_cfg.setdefault(attr, []) + del_cfg[attr].append({'address': address}) elif attr in have_conf: del_cfg[attr] = have_conf[attr] if add_cfg: @@ -370,6 +341,13 @@ def _get_replaced_config(self, want, have): if del_cfg: del_cfg['name'] = intf_name del_config.append(del_cfg) + + if state == 'overridden': + for conf in have: + intf_name = conf.get('name') + want_conf = next((cfg for cfg in want if cfg['name'] == intf_name), None) + if not want_conf: + del_config.append({'name': intf_name}) return add_config, del_config def _get_replaced_config_for_ospf_attributes(self, want, have): @@ -404,10 +382,9 @@ def _get_replaced_config_for_ospf_attributes(self, want, have): if ospf_attr not in have: add_config[ospf_attr] = want[ospf_attr] elif want[ospf_attr] != have[ospf_attr]: - if ospf_attr != 'message_digest_pwd': - if want[ospf_attr] != have[ospf_attr]: - add_config[ospf_attr] = want[ospf_attr] - del_config[ospf_attr] = have[ospf_attr] + if ospf_attr != 'md_authentication': + add_config[ospf_attr] = want[ospf_attr] + del_config[ospf_attr] = have[ospf_attr] else: have_mdkeys = have[ospf_attr] conf_mdkeys = want[ospf_attr] @@ -420,6 +397,10 @@ def _get_replaced_config_for_ospf_attributes(self, want, have): del_mdkeys.append(match_key) else: add_mdkeys.append(conf_key) + for match_key in have_mdkeys: + conf_key = next((key for key in conf_mdkeys if key['key_id'] == match_key['key_id']), None) + if not conf_key: + del_mdkeys.append(match_key) if add_mdkeys: add_config[ospf_attr] = add_mdkeys if del_mdkeys: @@ -474,19 +455,19 @@ def get_create_ospf_interfaces_requests(self, commands, have): self.update_dict(ospf_list, ospf_attr_dict, 'retransmit_interval', 'retransmission-interval') self.update_dict(ospf_list, ospf_attr_dict, 'transmit_delay', 'transmit-delay') - if 'auth_pwd' in ospf_list: - self.update_dict(ospf_list['auth_pwd'], ospf_attr_dict, 'pwd', 'authentication-key') - self.update_dict(ospf_list['auth_pwd'], ospf_attr_dict, 'encrypted', 'authentication-key-encrypted') + if 'authentication' in ospf_list: + self.update_dict(ospf_list['authentication'], ospf_attr_dict, 'password', 'authentication-key') + self.update_dict(ospf_list['authentication'], ospf_attr_dict, 'encrypted', 'authentication-key-encrypted') - if 'message_digest_pwd' in ospf_list: - for mdkeys in ospf_list['message_digest_pwd']: + if 'md_authentication' in ospf_list: + for mdkeys in ospf_list['md_authentication']: md_config = {} self.update_dict(mdkeys, md_config, 'key_id', 'authentication-key-id') if md_config: md_config.setdefault('config', {}) self.update_dict(mdkeys, md_config['config'], 'key_id', 'authentication-key-id') self.update_dict(mdkeys, md_config['config'], 'encrypted', 'authentication-key-encrypted') - self.update_dict(mdkeys, md_config['config'], 'pwd', 'authentication-md5-key') + self.update_dict(mdkeys, md_config['config'], 'md5key', 'authentication-md5-key') if md_config: ospf_md_configs_list.append(md_config) @@ -499,13 +480,13 @@ def get_create_ospf_interfaces_requests(self, commands, have): self.update_dict(ospf_list, ospf_attr_dict['config'], 'address', 'address') self.update_dict(ospf_list, ospf_attr_dict, 'address', 'address') ospf_attr_configs.append(ospf_attr_dict) - elif attr == "bfd": + elif attr == 'bfd': self.update_dict(cmd[attr], bfd_dict, 'enable', 'enabled') self.update_dict(cmd[attr], bfd_dict, 'bfd_profile', 'bfd-profile') - elif attr == "network": + elif attr == 'network': network_type = cmd.get('network') if network_type: - network_type = "openconfig-ospf-types:" + network_type.upper() + "_NETWORK" + network_type = 'openconfig-ospf-types:' + network_type.upper() + '_NETWORK' ospf_default = False for ospf_list in ospf_attr_configs: if ospf_list['address'] == DEFAULT_ADDRESS: @@ -522,16 +503,16 @@ def get_create_ospf_interfaces_requests(self, commands, have): if ospf_attr_configs: payload = { - "openconfig-ospfv2-ext:ospfv2": { - "if-addresses": ospf_attr_configs + 'openconfig-ospfv2-ext:ospfv2': { + 'if-addresses': ospf_attr_configs } } requests.append({'path': ospf_path, 'method': PATCH, 'data': payload}) if bfd_dict: payload = { 'openconfig-ospfv2-ext:ospfv2': { - "if-addresses": [{ - 'address': '0.0.0.0', + 'if-addresses': [{ + 'address': DEFAULT_ADDRESS, 'enable-bfd': {'config': bfd_dict} }] } @@ -558,20 +539,20 @@ def get_delete_ospf_interfaces_commands_requests(self, commands, have, is_delete for attr in cmd: if attr == 'name': continue - if attr == "bfd": - if "enable" in cmd.get(attr, {}) and "enable" in match_have.get(attr, {}): + if attr == 'bfd': + if 'enable' in cmd.get(attr, {}) and 'enable' in match_have.get(attr, {}): path = ospf_path + ospf_int_attributes['bfd']['enable'].format(DEFAULT_ADDRESS) requests.append({'path': path, 'method': DELETE}) del_cmd.setdefault(attr, {}) del_cmd[attr]['enable'] = match_have[attr]['enable'] - if "bfd_profile" in match_have.get(attr, {}): + if 'bfd_profile' in match_have.get(attr, {}): del_cmd[attr]['bfd_profile'] = match_have[attr]['bfd_profile'] - elif "bfd_profile" in cmd.get(attr, {}) and "bfd_profile" in match_have.get(attr, {}): + elif 'bfd_profile' in cmd.get(attr, {}) and 'bfd_profile' in match_have.get(attr, {}): path = ospf_path + ospf_int_attributes['bfd']['bfd_profile'].format(DEFAULT_ADDRESS) requests.append({'path': path, 'method': DELETE}) del_cmd.setdefault(attr, {}) del_cmd[attr]['bfd_profile'] = match_have[attr]['bfd_profile'] - elif attr == 'network' and "network" in cmd.get(attr, {}) and "network" in match_have.get(attr, {}): + elif attr == 'network' and 'network' in cmd.get(attr, {}) and 'network' in match_have.get(attr, {}): path = ospf_path + ospf_int_attributes['network'].format(DEFAULT_ADDRESS) requests.append({'path': path, 'method': DELETE}) del_cmd[attr] = match_have[attr] @@ -615,14 +596,14 @@ def get_delete_ospf_attributes_commands_requests(self, match_ospf_attrs, ospf_at commands.append(del_ospf_attr) continue for attr in o_attr: - if attr not in ('message_digest_pwd', 'address'): + if attr not in ('md_authentication', 'address'): if attr in m_attr and o_attr[attr] is not None and m_attr[attr] is not None: requests.append({ 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(address), 'method': DELETE }) del_ospf_attr[attr] = m_attr[attr] - elif attr == 'message_digest_pwd': + elif attr == 'md_authentication': if o_attr.get(attr) is None: del_mkeys = [] for key in m_attr.get(attr, []): @@ -662,13 +643,13 @@ def get_delete_ospf_attributes_commands_requests(self, match_ospf_attrs, ospf_at def get_delete_all_ospf_attributes_per_address_commands_requests(self, m_attr, ospf_path): commands, requests = {}, [] for attr in m_attr: - if attr not in ('message_digest_pwd', 'address'): + if attr not in ('md_authentication', 'address'): requests.append({ 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address']), 'method': DELETE }) commands[attr] = m_attr[attr] - elif attr == 'message_digest_pwd': + elif attr == 'md_authentication': del_mkeys = [] for key in m_attr.get(attr, []): requests.append({ @@ -688,8 +669,8 @@ def sort_lists_in_config(self, config): if cfg.get('ospf_attributes', []): cfg['ospf_attributes'].sort(key=lambda x: x['address']) for ospf_attr in cfg.get('ospf_attributes', []): - if ospf_attr.get('message_digest_pwd', []): - ospf_attr['message_digest_pwd'].sort(key=lambda x: x['key_id']) + if ospf_attr.get('md_authentication', []): + ospf_attr['md_authentication'].sort(key=lambda x: x['key_id']) def _strip_default_address(self, conf): if conf: @@ -707,20 +688,20 @@ def _add_default_address(self, conf): def get_ospf_intf_uri(self, intf_name, sub_intf=0): intf_name = intf_name.replace('/', '%2f') - ospf_intf_uri = "/data/openconfig-interfaces:interfaces/interface={}".format(intf_name) - if intf_name.startswith("Vlan"): - ospf_intf_uri += "/openconfig-vlan:routed-vlan" + ospf_intf_uri = '/data/openconfig-interfaces:interfaces/interface={}'.format(intf_name) + if intf_name.startswith('Vlan'): + ospf_intf_uri += '/openconfig-vlan:routed-vlan' else: - ospf_intf_uri += "/subinterfaces/subinterface={}".format(sub_intf) + ospf_intf_uri += '/subinterfaces/subinterface={}'.format(sub_intf) return ospf_intf_uri def get_ospf_uri(self, intf_name, sub_intf=0): ospf_uri = self.get_ospf_intf_uri(intf_name, sub_intf) - ospf_uri += "/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2" + ospf_uri += '/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' return ospf_uri def get_ospf_if_and_subif(self, intf_name): - return intf_name.split(".") if "." in intf_name else (intf_name, 0) + return intf_name.split('.') if '.' in intf_name else (intf_name, 0) def update_dict(self, src, dest, src_key, dest_key, value=False): if not value: @@ -753,15 +734,15 @@ def _get_generated_config(self, want, new_config, state): for o_attr in cmd_ospf_attr: if len(o_attr) > 1: md_keys = [] - o_md_keys = o_attr.get('message_digest_pwd', []) + o_md_keys = o_attr.get('md_authentication', []) if o_md_keys: for key in o_md_keys: if len(key) > 1: md_keys.append(key) if not md_keys: - o_attr.pop('message_digest_pwd', None) + o_attr.pop('md_authentication', None) else: - o_attr['message_digest_pwd'] = md_keys + o_attr['md_authentication'] = md_keys if len(o_attr) > 1: ospf_attr.append(o_attr) if ospf_attr: diff --git a/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py index de6898868..d447b7e5e 100644 --- a/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py @@ -29,6 +29,8 @@ ) from ansible.module_utils.connection import ConnectionError +DEFAULT_ADDRESS = '0.0.0.0' + class Ospfv2_interfacesFacts(object): """ The sonic ospfv2_interfaces fact class @@ -146,17 +148,13 @@ def get_ospfv2_interfaces(self): self.update_dict(attr, 'transmit_delay', config.get('transmit-delay')) if 'authentication-key' in config: - attr['auth_pwd'] = {} - self.update_dict(attr['auth_pwd'], 'pwd', config.get('authentication-key')) - self.update_dict(attr['auth_pwd'], 'encrypted', config.get('authentication-key-encrypted')) - - if 'dead-interval-minimal' in config: - dead_interval_minimal = config.get('dead-interval-minimal') - if dead_interval_minimal: - self.update_dict(attr, 'hello_multiplier', config.get('hello-multiplier')) - else: - self.update_dict(attr, 'dead_interval', config.get('dead-interval')) - elif 'dead-interval' in config: + attr['authentication'] = {} + self.update_dict(attr['authentication'], 'password', config.get('authentication-key')) + self.update_dict(attr['authentication'], 'encrypted', config.get('authentication-key-encrypted')) + + if config.get('dead-interval-minimal'): + self.update_dict(attr, 'hello_multiplier', config.get('hello-multiplier')) + else: self.update_dict(attr, 'dead_interval', config.get('dead-interval')) if 'network-type' in config: @@ -170,14 +168,14 @@ def get_ospfv2_interfaces(self): if md_config: md_key = {} self.update_dict(md_key, 'key_id', md_config.get('authentication-key-id')) - self.update_dict(md_key, 'pwd', md_config.get('authentication-md5-key')) + self.update_dict(md_key, 'md5key', md_config.get('authentication-md5-key')) self.update_dict(md_key, 'encrypted', md_config.get('authentication-key-encrypted')) if md_key: md_keys.append(md_key) - self.update_dict(attr, 'message_digest_pwd', md_keys) + self.update_dict(attr, 'md_authentication', md_keys) if attr: - if addr != '0.0.0.0': + if addr != DEFAULT_ADDRESS: attr['address'] = addr ospf_attributes.append(attr) @@ -189,7 +187,7 @@ def get_ospfv2_interfaces(self): return ospf_configs def update_dict(self, dict, key, value, parent_key=None): - if value is not None and value not in [{}, [], ()]: + if value not in [None, {}, []]: if parent_key: dict.setdefault(parent_key, {}) dict[parent_key][key] = value diff --git a/plugins/modules/sonic_ospfv2_interfaces.py b/plugins/modules/sonic_ospfv2_interfaces.py index 5dc4153f5..5dca34e53 100644 --- a/plugins/modules/sonic_ospfv2_interfaces.py +++ b/plugins/modules/sonic_ospfv2_interfaces.py @@ -45,7 +45,7 @@ options: config: description: - - Specifies the OSPFv2 interface mode related configuration. + - Specifies the OSPFv2 interface configurations. type: list elements: dict suboptions: @@ -56,8 +56,8 @@ - Full name of the interface, i.e. Ethernet1. ospf_attributes: description: - - Configure OSPFv2 attributes based on Interface IPv4 address. - - In case if IP address is not specified, default value will be set. + - Specifies OSPFv2 configurations for the interface. + - If I(address) is not specified, the IPv4 address of the interface is considered. - I(dead_interval) and I(hello_multiplier) are mutually exclusive. type: list elements: dict @@ -65,7 +65,7 @@ address: description: - Interface IPv4 address to be set. - - If no address is set, default value is considered. + - Specifies the interface IPv4 address. type: str area_id: description: @@ -82,22 +82,22 @@ - 'MD5HMAC' - 'NONE' - 'TEXT' - auth_pwd: + authentication: description: - Configure OSPFv2 plain text authentication type password. - Authentication key shall be max 8 charater long. type: dict suboptions: - pwd: + password: description: - - Configure authentication password. - - Plain text passwords i.e. password with encrypted=False will be encrypted in running-config, so idempotency will - not be maintained and every time the output will come as changed=True. + - Specifies the authentication password. + - Plain text password i.e. password with I(encrypted=false) will be stored in encrypted format in running-config, so idempotency will + not be maintained and hence the task output will always be I(changed=true). type: str required: true encrypted: description: - - Indicates whether the password is encrypted text. + - Indicates whether the password is in encrypted format. type: bool cost: description: @@ -116,27 +116,27 @@ description: - Configure OSPFv2 neighbour hello interval (1 to 65535). type: int - message_digest_pwd: + md_authentication: description: - - Configure OSPFv2 message digest keys and passwords. + - Configure OSPFv2 message digest keys and password. - Uses MD5 algorithm. type: list elements: dict suboptions: key_id: description: - - Configure OSPFv2 message digest key ID (1 to 255). + - Specifies the OSPFv2 message digest key ID (1 to 255). type: int required: True - pwd: + md5key: description: - - Configure OSPFv2 message digest password. - - Plain text passwords i.e. password with encrypted=False will be encrypted in running-config, so idempotency will - not be maintained and every time the output will come as changed=True. + - Specifies the OSPFv2 message digest password. + - Plain text password i.e. password with I(encrypted=false) will be stored in encrypted format in running-config, so idempotency will + not be maintained and hence the task output will always be I(changed=true). type: str encrypted: description: - - Indicates whether the password is encrypted text. + - Indicates whether the password is in encrypted format. type: bool mtu_ignore: description: @@ -238,8 +238,8 @@ mtu_ignore: True - address: '10.10.120.1' authentication_type: 'NONE' - auth_pwd: - pwd: 'pass2' + authentication: + password: 'pass2' - address: '10.19.119.1' bfd: enable: True @@ -357,8 +357,8 @@ mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'password' + authentication: + password: 'password' hello_multiplier: 5 bfd: enable: True @@ -369,8 +369,8 @@ - area_id: '3.3.3.3' address: '10.19.120.2' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'password' + authentication: + password: 'password' hello_multiplier: 5 bfd: enable: True @@ -455,13 +455,13 @@ mtu_ignore: True - address: '10.10.120.1' authentication_type: 'NONE' - auth_pwd: - pwd: 'pass2' + authentication: + password: 'pass2' - address: '10.19.119.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' + md5key: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' encrypted: True bfd: enable: True @@ -555,13 +555,13 @@ mtu_ignore: True - address: '10.10.120.1' authentication_type: 'NONE' - auth_pwd: - pwd: 'pass2' + authentication: + password: 'pass2' - address: '10.19.119.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' + md5key: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' encrypted: True bfd: enable: True @@ -654,13 +654,13 @@ mtu_ignore: True - address: '10.10.120.1' authentication_type: 'NONE' - auth_pwd: - pwd: 'pass2' + authentication: + password: 'pass2' - address: '10.19.119.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' + md5key: 'U2FsdGVkX1/Bq/+x8a3fsBo9ZrAX56ynmPKnRM87kfQ=' encrypted: True bfd: enable: True diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml index db3767574..399b7ff0b 100644 --- a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml +++ b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml @@ -42,8 +42,8 @@ tests: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -55,8 +55,8 @@ tests: - area_id: '3.3.3.3' address: '10.19.120.2' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -76,12 +76,12 @@ tests: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - key_id: 20 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 network: broadcast @@ -104,9 +104,9 @@ tests: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - name: "{{ vlan2 }}" bfd: @@ -127,9 +127,9 @@ tests: - address: '10.10.120.1' mtu_ignore: True authentication_type: 'TEXT' - message_digest_pwd: + md_authentication: - key_id: 30 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True network: point_to_point bfd: @@ -142,9 +142,9 @@ tests: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - name: "{{ vlan2 }}" bfd: @@ -155,15 +155,15 @@ tests: - area_id: '1.1.1.1' address: '10.19.120.2' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - area_id: '2.2.2.2' address: '10.19.120.3' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - name: "{{ lo1 }}" @@ -176,8 +176,8 @@ tests: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -198,8 +198,8 @@ tests: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -214,9 +214,9 @@ tests: ospf_attributes: - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - name: "{{ po1 }}" ospf_attributes: @@ -257,8 +257,8 @@ tests: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 - area_id: '4.4.4.4' @@ -267,9 +267,9 @@ tests: hello_multiplier: 2 - address: '10.10.120.2' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True bfd: enable: True @@ -282,9 +282,9 @@ tests: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - name: test_case_replace_01 description: Replace existing OSPFv2 interface configurations for interface level @@ -308,8 +308,8 @@ tests: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -347,8 +347,8 @@ tests: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: diff --git a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml index c7fae66a4..a863e53fc 100644 --- a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml +++ b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml @@ -12,8 +12,8 @@ merged_01: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -25,8 +25,8 @@ merged_01: - area_id: '3.3.3.3' address: '10.19.120.2' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -39,9 +39,9 @@ merged_01: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True state: merged existing_ospfv2_config: @@ -157,9 +157,9 @@ merged_02: - address: '10.10.120.1' mtu_ignore: True authentication_type: 'TEXT' - message_digest_pwd: + md_authentication: - key_id: 30 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True network: point_to_point bfd: @@ -172,9 +172,9 @@ merged_02: hello_multiplier: 2 - address: '10.10.120.1' authentication_type: 'NONE' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - name: 'Vlan100' bfd: @@ -185,15 +185,15 @@ merged_02: - area_id: '1.1.1.1' address: '10.19.120.2' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - area_id: '2.2.2.2' address: '10.19.120.3' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - name: 'Loopback100' @@ -206,8 +206,8 @@ merged_02: mtu_ignore: True - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 bfd: @@ -442,9 +442,9 @@ deleted_01: cost: 15 hello_multiplier: 5 - address: '10.10.120.1' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True - name: 'PortChannel100' ospf_attributes: @@ -456,9 +456,9 @@ deleted_01: network: 'broadcast' ospf_attributes: - address: '10.10.120.1' - message_digest_pwd: + md_authentication: - key_id: 10 - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True state: deleted existing_ospfv2_config: @@ -873,8 +873,8 @@ replaced_01: priority: 20 - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 - name: 'Loopback100' @@ -887,8 +887,8 @@ replaced_01: - address: '10.10.120.2' area_id: '1.1.1.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - address: '10.10.120.3' @@ -1091,6 +1091,32 @@ replaced_01: method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/enable-bfd' method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/metric' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/md-authentications/md-authentication=10' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/dead-interval-minimal' + method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'patch' data: @@ -1145,8 +1171,8 @@ overridden_01: priority: 20 - address: '10.10.120.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 - name: 'Loopback100' @@ -1159,8 +1185,8 @@ overridden_01: - address: '10.10.120.2' area_id: '1.1.1.1' authentication_type: 'MD5HMAC' - auth_pwd: - pwd: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + authentication: + password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - address: '10.10.120.3' @@ -1343,48 +1369,56 @@ overridden_01: hello-multiplier: 5 dead-interval-minimal: true expected_config_requests: - - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' - method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f6/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'delete' - - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' - method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'delete' - - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/dead-interval' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/metric' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/hello-interval' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/mtu-ignore' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/priority' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/enable-bfd' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/metric' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/md-authentications/md-authentication=10' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/dead-interval-minimal' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/area-id' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/authentication-key' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/authentication-type' + method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/dead-interval-minimal' method: 'delete' - - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' - method: 'patch' - data: - openconfig-ospfv2-ext:ospfv2: - if-addresses: - - address: '0.0.0.0' - config: - address: '0.0.0.0' - area-id: '2.2.2.2' - dead-interval: 40 - hello-interval: 10 - metric: 20 - mtu-ignore: true - priority: 20 - - address: '10.10.120.1' - config: - address: '10.10.120.1' - authentication-type: 'MD5HMAC' - authentication-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' - authentication-key-encrypted: true - hello-multiplier: 5 - dead-interval-minimal: true - - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' - method: 'patch' - data: - openconfig-ospfv2-ext:ospfv2: - if-addresses: - - address: '0.0.0.0' - enable-bfd: - config: - enabled: true - bfd-profile: 'profile1' - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'patch' data: @@ -1409,10 +1443,6 @@ overridden_01: data: openconfig-ospfv2-ext:ospfv2: if-addresses: - - address: '0.0.0.0' - config: - address: '0.0.0.0' - network-type: 'openconfig-ospf-types:BROADCAST_NETWORK' - address: '10.10.120.2' config: address: '10.10.120.2' From 987a631f31a1a3dfa4aec873d813cf8b620dbce4 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Wed, 12 Jun 2024 22:50:32 +0530 Subject: [PATCH 03/13] Sanity fix --- plugins/modules/sonic_ospfv2_interfaces.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/sonic_ospfv2_interfaces.py b/plugins/modules/sonic_ospfv2_interfaces.py index 5dca34e53..cca1abeae 100644 --- a/plugins/modules/sonic_ospfv2_interfaces.py +++ b/plugins/modules/sonic_ospfv2_interfaces.py @@ -91,8 +91,8 @@ password: description: - Specifies the authentication password. - - Plain text password i.e. password with I(encrypted=false) will be stored in encrypted format in running-config, so idempotency will - not be maintained and hence the task output will always be I(changed=true). + - Plain text password i.e. password with I(encrypted=false) will be stored in encrypted format in running-config, so idempotency will + not be maintained and hence the task output will always be I(changed=true). type: str required: true encrypted: From 20407b72beadb034c179698546a4a741f25a56dc Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Tue, 2 Jul 2024 20:22:07 +0530 Subject: [PATCH 04/13] Correcting address description --- plugins/modules/sonic_ospfv2_interfaces.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/modules/sonic_ospfv2_interfaces.py b/plugins/modules/sonic_ospfv2_interfaces.py index cca1abeae..62b4cb4c3 100644 --- a/plugins/modules/sonic_ospfv2_interfaces.py +++ b/plugins/modules/sonic_ospfv2_interfaces.py @@ -64,7 +64,6 @@ suboptions: address: description: - - Interface IPv4 address to be set. - Specifies the interface IPv4 address. type: str area_id: From 392c9d8b63f582a0c0a28ea06ebc2e30729aa2a6 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Tue, 23 Jul 2024 12:49:05 +0530 Subject: [PATCH 05/13] Normalize interface name --- .../ospfv2_interfaces/ospfv2_interfaces.py | 62 ++++++++----------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index 9ff7bf416..7686e5add 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -28,6 +28,7 @@ from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.utils import ( update_states, get_diff, + normalize_interface_name, remove_empties_from_list ) from ansible_collections.dellemc.enterprise_sonic.plugins.module_utils.network.sonic.utils.formatted_diff_utils import ( @@ -180,6 +181,7 @@ def set_config(self, existing_ospfv2_interfaces_facts): self._add_default_address(new_have) self.sort_lists_in_config(new_want) self.sort_lists_in_config(new_have) + normalize_interface_name(new_want, self._module) resp = self.set_state(new_want, new_have) return to_list(resp) @@ -301,38 +303,31 @@ def _get_replaced_overridden_config(self, want, have): elif attr == 'network': if conf[attr] != have_conf[attr]: add_cfg[attr] = conf[attr] - del_cfg[attr] = have_conf[attr] else: # attr = 'ospf_attributes' - ospf_attr = conf.get(attr, []) + ospf_attr = conf[attr] match_ospf_attr = have_conf.get(attr, []) - if not ospf_attr and match_ospf_attr: - del_cfg.setdefault(attr, []) - del_cfg[attr].append({'address': match_ospf_attr['address']}) - elif ospf_attr and not match_ospf_attr: - add_cfg[attr] = ospf_attr - elif ospf_attr and match_ospf_attr: - for ospf_list in ospf_attr: - address = ospf_list.get('address') - match_ospf_list = next((list for list in match_ospf_attr if list.get('address') == address), None) - if not match_ospf_list: - add_cfg[attr] = ospf_attr - else: - add_ospf_attr, del_ospf_attr = self._get_replaced_config_for_ospf_attributes(ospf_list, match_ospf_list) - if add_ospf_attr: - add_ospf_attr['address'] = address - add_cfg.setdefault(attr, []) - add_cfg[attr].append(add_ospf_attr) - if del_ospf_attr: - del_ospf_attr['address'] = address - del_cfg.setdefault(attr, []) - del_cfg[attr].append(del_ospf_attr) - for match_ospf_list in match_ospf_attr: - address = match_ospf_list.get('address') - ospf_list = next((list for list in ospf_attr if list.get('address') == address), None) - if not ospf_list: + for ospf_list in ospf_attr: + address = ospf_list.get('address') + match_ospf_list = next((o_list for o_list in match_ospf_attr if o_list.get('address') == address), None) + if not match_ospf_list: + add_cfg[attr] = ospf_attr + else: + add_ospf_attr, del_ospf_attr = self._get_replaced_config_for_ospf_attributes(ospf_list, match_ospf_list) + if add_ospf_attr: + add_ospf_attr['address'] = address + add_cfg.setdefault(attr, []) + add_cfg[attr].append(add_ospf_attr) + if del_ospf_attr: + del_ospf_attr['address'] = address del_cfg.setdefault(attr, []) - del_cfg[attr].append({'address': address}) + del_cfg[attr].append(del_ospf_attr) + for match_ospf_list in match_ospf_attr: + address = match_ospf_list.get('address') + ospf_list = next((o_list for o_list in ospf_attr if o_list.get('address') == address), None) + if not ospf_list: + del_cfg.setdefault(attr, []) + del_cfg[attr].append({'address': address}) elif attr in have_conf: del_cfg[attr] = have_conf[attr] if add_cfg: @@ -362,11 +357,9 @@ def _get_replaced_config_for_ospf_attributes(self, want, have): del_config['dead_interval'] = have['dead_interval'] elif want[ospf_attr] != have[ospf_attr]: add_config[ospf_attr] = want[ospf_attr] - del_config[ospf_attr] = have[ospf_attr] elif ospf_attr in have: del_config[ospf_attr] = have[ospf_attr] - continue - if ospf_attr == 'dead_interval': + elif ospf_attr == 'dead_interval': if ospf_attr in want: if ospf_attr not in have: add_config[ospf_attr] = want[ospf_attr] @@ -374,17 +367,16 @@ def _get_replaced_config_for_ospf_attributes(self, want, have): del_config['hello_interval'] = have['hello_interval'] elif want[ospf_attr] != have[ospf_attr]: add_config[ospf_attr] = want[ospf_attr] - del_config[ospf_attr] = have[ospf_attr] elif ospf_attr in have: del_config[ospf_attr] = have[ospf_attr] - continue - if ospf_attr in want: + elif ospf_attr in want: if ospf_attr not in have: add_config[ospf_attr] = want[ospf_attr] elif want[ospf_attr] != have[ospf_attr]: if ospf_attr != 'md_authentication': add_config[ospf_attr] = want[ospf_attr] - del_config[ospf_attr] = have[ospf_attr] + if ospf_attr == 'area_id': + del_config['area_id'] = have['area_id'] else: have_mdkeys = have[ospf_attr] conf_mdkeys = want[ospf_attr] From 42eae7bc2ba4452884aa57073c9acd7d5b1f3baa Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T <53558409+santhosh-kt@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:01:48 +0530 Subject: [PATCH 06/13] Update main.yml --- tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml index 95c12d043..9faaf66c9 100644 --- a/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml +++ b/tests/regression/roles/sonic_ospfv2_interfaces/tasks/main.yml @@ -11,7 +11,3 @@ - name: "Cleanup of {{ module_name }}" ansible.builtin.include_tasks: cleanup_tests.yaml - -- name: Display all variables/facts known for a host - ansible.builtin.debug: - var: hostvars[inventory_hostname].ansible_facts.test_reports From 1f06b9da597b2f4519287e37f60058e1b22e14c9 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Mon, 29 Jul 2024 13:28:31 +0530 Subject: [PATCH 07/13] Addressing review comments --- .../ospfv2_interfaces/ospfv2_interfaces.py | 106 +++++++++++------- .../ospfv2_interfaces/ospfv2_interfaces.py | 3 +- plugins/modules/sonic_ospfv2_interfaces.py | 2 +- .../sonic_ospfv2_interfaces/defaults/main.yml | 26 ++--- .../fixtures/sonic_ospfv2_interfaces.yaml | 22 ++-- 5 files changed, 91 insertions(+), 68 deletions(-) diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index 7686e5add..ec110b23c 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -14,6 +14,8 @@ __metaclass__ = type from copy import deepcopy +import re +import ipaddress from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -41,6 +43,7 @@ PATCH = 'patch' DELETE = 'delete' DEFAULT_ADDRESS = '0.0.0.0' +REGEX_IPV4_ADDRESS = r'^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$' TEST_KEYS = [ {'config': {'name': ''}}, @@ -54,7 +57,7 @@ {'md_authentication': {'key_id': '', '__delete_op': __DELETE_LEAFS_THEN_CONFIG_IF_NO_NON_KEY_LEAF}} ] -ospf_int_attributes = { +OSPF_INT_ATTRIBUTES = { 'bfd': { 'enable': '/if-addresses={}/enable-bfd', 'bfd_profile': '/if-addresses={}/enable-bfd/config/bfd-profile' @@ -181,7 +184,7 @@ def set_config(self, existing_ospfv2_interfaces_facts): self._add_default_address(new_have) self.sort_lists_in_config(new_want) self.sort_lists_in_config(new_have) - normalize_interface_name(new_want, self._module) + new_want = self._normalize_interface_name(new_want) resp = self.set_state(new_want, new_have) return to_list(resp) @@ -285,21 +288,20 @@ def _get_replaced_overridden_config(self, want, have): add_config.append(conf) else: add_cfg, del_cfg = {}, {} - for attr in ospf_int_attributes: + for attr in OSPF_INT_ATTRIBUTES: if attr in conf: if attr not in have_conf: add_cfg[attr] = conf[attr] else: if attr == 'bfd': for bfd_attr in ['enable', 'bfd_profile']: - if bfd_attr not in have_conf: - add_cfg.setdefault(attr, {}) - add_cfg[attr][bfd_attr] = conf[attr][bfd_attr] - elif conf[attr][bfd_attr] != have_conf[attr][bfd_attr]: - add_cfg.setdefault(attr, {}) - del_cfg.setdefault(attr, {}) - add_cfg[attr][bfd_attr] = conf[attr][bfd_attr] - del_cfg[attr][bfd_attr] = have_conf[attr][bfd_attr] + if bfd_attr in conf[attr]: + if bfd_attr not in have_conf: + add_cfg.setdefault(attr, {})[bfd_attr] = conf[attr][bfd_attr] + elif conf[attr][bfd_attr] != have_conf[attr][bfd_attr]: + add_cfg.setdefault(attr, {})[bfd_attr] = conf[attr][bfd_attr] + elif bfd_attr in have_conf[attr]: + del_cfg.setdefault(attr, {})[bfd_attr] = have_conf[attr][bfd_attr] elif attr == 'network': if conf[attr] != have_conf[attr]: add_cfg[attr] = conf[attr] @@ -311,23 +313,20 @@ def _get_replaced_overridden_config(self, want, have): address = ospf_list.get('address') match_ospf_list = next((o_list for o_list in match_ospf_attr if o_list.get('address') == address), None) if not match_ospf_list: - add_cfg[attr] = ospf_attr + add_cfg.setdefault(attr, []).append(ospf_list) else: add_ospf_attr, del_ospf_attr = self._get_replaced_config_for_ospf_attributes(ospf_list, match_ospf_list) if add_ospf_attr: add_ospf_attr['address'] = address - add_cfg.setdefault(attr, []) - add_cfg[attr].append(add_ospf_attr) + add_cfg.setdefault(attr, []).append(add_ospf_attr) if del_ospf_attr: del_ospf_attr['address'] = address - del_cfg.setdefault(attr, []) - del_cfg[attr].append(del_ospf_attr) + del_cfg.setdefault(attr, []).append(del_ospf_attr) for match_ospf_list in match_ospf_attr: address = match_ospf_list.get('address') ospf_list = next((o_list for o_list in ospf_attr if o_list.get('address') == address), None) if not ospf_list: - del_cfg.setdefault(attr, []) - del_cfg[attr].append({'address': address}) + del_cfg.setdefault(attr, []).append({'address': address}) elif attr in have_conf: del_cfg[attr] = have_conf[attr] if add_cfg: @@ -347,8 +346,7 @@ def _get_replaced_overridden_config(self, want, have): def _get_replaced_config_for_ospf_attributes(self, want, have): add_config, del_config = {}, {} - attr = 'ospf_attributes' - for ospf_attr in ospf_int_attributes[attr]: + for ospf_attr in OSPF_INT_ATTRIBUTES['ospf_attributes']: if ospf_attr == 'hello_multiplier': if ospf_attr in want: if ospf_attr not in have: @@ -397,7 +395,7 @@ def _get_replaced_config_for_ospf_attributes(self, want, have): add_config[ospf_attr] = add_mdkeys if del_mdkeys: del_config[ospf_attr] = del_mdkeys - elif attr in have: + elif ospf_attr in have: del_config[ospf_attr] = have[ospf_attr] return add_config, del_config @@ -430,7 +428,7 @@ def get_create_ospf_interfaces_requests(self, commands, have): match_address = match_attr.get('address') match_area_id = match_attr.get('area_id') if match_address and match_area_id and match_address == address and match_area_id != area_id: - path = ospf_path + ospf_int_attributes['ospf_attributes']['area_id'].format(address) + path = ospf_path + OSPF_INT_ATTRIBUTES['ospf_attributes']['area_id'].format(address) requests.append({'path': path, 'method': DELETE}) break @@ -468,10 +466,22 @@ def get_create_ospf_interfaces_requests(self, commands, have): if ospf_md_configs_list: ospf_attr_dict['md-authentications'] = {'md-authentication': ospf_md_configs_list} if ospf_attr_dict: - ospf_attr_dict.setdefault('config', {}) - self.update_dict(ospf_list, ospf_attr_dict['config'], 'address', 'address') - self.update_dict(ospf_list, ospf_attr_dict, 'address', 'address') - ospf_attr_configs.append(ospf_attr_dict) + ospf_default = False + if address == DEFAULT_ADDRESS: + for o_list in ospf_attr_configs: + if o_list['address'] == DEFAULT_ADDRESS: + if 'config' in ospf_attr_dict: + o_list['config'].update(ospf_attr_dict['config']) + if 'md-authentication' in ospf_attr_dict: + o_list['md-authentications'] = ospf_attr_dict['md-authentications'] + ospf_default = True + break + + if address != DEFAULT_ADDRESS or not ospf_default: + ospf_attr_dict.setdefault('config', {}) + self.update_dict(ospf_list, ospf_attr_dict['config'], 'address', 'address') + self.update_dict(ospf_list, ospf_attr_dict, 'address', 'address') + ospf_attr_configs.append(ospf_attr_dict) elif attr == 'bfd': self.update_dict(cmd[attr], bfd_dict, 'enable', 'enabled') self.update_dict(cmd[attr], bfd_dict, 'bfd_profile', 'bfd-profile') @@ -482,8 +492,7 @@ def get_create_ospf_interfaces_requests(self, commands, have): ospf_default = False for ospf_list in ospf_attr_configs: if ospf_list['address'] == DEFAULT_ADDRESS: - ospf_list.setdefault('config', {}) - ospf_list['config']['network-type'] = network_type + ospf_list.setdefault('config', {})['network-type'] = network_type ospf_default = True break if not ospf_default: @@ -533,25 +542,23 @@ def get_delete_ospf_interfaces_commands_requests(self, commands, have, is_delete continue if attr == 'bfd': if 'enable' in cmd.get(attr, {}) and 'enable' in match_have.get(attr, {}): - path = ospf_path + ospf_int_attributes['bfd']['enable'].format(DEFAULT_ADDRESS) + path = ospf_path + OSPF_INT_ATTRIBUTES['bfd']['enable'].format(DEFAULT_ADDRESS) requests.append({'path': path, 'method': DELETE}) - del_cmd.setdefault(attr, {}) - del_cmd[attr]['enable'] = match_have[attr]['enable'] + del_cmd.setdefault(attr, {})['enable'] = match_have[attr]['enable'] if 'bfd_profile' in match_have.get(attr, {}): del_cmd[attr]['bfd_profile'] = match_have[attr]['bfd_profile'] elif 'bfd_profile' in cmd.get(attr, {}) and 'bfd_profile' in match_have.get(attr, {}): - path = ospf_path + ospf_int_attributes['bfd']['bfd_profile'].format(DEFAULT_ADDRESS) + path = ospf_path + OSPF_INT_ATTRIBUTES['bfd']['bfd_profile'].format(DEFAULT_ADDRESS) requests.append({'path': path, 'method': DELETE}) - del_cmd.setdefault(attr, {}) - del_cmd[attr]['bfd_profile'] = match_have[attr]['bfd_profile'] - elif attr == 'network' and 'network' in cmd.get(attr, {}) and 'network' in match_have.get(attr, {}): - path = ospf_path + ospf_int_attributes['network'].format(DEFAULT_ADDRESS) + del_cmd.setdefault(attr, {})['bfd_profile'] = match_have[attr]['bfd_profile'] + elif attr == 'network' and match_have.get(attr, {}): + path = ospf_path + OSPF_INT_ATTRIBUTES['network'].format(DEFAULT_ADDRESS) requests.append({'path': path, 'method': DELETE}) del_cmd[attr] = match_have[attr] elif attr == 'ospf_attributes': match_ospf_attrs = match_have.get('ospf_attributes', []) if match_ospf_attrs: - ospf_attrs = cmd.get('ospf_attributes', []) + ospf_attrs = cmd.get('ospf_attributes') if ospf_attrs is not None: if not ospf_attrs: # Delete all attributes in have @@ -591,7 +598,7 @@ def get_delete_ospf_attributes_commands_requests(self, match_ospf_attrs, ospf_at if attr not in ('md_authentication', 'address'): if attr in m_attr and o_attr[attr] is not None and m_attr[attr] is not None: requests.append({ - 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(address), + 'path': ospf_path + OSPF_INT_ATTRIBUTES['ospf_attributes'][attr].format(address), 'method': DELETE }) del_ospf_attr[attr] = m_attr[attr] @@ -600,7 +607,7 @@ def get_delete_ospf_attributes_commands_requests(self, match_ospf_attrs, ospf_at del_mkeys = [] for key in m_attr.get(attr, []): requests.append({ - 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address'], key['key_id']), + 'path': ospf_path + OSPF_INT_ATTRIBUTES['ospf_attributes'][attr].format(m_attr['address'], key['key_id']), 'method': DELETE }) del_mkeys.append(key) @@ -613,7 +620,7 @@ def get_delete_ospf_attributes_commands_requests(self, match_ospf_attrs, ospf_at match_key = next((cfg for cfg in m_attr.get(attr, []) if cfg['key_id'] == key['key_id']), None) if match_key: requests.append({ - 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(address, key['key_id']), + 'path': ospf_path + OSPF_INT_ATTRIBUTES['ospf_attributes'][attr].format(address, key['key_id']), 'method': DELETE }) del_mkeys.append(match_key) @@ -637,7 +644,7 @@ def get_delete_all_ospf_attributes_per_address_commands_requests(self, m_attr, o for attr in m_attr: if attr not in ('md_authentication', 'address'): requests.append({ - 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address']), + 'path': ospf_path + OSPF_INT_ATTRIBUTES['ospf_attributes'][attr].format(m_attr['address']), 'method': DELETE }) commands[attr] = m_attr[attr] @@ -645,7 +652,7 @@ def get_delete_all_ospf_attributes_per_address_commands_requests(self, m_attr, o del_mkeys = [] for key in m_attr.get(attr, []): requests.append({ - 'path': ospf_path + ospf_int_attributes['ospf_attributes'][attr].format(m_attr['address'], key['key_id']), + 'path': ospf_path + OSPF_INT_ATTRIBUTES['ospf_attributes'][attr].format(m_attr['address'], key['key_id']), 'method': DELETE }) del_mkeys.append(key) @@ -678,6 +685,12 @@ def _add_default_address(self, conf): if not ospf_attr.get('address'): ospf_attr['address'] = DEFAULT_ADDRESS + def _getIpv4Address(self, ip): + if re.search(REGEX_IPV4_ADDRESS, ip): + return ip + else: + return ipaddress.IPv4Address(int(ip)) + def get_ospf_intf_uri(self, intf_name, sub_intf=0): intf_name = intf_name.replace('/', '%2f') ospf_intf_uri = '/data/openconfig-interfaces:interfaces/interface={}'.format(intf_name) @@ -702,6 +715,15 @@ def update_dict(self, src, dest, src_key, dest_key, value=False): elif src: dest.update(value) + def _normalize_interface_name(self, want): + normalize_interface_name(want, self._module) + for conf in want: + ospf_attr = conf.get('ospf_attributes', []) + for o_attr in ospf_attr: + if 'area_id' in o_attr: + o_attr['area_id'] = str(self._getIpv4Address(o_attr['area_id'])) + return want + def _get_generated_config(self, want, new_config, state): if state == 'merged': for cmd in want: diff --git a/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py index d447b7e5e..5996956ac 100644 --- a/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/facts/ospfv2_interfaces/ospfv2_interfaces.py @@ -189,7 +189,6 @@ def get_ospfv2_interfaces(self): def update_dict(self, dict, key, value, parent_key=None): if value not in [None, {}, []]: if parent_key: - dict.setdefault(parent_key, {}) - dict[parent_key][key] = value + dict.setdefault(parent_key, {})[key] = value else: dict[key] = value diff --git a/plugins/modules/sonic_ospfv2_interfaces.py b/plugins/modules/sonic_ospfv2_interfaces.py index 62b4cb4c3..6779f1c39 100644 --- a/plugins/modules/sonic_ospfv2_interfaces.py +++ b/plugins/modules/sonic_ospfv2_interfaces.py @@ -33,7 +33,7 @@ DOCUMENTATION = """ --- module: sonic_ospfv2_interfaces -version_added: '3.0.0' +version_added: '2.5.0' notes: - Supports C(check_mode). short_description: Configure OSPFv2 interface mode protocol settings on SONiC. diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml index 399b7ff0b..e9349db91 100644 --- a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml +++ b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml @@ -34,7 +34,7 @@ tests: input: - name: "{{ interface7 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 20 hello_interval: 10 @@ -68,7 +68,7 @@ tests: input: - name: "{{ po1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 15 retransmit_interval: 100 @@ -99,7 +99,7 @@ tests: input: - name: "{{ vlan1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 hello_multiplier: 2 - address: '10.10.120.1' @@ -121,7 +121,7 @@ tests: input: - name: "{{ po1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 15 - address: '10.10.120.1' @@ -159,7 +159,7 @@ tests: password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 2 - - area_id: '2.2.2.2' + - area_id: 33686018 address: '10.19.120.3' authentication_type: 'MD5HMAC' authentication: @@ -168,7 +168,7 @@ tests: hello_multiplier: 2 - name: "{{ lo1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 20 hello_interval: 10 @@ -190,7 +190,7 @@ tests: input: - name: "{{ lo1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 20 hello_interval: 10 @@ -228,12 +228,12 @@ tests: input: - name: "{{ po1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 15 - name: "{{ vlan1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 hello_multiplier: 2 - name: test_case_del_03 @@ -249,7 +249,7 @@ tests: input: - name: "{{ interface7 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 20 hello_interval: 10 @@ -277,7 +277,7 @@ tests: network: broadcast - name: "{{ vlan1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 hello_multiplier: 2 - address: '10.10.120.1' @@ -300,7 +300,7 @@ tests: - name: "{{ lo1 }}" network: point_to_point ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 20 hello_interval: 10 @@ -330,7 +330,7 @@ tests: network: point_to_point - name: "{{ po1 }}" ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 priority: 20 hello_interval: 10 diff --git a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml index a863e53fc..c020f2a80 100644 --- a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml +++ b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml @@ -576,7 +576,7 @@ deleted_01: enable-bfd: config: enabled: true - bfd-profile: 'profile2' + bfd-profile: 'profile2' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -627,7 +627,7 @@ deleted_01: enable-bfd: config: enabled: true - bfd-profile: 'profile1' + bfd-profile: 'profile1' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -661,6 +661,8 @@ deleted_01: method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=PortChannel100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.2/config/authentication-key' method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/config/network-type' + method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=0.0.0.0/enable-bfd' method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/md-authentications/md-authentication=10' @@ -785,7 +787,7 @@ deleted_02: enable-bfd: config: enabled: true - bfd-profile: 'profile2' + bfd-profile: 'profile2' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -836,7 +838,7 @@ deleted_02: enable-bfd: config: enabled: true - bfd-profile: 'profile1' + bfd-profile: 'profile1' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -865,7 +867,7 @@ replaced_01: bfd_profile: 'profile1' enable: True ospf_attributes: - - area_id: '2.2.2.2' + - area_id: '33686018' cost: 20 hello_interval: 10 dead_interval: 40 @@ -1010,7 +1012,7 @@ replaced_01: enable-bfd: config: enabled: true - bfd-profile: 'profile2' + bfd-profile: 'profile2' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -1061,7 +1063,7 @@ replaced_01: enable-bfd: config: enabled: true - bfd-profile: 'profile1' + bfd-profile: 'profile1' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -1163,7 +1165,7 @@ overridden_01: bfd_profile: 'profile1' enable: True ospf_attributes: - - area_id: '2.2.2.2' + - area_id: 33686018 cost: 20 hello_interval: 10 dead_interval: 40 @@ -1308,7 +1310,7 @@ overridden_01: enable-bfd: config: enabled: true - bfd-profile: 'profile2' + bfd-profile: 'profile2' - address: '10.10.120.1' config: address: '10.10.120.1' @@ -1359,7 +1361,7 @@ overridden_01: enable-bfd: config: enabled: true - bfd-profile: 'profile1' + bfd-profile: 'profile1' - address: '10.10.120.1' config: address: '10.10.120.1' From 7b5a2ee3a152d31dcc6aa797a0be8a385ab01c02 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Fri, 2 Aug 2024 19:17:15 +0530 Subject: [PATCH 08/13] Addressing internal review --- .../ospfv2_interfaces/ospfv2_interfaces.py | 57 ++++++++----------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index ec110b23c..b9028886a 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -14,7 +14,6 @@ __metaclass__ = type from copy import deepcopy -import re import ipaddress from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, @@ -43,7 +42,6 @@ PATCH = 'patch' DELETE = 'delete' DEFAULT_ADDRESS = '0.0.0.0' -REGEX_IPV4_ADDRESS = r'^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$' TEST_KEYS = [ {'config': {'name': ''}}, @@ -414,6 +412,8 @@ def get_create_ospf_interfaces_requests(self, commands, have): intf_name, sub_intf = self.get_ospf_if_and_subif(name) ospf_path = self.get_ospf_uri(intf_name, sub_intf) ospf_attr_configs = [] + default_address_attr_dict = {} + network_type = "" for attr in cmd: if attr == 'name': continue @@ -465,22 +465,13 @@ def get_create_ospf_interfaces_requests(self, commands, have): ospf_attr_dict = {'config': ospf_attr_dict} if ospf_md_configs_list: ospf_attr_dict['md-authentications'] = {'md-authentication': ospf_md_configs_list} + if ospf_attr_dict: - ospf_default = False if address == DEFAULT_ADDRESS: - for o_list in ospf_attr_configs: - if o_list['address'] == DEFAULT_ADDRESS: - if 'config' in ospf_attr_dict: - o_list['config'].update(ospf_attr_dict['config']) - if 'md-authentication' in ospf_attr_dict: - o_list['md-authentications'] = ospf_attr_dict['md-authentications'] - ospf_default = True - break - - if address != DEFAULT_ADDRESS or not ospf_default: - ospf_attr_dict.setdefault('config', {}) - self.update_dict(ospf_list, ospf_attr_dict['config'], 'address', 'address') - self.update_dict(ospf_list, ospf_attr_dict, 'address', 'address') + default_address_attr_dict = ospf_attr_dict + else: + ospf_attr_dict.setdefault('config', {})['address'] = address + ospf_attr_dict['address'] = address ospf_attr_configs.append(ospf_attr_dict) elif attr == 'bfd': self.update_dict(cmd[attr], bfd_dict, 'enable', 'enabled') @@ -489,18 +480,18 @@ def get_create_ospf_interfaces_requests(self, commands, have): network_type = cmd.get('network') if network_type: network_type = 'openconfig-ospf-types:' + network_type.upper() + '_NETWORK' - ospf_default = False - for ospf_list in ospf_attr_configs: - if ospf_list['address'] == DEFAULT_ADDRESS: - ospf_list.setdefault('config', {})['network-type'] = network_type - ospf_default = True - break - if not ospf_default: - ospf_attr_dict = { - 'address' : DEFAULT_ADDRESS, - 'config' : {'address' : DEFAULT_ADDRESS, 'network-type' : network_type} - } - ospf_attr_configs.append(ospf_attr_dict) + + if default_address_attr_dict: + default_address_attr_dict.setdefault('config', {})['address'] = DEFAULT_ADDRESS + if network_type: + default_address_attr_dict['config']['network-type'] = network_type + default_address_attr_dict['address'] = DEFAULT_ADDRESS + ospf_attr_configs.append(default_address_attr_dict) + elif network_type: + ospf_attr_configs.append({ + 'address': DEFAULT_ADDRESS, + 'config': {'network-type': network_type, 'address': DEFAULT_ADDRESS} + }) if ospf_attr_configs: payload = { @@ -686,10 +677,12 @@ def _add_default_address(self, conf): ospf_attr['address'] = DEFAULT_ADDRESS def _getIpv4Address(self, ip): - if re.search(REGEX_IPV4_ADDRESS, ip): - return ip - else: - return ipaddress.IPv4Address(int(ip)) + if ip.isdigit(): + ip = int(ip) + try: + return ipaddress.IPv4Address(ip) + except ipaddress.AddressValueError: + self._module.fail_json(msg="Invalid IPv4 address: {}".format(ip)) def get_ospf_intf_uri(self, intf_name, sub_intf=0): intf_name = intf_name.replace('/', '%2f') From 601d24fa9d6435314a5f52216853909e19fda72c Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T <53558409+santhosh-kt@users.noreply.github.com> Date: Fri, 2 Aug 2024 21:11:47 +0530 Subject: [PATCH 09/13] Minor changes Co-authored-by: Arun Saravanan Balachandran <52521751+ArunSaravananBalachandran@users.noreply.github.com> --- .../network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index b9028886a..1b9c04056 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -294,7 +294,7 @@ def _get_replaced_overridden_config(self, want, have): if attr == 'bfd': for bfd_attr in ['enable', 'bfd_profile']: if bfd_attr in conf[attr]: - if bfd_attr not in have_conf: + if bfd_attr not in have_conf[attr]: add_cfg.setdefault(attr, {})[bfd_attr] = conf[attr][bfd_attr] elif conf[attr][bfd_attr] != have_conf[attr][bfd_attr]: add_cfg.setdefault(attr, {})[bfd_attr] = conf[attr][bfd_attr] From 35d31256e84f535e19a66200873e24a5e179511a Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Fri, 2 Aug 2024 21:25:29 +0530 Subject: [PATCH 10/13] Addressing ut --- .../modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml index c020f2a80..f892ea601 100644 --- a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml +++ b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml @@ -1136,7 +1136,6 @@ replaced_01: - address: '0.0.0.0' enable-bfd: config: - enabled: true bfd-profile: 'profile3' - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'patch' @@ -1438,7 +1437,6 @@ overridden_01: - address: '0.0.0.0' enable-bfd: config: - enabled: true bfd-profile: 'profile3' - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'patch' From b2cd948fca49fe59f70ed314172506eaa3fc6815 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Mon, 5 Aug 2024 15:06:43 +0530 Subject: [PATCH 11/13] Addressed bfd alone cases --- .../ospfv2_interfaces/ospfv2_interfaces.py | 18 +++++++++--------- .../sonic_ospfv2_interfaces/defaults/main.yml | 5 +++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index 1b9c04056..4e592249d 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -500,16 +500,16 @@ def get_create_ospf_interfaces_requests(self, commands, have): } } requests.append({'path': ospf_path, 'method': PATCH, 'data': payload}) - if bfd_dict: - payload = { - 'openconfig-ospfv2-ext:ospfv2': { - 'if-addresses': [{ - 'address': DEFAULT_ADDRESS, - 'enable-bfd': {'config': bfd_dict} - }] - } + if bfd_dict: + payload = { + 'openconfig-ospfv2-ext:ospfv2': { + 'if-addresses': [{ + 'address': DEFAULT_ADDRESS, + 'enable-bfd': {'config': bfd_dict} + }] } - requests.append({'path': ospf_path, 'method': PATCH, 'data': payload}) + } + requests.append({'path': ospf_path, 'method': PATCH, 'data': payload}) return requests def get_delete_ospf_interfaces_commands_requests(self, commands, have, is_delete_all): diff --git a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml index e9349db91..ad379d752 100644 --- a/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml +++ b/tests/regression/roles/sonic_ospfv2_interfaces/defaults/main.yml @@ -22,6 +22,7 @@ preparations_tests: delete_port_configurations: - name: "{{ interface7 }}" - name: "{{ interface8 }}" + - name: "{{ interface9 }}" init_ospf: - router ospf delete_ospf: @@ -62,6 +63,10 @@ tests: bfd: enable: True network: point_to_point + - name: "{{ interface9 }}" + bfd: + enable: True + bfd_profile: 'profile1' - name: test_case_02 description: Add OSPFv2 interface configurations for Lag interfaces state: merged From 5d2a6a86bf6817ab69346f08e785331a4214964d Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Mon, 5 Aug 2024 16:10:58 +0530 Subject: [PATCH 12/13] Removing after in check_mode --- .../sonic/config/ospfv2_interfaces/ospfv2_interfaces.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py index 4e592249d..f53f4db46 100644 --- a/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py +++ b/plugins/module_utils/network/sonic/config/ospfv2_interfaces/ospfv2_interfaces.py @@ -128,9 +128,6 @@ def execute_module(self): except ConnectionError as exc: self._module.fail_json(msg=str(exc), code=exc.code) result['changed'] = True - - result['before'] = existing_ospfv2_interfaces_facts - old_config = existing_ospfv2_interfaces_facts result['commands'] = commands changed_ospfv2_interfaces_facts = self.get_ospfv2_interfaces_facts() @@ -142,6 +139,7 @@ def execute_module(self): new_config = changed_ospfv2_interfaces_facts old_config = existing_ospfv2_interfaces_facts if self._module.check_mode: + result.pop('after', None) new_commands = deepcopy(commands) self._add_default_address(new_commands) self._add_default_address(new_config) From 935accf9edcbe346bdb863b944222e60ddc23729 Mon Sep 17 00:00:00 2001 From: Santhosh Kumar T Date: Tue, 6 Aug 2024 22:46:45 +0530 Subject: [PATCH 13/13] Adding UT coverage --- .../fixtures/sonic_ospfv2_interfaces.yaml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml index f892ea601..2d62aa053 100644 --- a/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml +++ b/tests/unit/modules/network/sonic/fixtures/sonic_ospfv2_interfaces.yaml @@ -879,6 +879,10 @@ replaced_01: password: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' encrypted: True hello_multiplier: 5 + md_authentication: + - key_id: 10 + md5key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' + encrypted: True - name: 'Loopback100' network: broadcast bfd: @@ -933,6 +937,13 @@ replaced_01: authentication-key-encrypted: true hello-multiplier: 5 dead-interval-minimal: true + md-authentications: + md-authentication: + - authentication-key-id: 15 + config: + authentication-key-id: 15 + authentication-key-encrypted: true + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' - name: 'Eth1/6' subinterfaces: subinterface: @@ -1119,6 +1130,8 @@ replaced_01: method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Vlan100/openconfig-vlan:routed-vlan/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.19.120.3/config/dead-interval-minimal' method: 'delete' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2/if-addresses=10.10.120.1/md-authentications/md-authentication=15' + method: 'delete' - path: '/data/openconfig-interfaces:interfaces/interface=Loopback100/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' method: 'patch' data: @@ -1155,6 +1168,21 @@ replaced_01: config: address: '10.10.120.3' area-id: '2.2.2.2' + - path: '/data/openconfig-interfaces:interfaces/interface=Eth1%2f5/subinterfaces/subinterface=0/openconfig-if-ip:ipv4/openconfig-ospfv2-ext:ospfv2' + method: 'patch' + data: + openconfig-ospfv2-ext:ospfv2: + if-addresses: + - address: '10.10.120.1' + config: + address: '10.10.120.1' + md-authentications: + md-authentication: + - authentication-key-id: 10 + config: + authentication-key-encrypted: true + authentication-key-id: 10 + authentication-md5-key: 'U2FsdGVkX19eY7P3qRyyjaFsQgjoSQE71IX6IeBRios=' overridden_01: module_args: