diff options
| author | Rohit Thakur <rohitthakur2590@outlook.com> | 2020-04-02 00:37:06 +0530 | 
|---|---|---|
| committer | Rohit Thakur <rohitthakur2590@outlook.com> | 2020-05-11 19:27:16 +0530 | 
| commit | 37289b45840129f2296fbc9cff9a3eab97bdb2a5 (patch) | |
| tree | b3b80384e7e8795911562726c5d76b2789d1cda9 | |
| parent | 62ddab1affb33cb83b7a31ae6076e73c23dd1d0a (diff) | |
| download | vyos.vyos-37289b45840129f2296fbc9cff9a3eab97bdb2a5.tar.gz vyos.vyos-37289b45840129f2296fbc9cff9a3eab97bdb2a5.zip | |
vyos ospfv2 rm added
Signed-off-by: Rohit Thakur <rohitthakur2590@outlook.com>
| -rw-r--r-- | plugins/module_utils/network/vyos/argspec/ospfv2/__init__.py | 0 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py | 359 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/config/ospfv2/__init__.py | 0 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py | 570 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/facts/facts.py | 3 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/facts/ospfv2/__init__.py | 0 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py | 395 | ||||
| -rw-r--r-- | plugins/module_utils/network/vyos/utils/utils.py | 9 | ||||
| -rw-r--r-- | plugins/modules/vyos_facts.py | 2 | ||||
| -rw-r--r-- | plugins/modules/vyos_ospfv2.py | 1369 | 
10 files changed, 2699 insertions, 8 deletions
| diff --git a/plugins/module_utils/network/vyos/argspec/ospfv2/__init__.py b/plugins/module_utils/network/vyos/argspec/ospfv2/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/ospfv2/__init__.py diff --git a/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py new file mode 100644 index 00000000..1b11d3c9 --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py @@ -0,0 +1,359 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# 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 vyos_ospfv2 module +""" + + +class Ospfv2Args(object):  # pylint: disable=R0903 +    """The arg spec for the vyos_ospfv2 module +    """ +    def __init__(self, **kwargs): +        pass + +    argument_spec = { +        'config': { +            'elements': 'dict', +            'options': { +                'auto_cost': { +                    'options': { +                        'reference_bandwidth': { +                            'type': 'int' +                        } +                    }, +                    'type': 'dict' +                }, +                'default_information': { +                    'options': { +                        'originate': { +                            'options': { +                                'always': { +                                    'type': 'bool' +                                }, +                                'metric': { +                                    'type': 'int' +                                }, +                                'metric_type': { +                                    'type': 'int' +                                }, +                                'route_map': { +                                    'type': 'str' +                                } +                            }, +                            'type': 'dict' +                        } +                    }, +                    'type': 'dict' +                }, +                'default_metric': { +                    'type': 'int' +                }, +                'distance': { +                    'options': { +                        'global': { +                            'type': 'int' +                        }, +                        'ospf': { +                            'options': { +                                'external': { +                                    'type': 'int' +                                }, +                                'inter_area': { +                                    'type': 'int' +                                }, +                                'intra_area': { +                                    'type': 'int' +                                } +                            }, +                            'type': 'dict' +                        } +                    }, +                    'type': 'dict' +                }, +                'log_adjacency_changes': { +                    'choices': ['detail'], +                    'type': 'str' +                }, +                'max_metric': { +                    'options': { +                        'router_lsa': { +                            'options': { +                                'administrative': { +                                    'type': 'bool' +                                }, +                                'on_shutdown': { +                                    'type': 'int' +                                }, +                                'on_startup': { +                                    'type': 'int' +                                } +                            }, +                            'type': 'dict' +                        } +                    }, +                    'type': 'dict' +                }, +                'mpls_te': { +                    'options': { +                        'enabled': { +                            'type': 'bool' +                        }, +                        'router_address': { +                            'type': 'str' +                        } +                    }, +                    'type': 'dict' +                }, +                'neighbor': { +                    'elements': 'dict', +                    'options': { +                        'neighbor_id': { +                            'type': 'str' +                        }, +                        'poll_interval': { +                            'type': 'int' +                        }, +                        'priority': { +                            'type': 'int' +                        } +                    }, +                    'type': 'list' +                }, +                'ospf_area': { +                    'elements': 'dict', +                    'options': { +                        'area': { +                            'type': 'str' +                        }, +                        'area_type': { +                            'options': { +                                'normal': { +                                    'type': 'bool' +                                }, +                                'nssa': { +                                    'options': { +                                        'default_cost': { +                                            'type': 'int' +                                        }, +                                        'no_summary': { +                                            'type': 'bool' +                                        }, +                                        'translate': { +                                            'choices': +                                            ['always', 'candidate', 'never'], +                                            'type': +                                            'str' +                                        } +                                    }, +                                    'type': 'dict' +                                }, +                                'stub': { +                                    'options': { +                                        'default_cost': { +                                            'type': 'int' +                                        }, +                                        'no_summary': { +                                            'type': 'bool' +                                        } +                                    }, +                                    'type': 'dict' +                                } +                            }, +                            'type': 'dict' +                        }, +                        'authentication': { +                            'choices': ['plaintext-password', 'md5'], +                            'type': 'str' +                        }, +                        'network': { +                            'elements': 'dict', +                            'options': { +                                'address': { +                                    'required': True, +                                    'type': 'str' +                                } +                            }, +                            'type': 'list' +                        }, +                        'range': { +                            'elements': 'dict', +                            'options': { +                                'address': { +                                    'type': 'str' +                                }, +                                'cost': { +                                    'type': 'int' +                                }, +                                'not_advertise': { +                                    'type': 'bool' +                                }, +                                'substitute': { +                                    'type': 'str' +                                } +                            }, +                            'type': 'list' +                        }, +                        'shortcut': { +                            'choices': ['default', 'disable', 'enable'], +                            'type': 'str' +                        }, +                        'virtual_link': { +                            'elements': 'dict', +                            'options': { +                                'address': { +                                    'type': 'str' +                                }, +                                'authentication': { +                                    'options': { +                                        'md5': { +                                            'options': { +                                                'key_id': { +                                                    'type': 'int' +                                                }, +                                                'md5_key': { +                                                    'type': 'str' +                                                } +                                            }, +                                            'type': 'dict' +                                        }, +                                        'plaintext_password': { +                                            'type': 'str' +                                        } +                                    }, +                                    'type': 'dict' +                                }, +                                'dead_interval': { +                                    'type': 'int' +                                }, +                                'hello_interval': { +                                    'type': 'int' +                                }, +                                'retransmit_interval': { +                                    'type': 'int' +                                }, +                                'transmit_delay': { +                                    'type': 'int' +                                } +                            }, +                            'type': 'list' +                        } +                    }, +                    'type': 'list' +                }, +                'parameters': { +                    'options': { +                        'abr_type': { +                            'choices': +                            ['cisco', 'ibm', 'shortcut', 'standard'], +                            'type': 'str' +                        }, +                        'opaque_lsa': { +                            'type': 'bool' +                        }, +                        'rfc1583_compatibility': { +                            'type': 'bool' +                        }, +                        'router_id': { +                            'type': 'str' +                        } +                    }, +                    'type': 'dict' +                }, +                'passive_interface': { +                    'type': 'list' +                }, +                'passive_interface_exclude': { +                    'type': 'list' +                }, +                'redistribute': { +                    'elements': 'dict', +                    'options': { +                        'metric': { +                            'type': 'int' +                        }, +                        'metric_type': { +                            'type': 'int' +                        }, +                        'route_map': { +                            'type': 'str' +                        }, +                        'route_type': { +                            'choices': +                            ['bgp', 'connected', 'kernel', 'rip', 'static'], +                            'type': +                            'str' +                        } +                    }, +                    'type': 'list' +                }, +                'route_map': { +                    'type': 'list' +                }, +                'timers': { +                    'options': { +                        'refresh': { +                            'options': { +                                'timers': { +                                    'type': 'int' +                                } +                            }, +                            'type': 'dict' +                        }, +                        'throttle': { +                            'options': { +                                'spf': { +                                    'options': { +                                        'delay': { +                                            'type': 'int' +                                        }, +                                        'initial_holdtime': { +                                            'type': 'int' +                                        }, +                                        'max_holdtime': { +                                            'type': 'int' +                                        } +                                    }, +                                    'type': 'dict' +                                } +                            }, +                            'type': 'dict' +                        } +                    }, +                    'type': 'dict' +                } +            }, +            'type': 'list' +        }, +        "running_config": {"type": "str"}, +        'state': { +            'choices': [ +                'merged', 'replaced', 'deleted', 'parsed', 'gathered', +                'rendered' +            ], +            'default': +            'merged', +            'type': +            'str' +        } +    }  # pylint: disable=C0301 diff --git a/plugins/module_utils/network/vyos/config/ospfv2/__init__.py b/plugins/module_utils/network/vyos/config/ospfv2/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/plugins/module_utils/network/vyos/config/ospfv2/__init__.py diff --git a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py new file mode 100644 index 00000000..0109ca1a --- /dev/null +++ b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py @@ -0,0 +1,570 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The vyos_ospfv2 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, +    remove_empties, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts +from ansible.module_utils.six import iteritems + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( +    list_diff_want_only, _in_target, _is_w_same, _bool_to_str +) + +class Ospfv2(ConfigBase): +    """ +    The vyos_ospfv2 class +    """ + +    gather_subset = [ +        '!all', +        '!min', +    ] + +    gather_network_resources = [ +        'ospfv2', +    ] + +    def __init__(self, module): +        super(Ospfv2, self).__init__(module) + +    def get_ospfv2_facts(self, data=None): +        """ 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, data=data) +        ospfv2_facts = facts['ansible_network_resources'].get('ospfv2') +        if not ospfv2_facts: +            return [] +        return ospfv2_facts + +    def execute_module(self): +        """ Execute the module + +        :rtype: A dictionary +        :returns: The result from module execution +        """ +        result = {'changed': False} +        warnings = list() +        commands = list() + +        if self.state in self.ACTION_STATES: +            existing_ospfv2_facts = self.get_ospfv2_facts() +        else: +            existing_ospfv2_facts = [] + +        if self.state in self.ACTION_STATES or self.state == "rendered": +            commands.extend(self.set_config(existing_ospfv2_facts)) + +        if commands and self.state in self.ACTION_STATES: +            if not self._module.check_mode: +                self._connection.edit_config(commands) +            result["changed"] = True + +        if self.state in self.ACTION_STATES: +            result["commands"] = commands + +        if self.state in self.ACTION_STATES or self.state == "gathered": +            changed_ospfv2_facts = self.get_ospfv2_facts() +        elif self.state == "rendered": +            result["rendered"] = commands +        elif self.state == "parsed": +            running_config = self._module.params["running_config"] +            if not running_config: +                self._module.fail_json( +                    msg="value of running_config parameter must not be empty for state parsed" +                ) +            result["parsed"] = self.get_ospfv2_facts( +                data=running_config +            ) +        else: +            changed_ospfv2_facts = [] + +        if self.state in self.ACTION_STATES: +            result["before"] = existing_ospfv2_facts +            if result["changed"]: +                result["after"] = changed_ospfv2_facts +        elif self.state == "gathered": +            result["gathered"] = changed_ospfv2_facts + +        result["warnings"] = warnings +        return result + +    def set_config(self, existing_ospfv2_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_facts +        resp = self.set_state(want, have) +        return to_list(resp) + +    def set_state(self, w, h): +        """ 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 = [] +        if self.state in ("merged", "replaced", "overridden", "rendered") and not w: +            self._module.fail_json( +                msg="value of config parameter must not be empty for state {0}".format( +                    self.state +                ) +            ) +        if self.state == "overridden": +            commands.extend(self._state_overridden(w, h)) +        elif self.state == "deleted": +            commands.extend(self._state_deleted(w, h)) +        elif w: +            if self.state == "merged" or self.state == "rendered": +                for w_item in w: +                    commands.extend(self._state_merged(w_item, h)) +            elif self.state == "replaced": +                for w_item in w: +                    commands.extend(self._state_replaced(w_item, h)) +        return commands + +    def search_obj_in_have(self, have, w_name, key): +        """ +        This function  returns the rule-set/rule if it is present in target config. +        :param have: target config. +        :param w_name: rule-set name. +        :param type: rule_sets/rule/r_list. +        :return: rule-set/rule. +        """ +        if have: +            for item in have: +                if item[key] == w_name[key]: +                    return item +        return None + +    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 = [] +        h_item = {} +        if have: +            h_item = have[0] +            commands.extend(self._render_ospf_param(h_item, want, opr=False)) +        commands.extend(self._render_ospf_param(want, h_item)) +        return commands + +    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 = [] +        h_item = {} +        if have: +            h_item = have[0] +        commands.extend(self._render_ospf_param(want, h_item)) +        return commands + +    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 = [] +        if want: +            for w in want: +                if have: +                    h = have[0] +                    if h: +                        for key, val in iteritems(w): +                            if key in h: +                                if key == 'ospf_area': +                                    key = 'area' +                                commands.append(self._compute_command(attr=key, opr=False)) +        elif have and have[0]: +            commands.append('delete protocols ospf') +        return commands + +    def _render_ospf_param(self, want, have, opr=True): +        """ +        This function forms the set/delete commands for ospf leaf attributes +        and triggers the process for other child attributes. +        for firewall_global attributes. +        :param w: the desired config. +        :param h: the target config. +        :param opr: True/False. +        :return: generated commands list. +        """ +        commands = [] +        w = deepcopy(remove_empties(want)) +        leaf = ( +            "default_metric", +            "log_adjacency_changes" +        ) +        if w: +            for key, val in iteritems(w): +                if opr and key in leaf and not _is_w_same(w, have, key): +                    commands.append(self._form_attr_cmd(attr=key, val=_bool_to_str(val), opr=opr)) +                elif not opr and key in leaf and not _in_target(have, key): +                    commands.append(self._form_attr_cmd(attr=key, val=_bool_to_str(val), opr=opr)) +                else: +                    commands.extend(self._render_child_param(w, have, key, opr)) +        return commands + +    def _render_child_param(self, w, h, key, opr=True): +        """ +        This function invoke the function to extend commands +        based on the key. +        :param w: the desired configuration. +        :param h: the current configuration. +        :param key: attribute name. +        :param opr: operation. +        :return: list of commands. +        """ +        commands = [] +        if key in ("neighbor", "redistribute"): +            commands.extend(self._render_list_dict_param(key, w, h, opr=opr)) +        elif key in ("default_information", 'max_metric'): +            commands.extend(self._render_nested_dict_param(key, w, h, opr=opr)) +        elif key in ("mpls_te", "auto_cost", "parameters", "auto_cost"): +            commands.extend(self._render_dict_param(key, w, h, opr=opr)) +        elif key in ("route_map", "passive_interface", "passive_interface_exclude"): +            commands.extend(self._render_list_param(key, w, h, opr=opr)) +        elif key == "ospf_area": +            commands.extend(self._render_ospf_area(key, w, h, opr=opr)) +        elif key == "timers": +            commands.extend(self._render_timers(key, w, h, opr=opr, remove=remove)) +        elif key == "distance": +            commands.extend(self._render_distance(key, w, h, opr=opr, remove=remove)) +        return commands + +    def _render_dict_param(self, attr, want, have, opr=True): +        """ +        This function generate the commands for dictionary elements. +        :param attr: attribute name. +        :param w: the desired configuration. +        :param h: the target config. +        :param opr: True/False. +        :return: generated list of commands. +        """ +        commands = [] +        h = {} +        if have: +            h = have.get(attr) or {} +        if not opr and not h: +            commands.append(self._form_attr_cmd(attr=attr, opr=opr)) +        elif want[attr]: +            leaf_dict = {'auto_cost': 'reference_bandwidth', +                         'mpls_te': ('enabled', 'router_address'), +                         'parameters': ("router_id", "abr_type", "opaque_lsa", "rfc1583_compatibility")} +            leaf = leaf_dict[attr] +            for item, value in iteritems(want[attr]): +                if opr and item in leaf and not _is_w_same(want[attr], h, item): +                    if item == "enabled": +                        item = 'enable' +                    if item in ("opaque_lsa", "enable", "rfc1583_compatibility"): +                        commands.append(self._form_attr_cmd(key=attr, attr=item, opr=opr)) +                    else: +                        commands.append(self._form_attr_cmd(key=attr, attr=item, val=value, opr=opr)) +                elif not opr and item in leaf and not _in_target(h, item): +                    if item == "enabled": +                        commands.append(self._form_attr_cmd(key=attr, attr='enable', opr=opr)) +                    else: +                        commands.append(self._form_attr_cmd(key=attr, attr=item, opr=opr)) +        return commands + +    def _render_list_param(self, attr, want, have, cmd=None, opr=True): +        """ +        This function forms the commands for passed target list attributes'. +        :param attr: attribute name. +        :param w: the desired config. +        :param h: the target config. +        :param cmd: commands to be prepend. +        :param opr: True/False. +        :return: generated list of commands. +        """ +        commands = [] +        h = [] +        if want: +            w = want.get(attr) or [] +        if have: +            h = have.get(attr) or [] +        if not cmd: +            cmd = self._compute_command(opr=opr) +        if w: +            if opr: +                members = list_diff_want_only(w, h) +                for member in members: +                    command = cmd + attr.replace("_","-") + " " +                    if attr == 'network': +                        command += member['address'] +                    else: +                        command += member +                    commands.append(command) +            elif not opr: +                if h: +                    for member in w: +                        if attr == 'network': +                            if not self.search_obj_in_have(h, member, 'address'): +                                commands.append(cmd + attr.replace("_","-") + ' ' + member['address']) +                        elif member not in h: +                            commands.append(cmd + attr.replace("_","-") + ' ' + member) +                else: +                    commands.append(cmd + " " + attr.replace("_","-")) +        return commands + +    def _render_list_dict_param(self, attr, want, have, cmd=None, opr=True): +        """ +        This function forms the set/delete commands based on the 'opr' type +        for attributes with in desired list of dictionary. +        :param attr: attribute name. +        :param w: the desired config. +        :param h: the target config. +        :param cmd: commands to be prepend. +        :param opr: True/False. +        :return: generated commands list. +        """ +        commands = [] +        h = [] +        name = {'redistribute': 'route_type', +                'neighbor': 'neighbor_id', +                'range': 'address', +                'vlink': 'address'} +        leaf_dict = {'redistribute': ("metric", "route_map", "route_type", "metric_type"), +                     'neighbor': ("priority", "poll_interval", "neighbor_id"), +                     'range': ("cost", "address", "substitute", "not_advertise"), +                     'vlink': ("address", "dead_interval", "transmit_delay", "hello_interval", "retransmit_interval") +                     } +        leaf = leaf_dict[attr] +        w = want.get(attr) or [] +        if have: +            h = have.get(attr) or [] +        if not opr and not h: +            commands.append(self._compute_command(attr=attr, opr=opr)) +        elif w: +            for w_item in w: +                for key, val in iteritems(w_item): +                    if not cmd: +                        cmd = self._compute_command(opr=opr) +                    h_item = self.search_obj_in_have(h, w_item, name[attr]) +                    if opr and key in leaf and not _is_w_same(w_item, h_item, key): +                        if key == 'cost': +                            commands.append(cmd + attr + ' ' + w_item[name[attr]] + ' ' + key + ' ' + str(val)) +                        elif key == 'not_advertise': +                            commands.append(cmd + attr + ' ' + w_item[name[attr]] + ' ' + key.replace("_","-")) +                        elif key in ('route_type', 'neighbor_id', 'address'): +                            commands.append(cmd + attr + ' ' + str(val)) +                        elif key == 'authentication': +                            commands.append(self._render_vlink(key, w_item, h_item, cmd, opr)) +                        else: +                            commands.append(cmd + attr + ' ' + w_item[name[attr]] + ' ' + key.replace("_", "-") + ' ' + str(val)) +                    elif not opr and key in leaf and not _in_target(h_item, key): +                        if key in ('route_type', 'neighbor_id', 'address'): +                            commands.append(cmd + attr + ' ' + str(val)) +                        else: +                            commands.append(cmd + (attr + ' ' + w_item[name[attr]] + ' ' + key)) +        return commands + +    def _render_nested_dict_param(self, attr, want, have, opr=True): +        """ +        This function forms the set/delete commands based on the 'opr' type +        for attributes with in desired nested dicts. +        :param attr: attribute name. +        :param w: the desired config. +        :param h: the target config. +        :param cmd: commands to be prepend. +        :param opr: True/False. +        :return: generated commands list. +        """ +        commands = [] +        attr_dict = {'default_information': 'originate', +                     'max_metric': 'router_lsa', +                     } +        leaf_dict = {'default_information': ("always", "metric", "metric_type", "route_map"), +                    'max_metric': ("always", "metric", "metric_type", "route_map"), +                    } +        h = {} +        w = want.get(attr) or {} +        if have: +            h = have.get(attr) or {} +        if not opr and not h: +            commands.append(self._form_attr_cmd(attr=attr, opr=opr)) +        elif w: +            key = attr_dict[attr] +            w_attrib = want[attr].get(key) or {} +            cmd = self._compute_command(opr=opr) +            h_attrib = {} +            if w_attrib: +                leaf = leaf_dict[attr] +                if h and key in h.keys(): +                    h_attrib = h.get(key) or {} +                for item, val in iteritems(w[key]): +                    if opr and item in leaf and not _is_w_same(w[key], h_attrib, item): +                        if item in ('administrative', 'always'): +                            commands.append(cmd + (attr.replace("_","-") + " " + key.replace("_","-") + " " + item.replace("_","-"))) +                        else: +                            commands.append(cmd + (attr.replace("_","-") + " " + key.replace("_","-") + " " + item.replace("_","-") + " " + str(val))) + +                    elif not opr and item in leaf and not _in_target(h_attrib, item): +                        commands.append(cmd + (attr + " " + item)) +        return commands + +    def _render_ospf_area(self, attr, want, have, opr=True): +        """ +        This function forms the set/delete commands based on the 'opr' type +        for ospf area attributes. +        :param attr: attribute name. +        :param w: the desired config. +        :param h: the target config. +        :param opr: True/False. +        :return: generated commands list. +        """ +        commands = [] +        h_lst = {} +        w_lst = want.get(attr) or [] +        l_set = ("area", "shortcut", "authentication") +        if have: +            h_lst = have.get(attr) or [] +        if not opr and not h_lst: +            commands.append(self._form_attr_cmd(attr='area', opr=opr)) +        elif w_lst: +            for w_area in w_lst: +                cmd = self._compute_command(key='area', attr=_bool_to_str(w_area['area']), opr=opr) + ' ' +                h_area = self.search_obj_in_have(h_lst, w_area, 'area') +                if not opr and not h_area: +                    commands.append(self._form_attr_cmd(key='area', attr=w_area['area'], opr=opr)) +                else: +                    for key, val in iteritems(w_area): +                        if opr and key in l_set and not _is_w_same(w_area, h_area, key): +                            if key == 'area': +                                commands.append(self._form_attr_cmd(attr=key, val=_bool_to_str(val), opr=opr)) +                            else: +                                commands.append(cmd + key + ' ' + _bool_to_str(val).replace("_","-")) +                        elif not opr and key in l_set: +                            if key == 'area' and not _in_target(h_area, key): +                                commands.append(cmd) +                                continue +                            elif key != 'area' and not _in_target(h_area, key): +                                commands.append(cmd + val + ' ' + key) +                        elif key == 'area_type': +                            commands.extend(self._render_area_type(w_area, h_area, key, cmd, opr)) +                        elif key == 'network': +                            commands.extend(self._render_list_param(key, w_area, h_area, cmd, opr)) +                        elif key == 'range': +                            commands.extend(self._render_list_dict_param(key, w_area, h_area, cmd, opr)) +                        elif key == 'virtual_link': +                            commands.extend(self._render_vlink(key, w_area, h_area, cmd, opr)) +        return commands + +    def _render_area_type(self, want, have, attr, cmd, opr=True): +        """ +        This function forms the set/delete commands based on the 'opr' type +        for area_types attributes. +        :param attr: attribute name. +        :param w: the desired config. +        :param h: the target config. +        :param cmd: command to prepend. +        :param opr: True/False. +        :return: generated commands list. +        """ +        commands = [] +        h_type = {} +        w_type = want.get(attr) or [] +        if have: +            h_type = have.get(attr) or {} +        if not opr and not h_type: +            commands.append(cmd + attr.replace("_","-")) +        elif w_type: +            key = "normal" +            if opr and key in w_type.keys() and not _is_w_same(w_type, h_type, key): +                commands.append(cmd + attr.replace("_","-") + ' ' + key) +            elif not opr and key in w_type.keys() and not (h_type and key in h_type.keys()): +                commands.append(cmd + want['area'] + ' ' + attr.replace("_","-")) + +            a_type = {'nssa': ("default_cost", "no_summary", "translate"), +                      'stub': ("default_cost", "no_summary")} +            for key in a_type: +                w_area = want[attr].get(key) or {} +                h_area = {} +                if w_area: +                    if h_type and key in h_type.keys(): +                        h_area = h_type.get(key) or {} +                    for item, val in iteritems(w_type[key]): +                        if opr and item in a_type[key] and not _is_w_same(w_type[key], h_area, item): +                            commands.append(cmd + (attr.replace("_","-") + " " + key + " " + item.replace("_","-") + " " + str(val))) +                        elif not opr and item in a_type[key] and not (h_type and key in h_type): +                            commands.append(cmd + (want['area'] + ' ' + attr.replace("_","-") + " " + key + " " + item.replace("_","-"))) +        return commands + +    def _form_attr_cmd(self, key=None, attr=None, val=None, opr=True): +        """ +        This function forms the command for leaf attribute. +        :param key: parent key. +        :param attr: attribute name +        :param value: value +        :param opr: True/False. +        :return: generated command. +        """ +        return self._compute_command(key, attr=self._map_attrib(attr), val=val, opr=opr) + +    def _compute_command(self, key=None, attr=None, val=None, remove=False, opr=True): +        """ +        This function construct the add/delete command based on passed attributes. +        :param key: parent key. +        :param attr: attribute name +        :param value: value +        :param opr: True/False. +        :return: generated command. +        """ +        if remove or not opr: +            cmd = "delete protocols ospf " +        else: +            cmd = "set protocols ospf " +        if key: +            cmd += key.replace("_", "-") + " " +        if attr: +            cmd += attr.replace("_", "-") +        if val and opr: +            cmd += " '" + str(val) + "'" +        return cmd + +    def _map_attrib(self, attrib): +        """ +        - This function construct the regex string. +        - replace the underscore with hyphen. +        :param attrib: attribute +        :return: regex string +        """ +        return 'disable' if attrib =='disabled' else attrib.replace("_","-") diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py index 3c87be6b..17c7aa38 100644 --- a/plugins/module_utils/network/vyos/facts/facts.py +++ b/plugins/module_utils/network/vyos/facts/facts.py @@ -42,6 +42,8 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firew  )  from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospfv3.ospfv3 import (      Ospfv3Facts, +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospfv2.ospfv2 import ( +   Ospfv2Facts,  )  from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import (      Default, @@ -62,6 +64,7 @@ FACT_RESOURCE_SUBSETS = dict(      firewall_global=Firewall_globalFacts,      firewall_interfaces=Firewall_interfacesFacts,      ospfv3=Ospfv3Facts, +    ospfv2=Ospfv2Facts,  ) diff --git a/plugins/module_utils/network/vyos/facts/ospfv2/__init__.py b/plugins/module_utils/network/vyos/facts/ospfv2/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/ospfv2/__init__.py diff --git a/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py new file mode 100644 index 00000000..3457fac8 --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py @@ -0,0 +1,395 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The vyos ospfv2 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 re import findall, search, M +from copy import deepcopy +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( +    utils, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import Ospfv2Args + + +class Ospfv2Facts(object): +    """ The vyos ospfv2 fact class +    """ + +    def __init__(self, module, subspec='config', options='options'): +        self._module = module +        self.argument_spec = Ospfv2Args.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 get_device_data(self, connection): +        return connection.get_config() + +    def populate_facts(self, connection, ansible_facts, data=None): +        """ Populate the facts for ospfv2 +        :param connection: the device connection +        :param ansible_facts: Facts dictionary +        :param data: previously collected conf +        :rtype: dictionary +        :returns: facts +        """ +        if not data: +            data = self.get_device_data(connection) +            # typically data is populated from the current device configuration +            # data = connection.get('show running-config | section ^interface') +            # using mock data instead +        objs = [] +        ospfv2 = findall(r"^set protocols ospf (.+)", data, M) +        if ospfv2: +            config = self.render_config(ospfv2) +            if config: +                objs.append(config) +        ansible_facts["ansible_network_resources"].pop("ospfv2", None) +        facts = {} +        if objs: +            facts["ospfv2"] = [] +            params = utils.validate_config(self.argument_spec, {"config": objs}) +            for cfg in params["config"]: +                facts["ospfv2"].append(utils.remove_empties(cfg)) +        ansible_facts["ansible_network_resources"].update(facts) +        return ansible_facts + +    def render_config(self, conf): +        """ +        Render config as dictionary structure + +        :param conf: The configuration +        :returns: The generated config +        """ +        conf = "\n".join(filter(lambda x: x, conf)) +        a_lst = ["default_metric", "log_adjacency_changes"] +        config = self.parse_attr(conf, a_lst) + +        if not config: +            config = {} +        config["timers"] = self.parse_timers(conf) +        config["auto_cost"] = self.parse_auto_cost(conf) +        config["distance"] = self.parse_distance(conf) +        config["max_metric"] = self.parse_max_metric(conf) +        config["mpls_te"] = self.parse_attrib(conf, "mpls_te", "mpls-te") +        config["default_information"] = self.parse_def_info(conf) +        config["parameters"] = self.parse_attrib(conf, "parameters", "parameters") +        config["route_map"] = self.parse_leaf_list(conf, "route-map") +        config["ospf_area"] = self.parse_attrib_list(conf, "area", "area") +        config["neighbor"] = self.parse_attrib_list(conf, "neighbor", "neighbor_id") +        config["passive_interface"] = self.parse_leaf_list(conf, "passive-interface") +        config["redistribute"] = self.parse_attrib_list(conf, "redistribute", "route_type") +        config["passive_interface_exclude"] = self.parse_leaf_list(conf, "passive-interface-exclude") +        return config + +    def parse_timers(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'timers' attributes +        :param conf: configuration +        :param attrib: attribute name +        :return: generated config dictionary +        """ +        cfg_dict = {} +        cfg_dict["refresh"] = self.parse_refresh(conf, "refresh") +        cfg_dict["throttle"] = self.parse_throttle(conf, "spf") +        return cfg_dict + +    def parse_throttle(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'throttle' attributes +        :param conf: configuration +        :param attrib: 'spf' +        :return: generated config dictionary +        """ +        cfg_dict = {} +        cfg_dict[attrib] = self.parse_attrib(conf, attrib, match=attrib) +        return cfg_dict + +    def parse_refresh(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'refresh' attributes +        :param conf: configuration +        :param attrib: 'refresh' +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attr(conf, ["timers"], match=attrib) +        return cfg_dict + +    def parse_attrib_list(self, conf, attrib, param): +        """ +        This function forms the regex to fetch the listed attributes +        from config +        :param conf: configuration data +        :param attrib: attribute name +        :param param: parameter data +        :return: generated rule list configuration +        """ +        r_lst = [] +        if attrib == "area": +            items = findall(r"^" + attrib + " (?:\'*)(\S+)(?:\'*)", conf, M) +        else: +            items = findall(r"" + attrib + " (?:\'*)(\S+)(?:\'*)", conf, M) +        if items: +            a_lst = [] +            for item in set(items): +                i_regex = r" %s .+$" % item +                cfg = "\n".join(findall(i_regex, conf, M)) +                if attrib == 'area': +                    obj = self.parse_area(cfg, item) +                elif attrib == 'virtual-link': +                    obj = self.parse_vlink(cfg) +                else: +                    obj = self.parse_attrib(cfg, attrib) +                obj[param] = item.strip("'") +                if obj: +                    a_lst.append(obj) +            r_lst = sorted(a_lst, key=lambda i: i[param]) +        return r_lst + +    def parse_leaf_list(self, conf, attrib): +        """ +        This function forms the regex to fetch the listed attributes +        from the configuration data +        :param conf: configuration data +        :param attrib: attribute name +        :return: generated rule list configuration +        """ +        lst = [] +        items = findall(r"^" + attrib + " (?:\'*)(\S+)(?:\'*)", conf, M) +        if items: +            for i in set(items): +                lst.append(i.strip("'")) +        return lst + +    def parse_distance(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'distance' attributes +        :param conf: configuration +        :param attrib: attribute name +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attr(conf, ["global"], match=attrib) +        cfg_dict["ospf"] = self.parse_ospf(conf, "ospf") +        return cfg_dict + +    def parse_ospf(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'distance ospf' attributes +        :param conf: configuration +        :param attrib: 'ospf' +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attrib(conf, 'ospf', match=attrib) +        return cfg_dict + +    def parse_max_metric(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'max_metric' attributes +        :param conf: configuration +        :param attrib: attribute name +        :return: generated config dictionary +        """ +        cfg_dict = {} +        cfg_dict["router_lsa"] = self.parse_attrib(conf, "router_lsa", match="router-lsa") +        return cfg_dict + +    def parse_auto_cost(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'auto_cost' attributes +        :param conf: configuration +        :param attrib: attribute name +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attr(conf, ["reference_bandwidth"], match=attrib) +        return cfg_dict + +    def parse_def_info(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'default_information' attributes +        :param conf: configuration +        :param attrib: attribute name +        :return: generated config dictionary +        """ +        cfg_dict = {} +        cfg_dict["originate"] = self.parse_attrib(conf, "originate", "originate") +        return cfg_dict + +    def parse_area(self, conf, area_id): +        """ +        This function triggers the parsing of 'area' attributes. +        :param conf: configuration data +        :param area_id: area identity +        :return: generated rule configuration dictionary. +        """ +        rule = self.parse_attrib(conf, "area", match=area_id) +        r_sub = { +            "area_type": self.parse_area_type(conf, "area-type"), +            "network": self.parse_network(conf), +            "range": self.parse_attrib_list(conf, "range", "address"), +            "virtual_link": self.parse_attrib_list(conf, "virtual-link", "address") +        } +        rule.update(r_sub) +        return rule + +    def parse_area_type(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'area_type' attributes +        :param conf: configuration +        :param attrib: 'area-type' +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attr(conf, ["normal"], match=attrib) +        cfg_dict["nssa"] = self.parse_attrib(conf, "nssa") +        cfg_dict["stub"] = self.parse_attrib(conf, "stub") +        return cfg_dict + +    def parse_network(self, conf): +        """ +        This function forms the regex to fetch the 'network' +        :param conf: configuration data +        :return: generated rule list configuration +        """ +        a_lst = [] +        applications = findall(r"network (.+)", conf, M) +        if applications: +            app_lst = [] +            for r in set(applications): +                obj = {"address": r.strip("'")} +                app_lst.append(obj) +            a_lst = sorted(app_lst, key=lambda i: i["address"]) +        return a_lst + +    def parse_vlink(self, conf): +        """ +        This function triggers the parsing of 'vitual_link' attributes +        :param conf: configuration data +        :return: generated rule configuration dictionary +        """ +        rule = self.parse_attrib(conf, 'vlink') +        r_sub = {"authentication": self.parse_authentication(conf, "authentication")} +        rule.update(r_sub) +        return rule + +    def parse_authentication(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'authentication' attributes. +        :param conf: configuration +        :param attrib: 'authentication' +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attr(conf, ["plaintext_password"], match=attrib) +        cfg_dict["md5"] = self.parse_md5(conf, "md5") +        return cfg_dict + +    def parse_md5(self, conf, attrib=None): +        """ +        This function triggers the parsing of 'md5' attributes +        :param conf: configuration +        :param attrib: 'md5' +        :return: generated config dictionary +        """ +        cfg_dict = self.parse_attr(conf, ["key_id"], match=attrib) +        return cfg_dict + +    def parse_attrib(self, conf, param, match=None): +        """ +        This function triggers the parsing of 'ospf' attributes +        :param conf: configuration data +        :return: generated configuration dictionary +        """ +        param_lst = { +            'stub': ["default_cost", "no_summary"], +            'area':  ["shortcut", "authentication"], +            'mpls_te': ["enabled", "router_address"], +            'neighbor': ["priority", "poll_interval"], +            'ospf': ["external", "inter_area", "intra_area"], +            'nssa': ["translate", "default_cost", "no_summary"], +            'redistribute': ["metric", "metric_type", "route_map"], +            'spf': ["delay", "max_holdtime", "initial_holdtime"], +            'range': ["cost", "substitute", "not_advertise"], +            'originate': ["always", "metric", "metric_type", "route_map"], +            'router_lsa': ["administrative", "on_shutdown", "on_startup"], +            'config_routes': ["default_metric", "log_adjacency_changes"], +            'parameters': ["abr_type", "opaque_lsa", "router_id", "rfc1583_compatibility"], +            'vlink': ["dead_interval", "hello_interval", "transmit_delay", "retransmit_interval"] +            } +        cfg_dict = self.parse_attr(conf, param_lst[param], match) +        return cfg_dict + +    def parse_attr(self, conf, attr_list, match=None): +        """ +        This function peforms the following: +        - Form the regex to fetch the required attribute config. +        - Type cast the output in desired format. +        :param conf: configuration. +        :param attr_list: list of attributes. +        :param match: parent node/attribute name. +        :return: generated config dictionary. +        """ +        config = {} +        for attrib in attr_list: +            regex = self.map_regex(attrib) +            if match: +                regex = match.replace("_", "-") + " " + regex +            if conf: +                if self.is_bool(attrib): +                    out = conf.find(attrib.replace("_", "-")) +                    dis = conf.find(attrib.replace("_", "-") + " 'disable'") +                    if match: +                        en = conf.find(match + " 'enable'") +                    if out >= 1: +                        if dis >= 1: +                            config[attrib] = False +                        else: +                            config[attrib] = True +                    elif match and en >= 1: +                        config[attrib] = True +                else: +                    out = search(r"^.*" + regex + " (.+)", conf, M) +                    if out: +                        val = out.group(1).strip("'") +                        if self.is_num(attrib): +                            val = int(val) +                        config[attrib] = val +        return config + +    def map_regex(self, attrib): +        """ +        - This function construct the regex string. +        - replace the underscore with hyphen. +        :param attrib: attribute +        :return: regex string +        """ +        return 'disable' if attrib == "disabled" else 'enable' if attrib == "enabled" else attrib.replace("_","-") + +    def is_bool(self, attrib): +        """ +        This function looks for the attribute in predefined bool type set. +        :param attrib: attribute. +        :return: True/False +        """ +        bool_set = ("always", "normal", "enabled", "opaque_lsa", "not_advertise", "administrative", "rfc1583_compatibility") +        return True if attrib in bool_set else False + +    def is_num(self, attrib): +        """ +        This function looks for the attribute in predefined integer type set. +        :param attrib: attribute. +        :return: True/false. +        """ +        num_set = ("ospf", "delay", "metric", "inter_area", "intra_area", "on_startup", "metric_type", "on_shutdown", +                   "max_holdtime", "default_metric", "initial_holdtime") +        return True if attrib in num_set else False diff --git a/plugins/module_utils/network/vyos/utils/utils.py b/plugins/module_utils/network/vyos/utils/utils.py index 96feddd9..c7dc575a 100644 --- a/plugins/module_utils/network/vyos/utils/utils.py +++ b/plugins/module_utils/network/vyos/utils/utils.py @@ -7,6 +7,7 @@  from __future__ import absolute_import, division, print_function  __metaclass__ = type +import q  from ansible.module_utils.six import iteritems  from ansible_collections.ansible.netcommon.plugins.module_utils.compat import (      ipaddress, @@ -238,13 +239,7 @@ def _bool_to_str(val):      :param val: bool value.      :return: enable/disable.      """ -    return ( -        "enable" -        if str(val) == "True" -        else "disable" -        if str(val) == "False" -        else val -    ) +    return "enable" if str(val) == "True" else "disable" if str(val) == "False" else val  def _is_w_same(w, h, key): diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index 5849519c..72b191c4 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -48,7 +48,7 @@ options:        used with an initial C(M(!)) to specify that a specific subset should not be        collected. Valid subsets are 'all', 'interfaces', 'l3_interfaces', 'lag_interfaces',        'lldp_global', 'lldp_interfaces', 'static_routes', 'firewall_rules', 'firewall_global', -      'firewall_interfaces', 'ospfv3'. +      'firewall_interfaces', 'ospfv3', 'ospfv2'.      required: false  """ diff --git a/plugins/modules/vyos_ospfv2.py b/plugins/modules/vyos_ospfv2.py new file mode 100644 index 00000000..73528eb5 --- /dev/null +++ b/plugins/modules/vyos_ospfv2.py @@ -0,0 +1,1369 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat +# 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 vyos_ospfv2 +""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +ANSIBLE_METADATA = { +    'metadata_version': '1.1', +    'status': ['preview'], +    'supported_by': 'network' +} + +DOCUMENTATION = """ +--- +module: vyos_ospfv2 +version_added: 2.10 +short_description: Manages attributes of OSPF IPv4 routes on VyOS network devices. +description: This module manages attributes of OSPF IPv4 routes on VyOS network devices. +author: Rohit Thakur (@rohitthakur2590) +options: +  config: +    description: A provided OSPF route configuration. +    type: list +    elements: dict +    suboptions: +      ospf_area: +        description: OSPF area. +        type: list +        elements: dict +        suboptions: +          area: +            description: Configured to discard packets. +            type: str +          area_type: +            description: Area type. +            type: dict +            suboptions: +              normal: +                description: Normal OSPF area. +                type: bool +              nssa: +                description: Nssa OSPF area. +                type: dict +                suboptions: +                  default_cost: +                    description: Summary-default cost of nssa area. +                    type: int +                  no_summary: +                    description: Do not inject inter-area routes into stub. +                    type: bool +                  translate:  +                    description: Nssa-abr. +                    type: str +                    choices: ['always', 'candidate', 'never'] +              stub:  +                description: Stub OSPF area. +                type: dict +                suboptions: +                  default_cost: +                    description: Summary-default cost of stub area. +                    type: int +                  no_summary: +                    description: Do not inject inter-area routes into stub. +                    type: bool +          authentication: +            description: OSPF area authentication type. +            type: str +            choices: ['plaintext-password', 'md5'] +          network: +            description: OSPF network. +            type: list +            elements: dict +            suboptions: +              address: +                required: True +                description: OSPF IPv4 network address. +                type: str  +          range: +            description: Summarize routes matching prefix (border routers only). +            type: list +            elements: dict +            suboptions: +              address: +                description: border router IPv4 address. +                type: str +              cost: +                description: Metric for this range. +                type: int +              not_advertise: +                description: Don't advertise this range. +                type: bool +              substitute: +                description: Announce area range (IPv4 address) as another prefix. +                type: str +          shortcut: +            description: Area's shortcut mode. +            type: str +            choices: ['default', 'disable', 'enable'] +          virtual_link: +            description: Virtual link address. +            type: list +            elements: dict +            suboptions: +              address: +                description: virtual link address. +                type: str +              authentication: +                description: OSPF area authentication type. +                type: dict +                suboptions: +                  md5: +                    description: MD5 key id based authentication. +                    type: dict +                    suboptions: +                      key_id: +                        description: MD5 key id. +                        type: int +                      md5_key: +                        description: MD5 key. +                        type: str +                  plaintext_password: +                    description: Plain text password. +                    type: str +              dead_interval: +                description: Interval after which a neighbor is declared dead. +                type: int +              hello_interval: +                description: Interval between hello packets. +                type: int +              retransmit_interval:  +                description: Interval between retransmitting lost link state advertisements. +                type: int +              transmit_delay: +                description: Link state transmit delay. +                type: int +      log_adjacency_changes: +         description: Log changes in adjacency state. +         type: str +         choices: ['detail'] +      max_metric:  +        description: OSPF maximum/infinite-distance metric. +        type: dict +        suboptions: +          router_lsa: +            description: Advertise own Router-LSA with infinite distance (stub router). +            type: dict +            suboptions: +              administrative: +                description: Administratively apply, for an indefinite period. +                type: bool +              on_shutdown: +                description: Time to advertise self as stub-router. +                type: int    +              on_startup: +                description: Time to advertise self as stub-router +                type: int    +      auto_cost: +        description: Calculate OSPF interface cost according to bandwidth. +        type: dict +        suboptions: +          reference_bandwidth: +            description: Reference bandwidth cost in Mbits/sec. +            type: int +      default_information: +        description: Control distribution of default information. +        type: dict +        suboptions: +          originate: +            description: Distribute a default route. +            type: dict +            suboptions: +              always: +                description: Always advertise default route. +                type: bool +              metric: +                description: OSPF default metric. +                type: int +              metric_type: +                description: OSPF Metric types for default routes. +                type: int +              route_map: +                description: Route map references. +                type: str            +      default_metric: +        description: Metric of redistributed routes +        type: int +      distance: +        description: Administrative distance. +        type: dict +        suboptions: +          global: +            description: Global OSPF administrative distance. +            type: int +          ospf:  +            description: OSPF administrative distance. +            type: dict +            suboptions: +              external:  +                description: Distance for external routes. +                type: int +              inter_area: +                description: Distance for inter-area routes. +                type: int +              intra_area: +                description: Distance for intra-area routes. +                type: int +      mpls_te: +        description: MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters. +        type: dict +        suboptions: +          enabled: +            description: Enable MPLS-TE functionality. +            type: bool +          router_address: +            description: Stable IP address of the advertising router. +            type: str + +      neighbor: +        description: Neighbor IP address. +        type: list +        elements: dict +        suboptions: +          neighbor_id: +            description: Identity (number/IP address) of neighbor. +            type: str  +          poll_interval: +            description: Seconds between dead neighbor polling interval. +            type: int +          priority: +            description: Neighbor priority. +            type: int        +      parameters: +        descriptions: OSPF specific parameters. +        type: dict +        suboptions:  +         abr_type:  +           description: OSPF ABR Type. +           type: str +           choices: ['cisco', 'ibm', 'shortcut', 'standard'] +         opaque_lsa: +           description: Enable the Opaque-LSA capability (rfc2370). +           type: bool +         rfc1583_compatibility: +           description: Enable rfc1583 criteria for handling AS external routes. +           type: bool +         router_id:  +           description: Override the default router identifier. +           type: str +      passive_interface: +        description: Suppress routing updates on an interface. +        type: list +      passive_interface_exclude: +        description: Interface to exclude when using passive-interface default. +        type: list +      redistribute:   +        description: Redistribute information from another routing protocol. +        type: list +        elements: dict +        suboptions:  +          route_type: +            description: Route type to redistribute. +            type: str +            choices: ['bgp', 'connected', 'kernel', 'rip', 'static'] +          metric: +            description: Metric for redistribution routes. +            type: int +          metric_type: +            description: OSPF Metric types. +            type: int +          route_map: +            description: Route map references. +            type: str  +       +      route_map: +        description: Filter routes installed in local route map.        +        type: list +      timers: +        description: Adjust routing timers. +        type: dict +        suboptions: +          refresh: +            description: Adjust refresh parameters. +            type: dict +            suboptions: +              timers: +                description: refresh timer. +                type: int +          throttle: +            description: Throttling adaptive timers. +            type: dict +            suboptions: +              spf: +                description: OSPF SPF timers. +                type: dict +                suboptions: +                  delay: +                    description: Delay (msec) from first change received till SPF calculation. +                    type: int +                  initial_holdtime: +                    description: Initial hold time(msec) between consecutive SPF calculations. +                    type: int +                  max_holdtime: +                    description: maximum hold time (sec). +                    type: int +  state: +    description: +      - The state the configuration should be left in. +    type: str +    choices: +    - merged +    - replaced +    - deleted +    - parsed +    - gathered +    - rendered +    default: merged +""" +EXAMPLES = """ +# Using merged +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep ospf +# +- name: Merge the provided configuration with the existing running configuration +      vyos_ospf_routes: +        config: +          - afi: 'ipv4' +            ospf_area: +              - area: 0 +                network: 192.168.0.0/24 +            default_information: +              originate: +                always: true +                metric: 2 +                metric_type: 10 +            log_adjacency_changes: "details" +            parameters: +              router_id: 10.1.1.1 +            redistribute: +              - route_type: 'connected' +                metric_type: 2 +                route_map: 'CONNECT' +          - afi: 'ipv6' +            ospf_area: +              - area: 0.0.0.0 +                range: 2001:db8:1::/64 +            parameters: +              router-id 192.168.1.1 +            redistribute: +              - route_type: 'connected' +        state: merged +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [] +# +#    "commands": [ +#       "set interfaces ethernet eth1 firewall in name 'INBOUND'",  +#       "set protocols ospf area 0 network 192.168.0.0/24", +#       "set protocols ospf default-information originate always", +#       "set protocols ospf default-information originate metric 10", +#       "set protocols ospf default-information originate metric-type 2", +#       "set protocols ospf log-adjacency-changes", +#       "set protocols ospf parameters router-id 10.1.1.1", +#       "set protocols ospf redistribute connected metric-type 2", +#       "set protocols ospf redistribute connected route-map CONNECT", +#       "set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64, +#       "set protocols ospfv3 parameters router-id 192.168.1.1, +#       "set protocols ospfv3 redistribute connected +#    ] +# +# "after": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "connetced",  +#                            "metric_type": 2 +#                            "route_map": "CONNECT" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connetced", +#                            }  +#                        ] +#                } +#    ] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute connected metric-type 2 +# set protocols ospf redistribute connected route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64 +# set protocols ospfv3 parameters router-id 192.168.1.1 +# set protocols ospfv3 redistribute connected + + +# Using replaced +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep ospf +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute connected metric-type 2 +# set protocols ospf redistribute connected route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64 +# set protocols ospfv3 parameters router-id 192.168.1.1 +# set protocols ospfv3 redistribute connected +# +- name: Replace the provided configuration with the existing running configuration +      vyos_ospf_routes: +        config: +          - afi: 'ipv4' +            ospf_area: +              - area: 0 +                network: 192.168.0.0/24 +                area_type: +                  normal: True +            default_information: +              originate: +                always: true +                metric: 2 +                metric_type: 10 +            log_adjacency_changes: "details" +            parameters: +              router_id: 10.1.1.1 +            redistribute: +              - route_type: 'static' +                metric_type: 2 +                route_map: 'STATIC' +          - afi: 'ipv6' +            ospf_area: +              - area: 0.0.0.0 +                range: 2001:db8:1::/64 +            parameters: +              router-id 192.168.1.1 +            redistribute: +              - route_type: 'connected' +        state: replaced +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "connetced",  +#                            "metric_type": 2 +#                            "route_map": "CONNECT" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connetced", +#                            }  +#                        ] +#                } +#    ] +# +#    "commands": [ +#       "delete protocols ospf redistribute connected", +#       "set protocols ospf area 0 area_type normal", +#       "set protocols ospf redistribute static metric-type 2", +#       "set protocols ospf redistribute static route-map CONNECT" +#    ] +# +# "after": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "area_type":  +#                               { +#                                 normal: true +#                               } +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "static",  +#                            "metric_type": 2 +#                            "route_map": "STATIC" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connected", +#                            }  +#                        ] +#                } +#    ] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute static metric-type 2 +# set protocols ospf redistribute static route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64 +# set protocols ospfv3 parameters router-id 192.168.2.1 +# set protocols ospfv3 redistribute connected + + +# Using replaced +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep ospf +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute connected metric-type 2 +# set protocols ospf redistribute connected route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64 +# set protocols ospfv3 parameters router-id 192.168.1.1 +# set protocols ospfv3 redistribute connected +# +- name: Replace the provided configuration with the existing running configuration +      vyos_ospf_routes: +        config: +          - afi: 'ipv4' +            ospf_area: +              - area: 0 +                network: 192.168.0.0/24 +                area_type: +                  normal: True +            default_information: +              originate: +                always: true +                metric: 2 +                metric_type: 10 +            log_adjacency_changes: "details" +            parameters: +              router_id: 10.1.1.1 +            redistribute: +              - route_type: 'static' +                metric_type: 2 +                route_map: 'STATIC' +          - afi: 'ipv6' +            ospf_area: +              - area: 0.0.0.0 +                range: 2001:db8:1::/64 +            parameters: +              router-id 192.168.1.1 +            redistribute: +              - route_type: 'connected' +        state: replaced +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "connetced",  +#                            "metric_type": 2 +#                            "route_map": "CONNECT" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connetced", +#                            }  +#                        ] +#                } +#    ] +# +#    "commands": [ +#       "delete protocols ospf redistribute connected", +#       "set protocols ospf area 0 area_type normal", +#       "set protocols ospf redistribute static metric-type 2", +#       "set protocols ospf redistribute static route-map CONNECT" +#    ] +# +# "after": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "area_type":  +#                               { +#                                 normal: true +#                               } +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "static",  +#                            "metric_type": 2 +#                            "route_map": "STATIC" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connected", +#                            }  +#                        ] +#                } +#    ] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute static metric-type 2 +# set protocols ospf redistribute static route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64 +# set protocols ospfv3 parameters router-id 192.168.2.1 +# set protocols ospfv3 redistribute connected + + +# Using replaced +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep ospf +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute connected metric-type 2 +# set protocols ospf redistribute connected route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64 +# set protocols ospfv3 parameters router-id 192.168.1.1 +# set protocols ospfv3 redistribute connected +# +- name: Replace the provided configuration with the existing running configuration +      vyos_ospf_routes: +        config: +          - afi: 'ipv4' +            ospf_area: +              - area: 0 +                network: 192.168.0.0/24 +                area_type: +                  normal: True +            default_information: +              originate: +                always: true +                metric: 2 +                metric_type: 10 +            log_adjacency_changes: "details" +            parameters: +              router_id: 10.1.1.1 +            redistribute: +              - route_type: 'static' +                metric_type: 2 +                route_map: 'STATIC' +          - afi: 'ipv6' +            ospf_area: +              - area: 0.0.0.0 +                range: 2001:db8:1::/64 +            parameters: +              router-id 192.168.1.1 +            redistribute: +              - route_type: 'connected' +        state: replaced +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "connetced",  +#                            "metric_type": 2 +#                            "route_map": "CONNECT" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connetced", +#                            }  +#                        ] +#                } +#    ] +# +#    "commands": [ +#       "delete protocols ospf redistribute connected", +#       "set protocols ospf area 0 area_type normal", +#       "set protocols ospf redistribute static metric-type 2", +#       "set protocols ospf redistribute static route-map CONNECT" +#    ] +# +# "after": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "area_type":  +#                               { +#                                 normal: true +#                               } +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "static",  +#                            "metric_type": 2 +#                            "route_map": "STATIC" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connected", +#                            }  +#                        ] +#                } +#    ] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute static metric-type 2 +# set protocols ospf redistribute static route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64 +# set protocols ospfv3 parameters router-id 192.168.2.1 +# set protocols ospfv3 redistribute connected + + +# Using replaced +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep ospf +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute connected metric-type 2 +# set protocols ospf redistribute connected route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64 +# set protocols ospfv3 parameters router-id 192.168.1.1 +# set protocols ospfv3 redistribute connected +# +- name: Replace the provided configuration with the existing running configuration +      vyos_ospf_routes: +        config: +          - afi: 'ipv4' +            ospf_area: +              - area: 0 +                network: 192.168.0.0/24 +                area_type: +                  normal: True +            default_information: +              originate: +                always: true +                metric: 2 +                metric_type: 10 +            log_adjacency_changes: "details" +            parameters: +              router_id: 10.1.1.1 +            redistribute: +              - route_type: 'static' +                metric_type: 2 +                route_map: 'STATIC' +          - afi: 'ipv6' +            ospf_area: +              - area: 0.0.0.0 +                range: 2001:db8:1::/64 +            parameters: +              router-id 192.168.1.1 +            redistribute: +              - route_type: 'connected' +        state: replaced +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "connetced",  +#                            "metric_type": 2 +#                            "route_map": "CONNECT" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connetced", +#                            }  +#                        ] +#                } +#    ] +# +#    "commands": [ +#       "delete protocols ospf redistribute connected", +#       "set protocols ospf area 0 area_type normal", +#       "set protocols ospf redistribute static metric-type 2", +#       "set protocols ospf redistribute static route-map CONNECT" +#    ] +# +# "after": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "area_type":  +#                               { +#                                 normal: true +#                               } +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "static",  +#                            "metric_type": 2 +#                            "route_map": "STATIC" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connected", +#                            }  +#                        ] +#                } +#    ] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute static metric-type 2 +# set protocols ospf redistribute static route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64 +# set protocols ospfv3 parameters router-id 192.168.2.1 +# set protocols ospfv3 redistribute connected + + +# Using deleted +# +# Before state: +# ------------- +# +# vyos@192# run show configuration commands | grep ospf +# set protocols ospf area 0 network 192.168.0.0/24 +# set protocols ospf default-information originate always +# set protocols ospf default-information originate metric 10 +# set protocols ospf default-information originate metric-type 2 +# set protocols ospf log-adjacency-changes details +# set protocols ospf parameters router-id 10.1.1.1 +# set protocols ospf redistribute connected metric-type 2 +# set protocols ospf redistribute connected route-map CONNECT +# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64 +# set protocols ospfv3 parameters router-id 192.168.1.1 +# set protocols ospfv3 redistribute connected +# +- name: Delete all the configuration +      vyos_ospf_routes: +        config: +        state: deleted +# +# +# ------------------------- +# Module Execution Result +# ------------------------- +# +# before": [ +#        { +#                { +#                    "afi": "ipv4", +#                    "ospf_area":[ +#                        { +#                            "area": "0",  +#                            "network": "192.168.0.0/24" +#                        } +#                      ], +#                    "default_information":  +#                        { +#                            "originate":  +#                               { +#                                 always: true, +#                                 metric: 2,  +#                                 metric_type: 10  +#                               } +#                        }, +#                   "log_adjacency_changes": "details" +#                   "parameters": +#                        { +#                            "router_id": "10.1.1.1" +#                        }, +#                    "redistribute":[ +#                        { +#                            "route_type": "connetced",  +#                            "metric_type": 2 +#                            "route_map": "CONNECT" +#                        } +#                      ] +#                },  +#                { +#                    "afi": "ipv6",  +#                    "ospf_area":[ +#                        { +#                            "area": "0.0.0.0",  +#                        } +#                       ], +#                    "range": "2001:db8:1::/64",  +#                    "parameters": +#                        { +#                            "router_id": "192.168.1.1" +#                        }, +#                    "redistribute": +#                        [ +#                            { +#                               "route_type": "connetced", +#                            }  +#                        ] +#                } +#    ] +# +#    "commands": [ +#       "delete protocols ospf", +#       "delete protocols ospfv3", +#    ] +# +# "after": [] +# +# After state: +# ------------- +# +# vyos@vyos:~$ show configuration commands| grep firewall + + +""" +RETURN = """ +before: +  description: The configuration prior to the model invocation. +  returned: always +  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 +  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.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import Ospfv2Args +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospfv2.ospfv2 import Ospfv2 + + +def main(): +    """ +    Main entry point for module execution + +    :returns: the result form module invocation +    """ +    required_if = [ +        ("state", "merged", ("config",)), +        ("state", "replaced", ("config",)), +        ("state", "parsed", ("running_config",)), +    ] +    mutually_exclusive = [("config", "running_config")] +    module = AnsibleModule( +        argument_spec=Ospfv2Args.argument_spec, +        required_if=required_if, +        supports_check_mode=True, +        mutually_exclusive=mutually_exclusive, +    ) + +    result = Ospfv2(module).execute_module() +    module.exit_json(**result) + + +if __name__ == '__main__': +    main() | 
