From 17bf6225b3c050162093499b6a47b9df70fe5132 Mon Sep 17 00:00:00 2001 From: omnom62 Date: Mon, 20 Oct 2025 05:41:16 -0500 Subject: [PATCH 01/32] Init VRRP --- .pre-commit-config.yaml | 4 +- README.md | 5 +- changelogs/fragments/t6820_vrrp.yml | 3 + plugins/action/vyos_vrrp.py | 1 + .../network/vyos/argspec/vrrp/__init__.py | 0 .../network/vyos/argspec/vrrp/vrrp.py | 55 + .../network/vyos/config/vrrp/__init__.py | 0 .../network/vyos/config/vrrp/vrrp.py | 404 ++++++ .../module_utils/network/vyos/facts/facts.py | 4 + .../network/vyos/facts/vrrp/__init__.py | 0 .../network/vyos/facts/vrrp/vrrp.py | 104 ++ .../network/vyos/rm_templates/vrrp.py | 473 +++++++ plugins/modules/vyos_vrrp.py | 1128 +++++++++++++++++ 13 files changed, 2177 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/t6820_vrrp.yml create mode 120000 plugins/action/vyos_vrrp.py create mode 100644 plugins/module_utils/network/vyos/argspec/vrrp/__init__.py create mode 100644 plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py create mode 100644 plugins/module_utils/network/vyos/config/vrrp/__init__.py create mode 100644 plugins/module_utils/network/vyos/config/vrrp/vrrp.py create mode 100644 plugins/module_utils/network/vyos/facts/vrrp/__init__.py create mode 100644 plugins/module_utils/network/vyos/facts/vrrp/vrrp.py create mode 100644 plugins/module_utils/network/vyos/rm_templates/vrrp.py create mode 100644 plugins/modules/vyos_vrrp.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d5617c09b..57f1810b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,9 +7,11 @@ ci: repos: - repo: https://github.com/ansible-network/collection_prep - rev: 1.1.1 + rev: 1.1.2 hooks: - id: update-docs + additional_dependencies: + - "ansible-core==2.18.*" - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 diff --git a/README.md b/README.md index 6650cb670..73c6330e7 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,8 @@ compatibility with older versions of VyOS are maintained but not guaranteed. ## Ansible version compatibility -This collection has been tested against following Ansible versions: **>=2.15.0**. +This collection has been tested against the following Ansible versions: **>=2.15.0**. -For collections that support Ansible 2.9, please ensure you update your `network_os` to use the -fully qualified collection name (for example, `cisco.ios.ios`). Plugins and modules within a collection may be tested with only specific Ansible versions. A collection may contain metadata that identifies these versions. PEP440 is the schema used to describe the versions of Ansible. @@ -72,6 +70,7 @@ Name | Description [vyos.vyos.vyos_system](https://github.com/vyos/vyos.vyos/blob/main/docs/vyos.vyos.vyos_system_module.rst)|Run `set system` commands on VyOS devices [vyos.vyos.vyos_user](https://github.com/vyos/vyos.vyos/blob/main/docs/vyos.vyos.vyos_user_module.rst)|Manage the collection of local users on VyOS device [vyos.vyos.vyos_vlan](https://github.com/vyos/vyos.vyos/blob/main/docs/vyos.vyos.vyos_vlan_module.rst)|Manage VLANs on VyOS network devices +[vyos.vyos.vyos_vrrp](https://github.com/vyos/vyos.vyos/blob/main/docs/vyos.vyos.vyos_vrrp_module.rst)|High Availability (VRRP) resource module diff --git a/changelogs/fragments/t6820_vrrp.yml b/changelogs/fragments/t6820_vrrp.yml new file mode 100644 index 000000000..34343bbfd --- /dev/null +++ b/changelogs/fragments/t6820_vrrp.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - vyos_vrrp - Add VRRP (High Availability) support diff --git a/plugins/action/vyos_vrrp.py b/plugins/action/vyos_vrrp.py new file mode 120000 index 000000000..331a791fc --- /dev/null +++ b/plugins/action/vyos_vrrp.py @@ -0,0 +1 @@ +vyos.py \ No newline at end of file diff --git a/plugins/module_utils/network/vyos/argspec/vrrp/__init__.py b/plugins/module_utils/network/vyos/argspec/vrrp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py b/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py new file mode 100644 index 000000000..41cd47ac2 --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the +# cli_rm_builder. +# +# Manually editing this file is not advised. +# +# To update the argspec make the desired changes +# in the module docstring and re-run +# cli_rm_builder. +# +############################################# + +""" +The arg spec for the vyos_vrrp module +""" + + +class VrrpArgs(object): # pylint: disable=R0903 + """The arg spec for the vyos_vrrp module""" + + argument_spec = { + "config": { + "type": "dict", + "options": { + "disable": {"aliases": ["disabled"], "type": "bool", "default": False}, + }, + }, + "state": { + "type": "str", + "choices": [ + "deleted", + "merged", + "purged", + "replaced", + "gathered", + "rendered", + "parsed", + ], + "default": "merged", + }, + "running_config": {"type": "str"}, + } # pylint: disable=C0301 diff --git a/plugins/module_utils/network/vyos/config/vrrp/__init__.py b/plugins/module_utils/network/vyos/config/vrrp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/module_utils/network/vyos/config/vrrp/vrrp.py b/plugins/module_utils/network/vyos/config/vrrp/vrrp.py new file mode 100644 index 000000000..5f51e276d --- /dev/null +++ b/plugins/module_utils/network/vyos/config/vrrp/vrrp.py @@ -0,0 +1,404 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2021 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +""" +The vyos_vrrp config file. +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 its desired end-state is +created. +""" + +from ansible.module_utils.six import iteritems +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( + ResourceModule, +) + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.vrrp import ( + VrrpTemplate, +) + + +# from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( +# dict_merge, +# ) + + +class Vrrp(ResourceModule): + """ + The vyos_vrrp config class + """ + + def __init__(self, module): + super(Vrrp, self).__init__( + empty_fact_val={}, + facts_module=Facts(module), + module=module, + resource="vrrp", + tmplt=VrrpTemplate(), + ) + self.parsers = [] + + def _validate_template(self): + self._tmplt = VrrpTemplate() + + def parse(self): + """override parse to check template""" + self._validate_template() + return super().parse() + + def get_parser(self, name): + """get_parsers""" + self._validate_template() + return super().get_parser(name) + + def execute_module(self): + """Execute the module + + :rtype: A dictionary + :returns: The result from module execution + """ + self._validate_template() + if self.state not in ["parsed", "gathered"]: + self.generate_commands() + self.run_commands() + return self.result + + def generate_commands(self): + """Generate configuration commands to send based on + want, have and desired state. + """ + wantd = {} + haved = {} + + # if ( + # self.want.get("as_number") == self.have.get("as_number") + # or not self.have + # or LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + # ): + # if self.want: + # wantd = {self.want["as_number"]: self.want} + # if self.have: + # haved = {self.have["as_number"]: self.have} + # else: + # self._module.fail_json(msg="Only one bgp instance is allowed per device") + # + # # turn all lists of dicts into dicts prior to merge + # for entry in wantd, haved: + # self._vrrp_list_to_dict(entry) + # + # # if state is merged, merge want onto have and then compare + # if self.state == "merged": + # wantd = dict_merge(haved, wantd) + # + # # if state is deleted, empty out wantd and set haved to wantd + # if self.state == "purged": + # h_del = {} + # for k, v in iteritems(haved): + # if k in wantd or not wantd: + # h_del.update({k: v}) + # for num, entry in iteritems(h_del): + # self.commands.append(self._tmplt.render({"as_number": num}, "router", True)) + # wantd = {} + # + # if self.state == "deleted": + # self._compare(want={}, have=self.have) + # wantd = {} + # + # for k, want in iteritems(wantd): + # self._compare(want=want, have=haved.pop(k, {})) + # + + def _compare(self, want, have): + """Leverages the base class `compare()` method and + populates the list of commands to be run by comparing + the `want` and `have` data with the `parsers` defined + for the vrrp network resource. + """ + # if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + # self._compare_asn(want, have) + # + parsers = ["maximum_paths", "timers"] + self._compare_neighbor(want, have) + self._compare_bgp_params(want, have) + for name, entry in iteritems(want): + if name != "as_number": + self.compare( + parsers=parsers, + want={"as_number": want["as_number"], name: entry}, + have={ + "as_number": want["as_number"], + name: have.pop(name, {}), + }, + ) + for name, entry in iteritems(have): + if name != "as_number": + self.compare( + parsers=parsers, + want={}, + have={"as_number": have["as_number"], name: entry}, + ) + # Do the negation first + command_set = [] + for cmd in self.commands: + if cmd not in command_set: + if "delete" in cmd: + command_set.insert(0, cmd) + else: + command_set.append(cmd) + self.commands = command_set + + def _compare_neighbor(self, want, have): + parsers = [ + "neighbor.advertisement_interval", + "neighbor.allowas_in", + "neighbor.as_override", + "neighbor.attribute_unchanged.as_path", + "neighbor.attribute_unchanged.med", + "neighbor.attribute_unchanged.next_hop", + "neighbor.capability_dynamic", + "neighbor.capability_orf", + "neighbor.default_originate", + "neighbor.description", + "neighbor.disable_capability_negotiation", + "neighbor.disable_connected_check", + "neighbor.disable_send_community", + "neighbor.distribute_list", + "neighbor.ebgp_multihop", + "neighbor.filter_list", + "neighbor.local_as", + "neighbor.maximum_prefix", + "neighbor.nexthop_self", + "neighbor.override_capability", + "neighbor.passive", + "neighbor.password", + "neighbor.peer_group_name", + "neighbor.port", + "neighbor.prefix_list", + "neighbor.remote_as", + "neighbor.remove_private_as", + "neighbor.route_map", + "neighbor.route_reflector_client", + "neighbor.route_server_client", + "neighbor.shutdown", + "neighbor.soft_reconfiguration", + "neighbor.strict_capability_match", + "neighbor.unsuppress_map", + "neighbor.update_source", + "neighbor.weight", + "neighbor.ttl_security", + "neighbor.timers", + ] + + wneigh = want.pop("neighbor", {}) + hneigh = have.pop("neighbor", {}) + self._compare_neigh_lists(wneigh, hneigh) + + for name, entry in iteritems(wneigh): + for k, v in entry.items(): + if k == "address": + continue + if hneigh.get(name): + h = {"address": name, k: hneigh[name].pop(k, {})} + else: + h = {} + self.compare( + parsers=parsers, + want={ + "as_number": want["as_number"], + "neighbor": {"address": name, k: v}, + }, + have={"as_number": want["as_number"], "neighbor": h}, + ) + for name, entry in iteritems(hneigh): + if name not in wneigh.keys(): + if self._check_af(name): + msg = "Use the _bgp_address_family module to delete the address_family under neighbor {0}, before replacing/deleting the neighbor.".format( + name, + ) + self._module.fail_json(msg=msg) + else: + self.commands.append( + "delete protocols bgp" + self._asn_mod + " neighbor " + name, + ) + continue + for k, v in entry.items(): + self.compare( + parsers=parsers, + want={}, + have={ + "as_number": have["as_number"], + "neighbor": {"address": name, k: v}, + }, + ) + + def _compare_bgp_params(self, want, have): + parsers = [ + "bgp_params.always_compare_med", + "bgp_params.bestpath.as_path", + "bgp_params.bestpath.compare_routerid", + "bgp_params.bestpath.med", + "bgp_params.cluster_id", + "bgp_params.confederation", + "bgp_params.dampening_half_life", + "bgp_params.dampening_max_suppress_time", + "bgp_params.dampening_re_use", + "bgp_params.dampening_start_suppress_time", + "bgp_params.default", + "bgp_params.deterministic_med", + "bgp_params.disbale_network_import_check", + "bgp_params.enforce_first_as", + "bgp_params.graceful_restart", + "bgp_params.log_neighbor_changes", + "bgp_params.no_client_to_client_reflection", + "bgp_params.no_fast_external_failover", + "bgp_params.routerid", + "bgp_params.scan_time", + ] + + wbgp = want.pop("bgp_params", {}) + hbgp = have.pop("bgp_params", {}) + for name, entry in iteritems(wbgp): + if name == "confederation": + if entry != hbgp.pop(name, {}): + self.addcmd( + { + "as_number": want["as_number"], + "bgp_params": {name: entry}, + }, + "bgp_params.confederation", + False, + ) + elif name == "distance": + if entry != hbgp.pop(name, {}): + distance_parsers = [ + "bgp_params.distance.global", + "bgp_params.distance.prefix", + ] + for distance_type in entry: + self.compare( + parsers=distance_parsers, + want={ + "as_number": want["as_number"], + "bgp_params": {name: distance_type}, + }, + have={ + "as_number": want["as_number"], + "bgp_params": {name: hbgp.pop(name, {})}, + }, + ) + else: + self.compare( + parsers=parsers, + want={ + "as_number": want["as_number"], + "bgp_params": {name: entry}, + }, + have={ + "as_number": want["as_number"], + "bgp_params": {name: hbgp.pop(name, {})}, + }, + ) + if not wbgp and hbgp: + self.commands.append("delete protocols bgp" + self._asn_mod + " parameters") + hbgp = {} + for name, entry in iteritems(hbgp): + if name == "confederation": + self.commands.append( + "delete protocols bgp" + self._asn_mod + " parameters confederation", + ) + elif name == "distance": + distance_parsers = [ + "bgp_params.distance.global", + "bgp_params.distance.prefix", + ] + self.compare( + parsers=distance_parsers, + want={}, + have={ + "as_number": have["as_number"], + "bgp_params": {name: entry[0]}, + }, + ) + else: + self.compare( + parsers=parsers, + want={}, + have={ + "as_number": have["as_number"], + "bgp_params": {name: entry}, + }, + ) + + def _compare_neigh_lists(self, want, have): + for attrib in [ + "distribute_list", + "filter_list", + "prefix_list", + "route_map", + ]: + wdict = want.pop(attrib, {}) + hdict = have.pop(attrib, {}) + for key, entry in iteritems(wdict): + if entry != hdict.pop(key, {}): + self.addcmd(entry, "neighbor.{0}".format(attrib), False) + # remove remaining items in have for replaced + for entry in hdict.values(): + self.addcmd(entry, "neighbor.{0}".format(attrib), True) + + def _vrrp_list_to_dict(self, entry): + for name, proc in iteritems(entry): + if "neighbor" in proc: + neigh_dict = {} + for entry in proc.get("neighbor", []): + neigh_dict.update({entry["address"]: entry}) + proc["neighbor"] = neigh_dict + + if "network" in proc: + network_dict = {} + for entry in proc.get("network", []): + network_dict.update({entry["address"]: entry}) + proc["network"] = network_dict + + if "aggregate_address" in proc: + agg_dict = {} + for entry in proc.get("aggregate_address", []): + agg_dict.update({entry["prefix"]: entry}) + proc["aggregate_address"] = agg_dict + + if "redistribute" in proc: + redis_dict = {} + for entry in proc.get("redistribute", []): + redis_dict.update({entry["protocol"]: entry}) + proc["redistribute"] = redis_dict + + def _compare_asn(self, want, have): + if want.get("as_number") and not have.get("as_number"): + self.commands.append( + "set protocols bgp " + "system-as" + " " + str(want.get("as_number")), + ) + + def _check_af(self, neighbor): + af_present = False + if self._connection: + config_lines = self._get_config(self._connection).splitlines() + for line in config_lines: + if neighbor in line: + if "address-family" in line: + af_present = True + return af_present + + def _get_config(self, connection): + return connection.get( + 'show configuration commands | match "set protocols bgp .*neighbor"', + ) diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py index 74bbda747..8cd7cbce9 100644 --- a/plugins/module_utils/network/vyos/facts/facts.py +++ b/plugins/module_utils/network/vyos/facts/facts.py @@ -80,6 +80,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes import ( Static_routesFacts, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.vrrp.vrrp import ( + VrrpFacts, +) FACT_LEGACY_SUBSETS = dict(default=Default, neighbors=Neighbors, config=Config) @@ -104,6 +107,7 @@ ntp_global=Ntp_globalFacts, snmp_server=Snmp_serverFacts, hostname=HostnameFacts, + vrrp=VrrpFacts, ) diff --git a/plugins/module_utils/network/vyos/facts/vrrp/__init__.py b/plugins/module_utils/network/vyos/facts/vrrp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py new file mode 100644 index 000000000..43a70b95e --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2021 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +""" +The vyos vrrp 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. +""" + +import re + +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.vrrp.vrrp import ( + VrrpArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.vrrp import ( + VrrpTemplate, +) + + +class VrrpFacts(object): + """The vyos vrrp facts class""" + + def __init__(self, module, subspec="config", options="options"): + self._module = module + self.argument_spec = VrrpArgs.argument_spec + + def get_device_data(self, connection): + return connection.get('show configuration commands | match "set high-availability"') + + def get_config_set(self, data, connection): + """To classify the configurations beased on vrrp""" + config_dict = {} + for config_line in data.splitlines(): + vrrp_grp = re.search(r"set high-availability vrrp group (\S+).*", config_line) + vrrp_vsrv = re.search(r"set high-availability virtual-server (\S+).*", config_line) + vrrp_disable = re.search(r"set high-availability disable", config_line) + if vrrp_disable: + config_dict["disable"] = config_dict.get("disable", "") + config_line + "\n" + if vrrp_grp: + config_dict[vrrp_grp.group(1)] = ( + config_dict.get(vrrp_grp.group(1), "") + config_line + "\n" + ) + return list(config_dict.values()) + + def populate_facts(self, connection, ansible_facts, data=None): + """Populate the facts for vrrp network resource + + :param connection: the device connection + :param ansible_facts: Facts dictionary + :param data: previously collected conf + + :rtype: dictionary + :returns: facts + """ + facts = {} + objs = {} + config_lines = [] + + if not data: + data = self.get_device_data(connection) + + vrrp_facts = {} + resources = self.get_config_set(data, connection) + + for resource in resources: + vrrp_parser = VrrpTemplate( + lines=resource.split("\n"), + module=self._module, + ) + objs = vrrp_parser.parse() + self._module.fail_json(msg=str(resource.split("\n")) + str(objs)) + if objs: + self._module.fail_json(msg=str(objs)) + + # for resource in data.splitlines(): + # if "address-family" not in resource: + # config_lines.append(re.sub("'", "", resource)) + # + # vrrp_parser = VrrpTemplate(lines=config_lines, module=self._module) + # + # objs = vrrp_parser.parse() + # self._module.fail_json(msg=objs) + + ansible_facts["ansible_network_resources"].pop("vrrp", None) + + params = utils.remove_empties( + vrrp_parser.validate_config(self.argument_spec, {"config": objs}, redact=True), + ) + + facts["vrrp"] = params.get("config", []) + ansible_facts["ansible_network_resources"].update(facts) + self._module.fail_json(msg=ansible_facts) + + return ansible_facts diff --git a/plugins/module_utils/network/vyos/rm_templates/vrrp.py b/plugins/module_utils/network/vyos/rm_templates/vrrp.py new file mode 100644 index 000000000..c285416e3 --- /dev/null +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -0,0 +1,473 @@ +# -*- coding: utf-8 -*- +# Copyright 2021 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +""" +The Bgp_global parser templates file. This contains +a list of parser definitions and associated functions that +facilitates both facts gathering and native command generation for +the given network resource. +""" + +import re + +# from ansible.module_utils.six import iteritems +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( + NetworkTemplate, +) + + +class VrrpTemplate(NetworkTemplate): + def __init__(self, lines=None, module=None): + prefix = {"set": "set", "remove": "delete"} + super(VrrpTemplate, self).__init__( + lines=lines, + tmplt=self, + prefix=prefix, + module=module, + ) + + # fmt: off + PARSERS = [ + { + "name": "disable", + "getval": re.compile( + r""" + ^set + \shigh-availability + \s(?Pdisable) + $""", + re.VERBOSE, + ), + "setval": "high-availability disable", + "result": { + "disable": "{{ True if disable is defined }}", + }, + }, + { + "name": "vg_global_garp_interval", + "getval": re.compile( + r""" + ^set + \shigh-availability + \s(?Pdisable) + $""", + re.VERBOSE, + ), + "setval": "high-availability disable", + "result": { + "disable": "{{ True if disable is defined }}", + }, + }, + { + "name": "vg_addr", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \saddress + \s(?P
\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} address {{address}}", + "compval": "address", + "result": { + "group": "{{ group }}", + "address": "{{ address }}", + }, + }, + { + "name": "vg_addr_addr_int", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \saddress + \s(?P
\S+) + \sinterface + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} address {{address}} interface {{interface}}", + "compval": "interface", + "result": { + "group": "{{ group }}", + "address": "{{ address }}", + "interface": "{{ interface }}", + }, + }, + { + "name": "vg_excluded_addr", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sexcluded-address + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} excluded-address {{excluded_addr}}", + "compval": "excluded_address", + "result": { + "group": "{{ group }}", + "excluded_address": "{{ excluded_addr }}", + }, + }, + { + "name": "vg_excluded_addr_int", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sexcluded-address + \s(?P\S+) + \sinterface + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} excluded-address {{excluded_addr}} interface {{excluded_addr_interface}}", + "compval": "excluded_address_interface", + "result": { + "group": "{{ group }}", + "excluded_address_interface": "{{ excluded_address_int }}", + }, + }, + { + "name": "vg_priority", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \spriority + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} priority {{priority}}", + "compval": "priority", + "result": { + "group": "{{ group }}", + "priority": "{{ priority }}", + }, + }, + { + "name": "vg_advertise_interval", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sadvertise-interval + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} advertise-interval {{adv_int}}", + "compval": "advertise_interval", + "result": { + "group": "{{ group }}", + "advertise_interval": "{{ adv_int }}", + }, + }, + { + "name": "vg_description", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sdescription + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} description {{description}}", + "compval": "description", + "result": { + "group": "{{ group }}", + "description": "{{ description }}", + }, + }, + { + "name": "vg_vrid", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \svrid + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} vrid {{vrid}}", + "compval": "vrid", + "result": { + "group": "{{ group }}", + "vrid": "{{ vrid }}", + }, + }, + { + "name": "vg_no_preempt", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \s(?Pno-preempt) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} no-preempt", + "compval": "no_preempt", + "result": { + "group": "{{ group }}", + "no_preempt": "{{ True if np is defined }}", + }, + }, + { + "name": "vg_preempt_delay", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \spreempt-delay + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} preempt-delay {{prd}}", + "compval": "preempt_delay", + "result": { + "group": "{{ group }}", + "preempt-delay": "{{ prd }}", + }, + }, + { + "name": "vg_authentication_password", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sauthentication + \spassword + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} authentication password {{pass}}", + "compval": "pass", + "result": { + "group": "{{ group }}", + "authentication": { + "password": "{{ pass }}", + }, + }, + }, + { + "name": "vg_authentication_type", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sauthentication + \stype + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} authentication type {{type}}", + "compval": "type", + "result": { + "group": "{{ group }}", + "authentication": { + "password": "{{ type }}", + }, + }, + }, + { + "name": "vg_rfc3768", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \srfc3768-compatibility + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} rfc3768-compatibility {{rfc3768}}", + "compval": "rfc3768_compatibility", + "result": { + "group": "{{ group }}", + "rfc3768_compatibility": "{{ True if rfc3768 is defined }}", + }, + }, + { + "name": "vg_garp_interval", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sgarp + \sinterval + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} garp interval {{garp_int}}", + "compval": "interval", + "result": { + "group": "{{ group }}", + "garp": { + "interval": "{{ garp_int}}", + }, + }, + }, + { + "name": "vg_garp_master_delay", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sgarp + \smaster-delay + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} garp master-delay {{garp_mdelay}}", + "compval": "master_delay", + "result": { + "group": "{{ group }}", + "garp": { + "master_delay": "{{ garp_mdelay }}", + }, + }, + }, + { + "name": "vg_garp_master_refresh", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sgarp + \smaster-refresh + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} garp master-refresh {{garp_mrefresh}}", + "compval": "master_refresh", + "result": { + "group": "{{ group }}", + "garp": { + "master_refresh": "{{ garp_mrefresh }}", + }, + }, + }, + { + "name": "vg_garp_master_refresh_repeat", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sgarp + \smaster-refresh-repeat + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} garp master-refresh-repeat {{garp_mrefresh_repeat}}", + "compval": "master_refresh_repeat", + "result": { + "group": "{{ group }}", + "garp": { + "master_refresh_repeat": "{{ garp_mrefresh_repeat }}", + }, + }, + }, + { + "name": "vg_garp_master_repeat", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sgroup + \s(?P\S+) + \sgarp + \smaster-repeat + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp group {{group}} garp master-repeat {{garp_mrepeat}}", + "compval": "master_repeat", + "result": { + "group": "{{ group }}", + "garp": { + "master_repeat": "{{ garp_mrepeat }}", + }, + }, + }, + + ] + # fmt: on diff --git a/plugins/modules/vyos_vrrp.py b/plugins/modules/vyos_vrrp.py new file mode 100644 index 000000000..e56b84f77 --- /dev/null +++ b/plugins/modules/vyos_vrrp.py @@ -0,0 +1,1128 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2024 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_vrrp +""" + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_vrrp +version_added: 1.0.0 +short_description: High Availability (VRRP) resource module +description: +- This module manages VRRP configuration of interfaces on devices running VYOS. +- The provided examples of commands are valid for VyOS 1.4+ +author: +- Evgeny Molotkov (@omnom62) +options: + config: + description: A dict of VRRP configuration. + type: dict + suboptions: + disable: + default: false + description: Disable instance + type: bool + state: + description: + - The state the configuration should be left in. + - State I(purged) removes all the BGP configurations from the + target device. Use caution with this state.('delete protocols bgp ') + - State I(deleted) only removes BGP attributes that this modules + manages and does not negate the BGP process completely. Thereby, preserving + address-family related configurations under BGP context. + - Running states I(deleted) and I(replaced) will result in an error if there + are address-family configuration lines present under neighbor context that is + is to be removed. Please use the M(vyos.vyos.vyos_bgp_address_family) + module for prior cleanup. + - Refer to examples for more details. + type: str + choices: [deleted, merged, purged, replaced, gathered, rendered, parsed] + default: merged + running_config: + description: + - This option is used only with state I(parsed). + - The value of this option should be the output received from the EOS device by + executing the command B(show running-config | section bgp). + - The state I(parsed) reads the configuration from C(running_config) option and + transforms it into Ansible structured data as per the resource module's argspec + and the value is then returned in the I(parsed) key within the result. + type: str +""" + +EXAMPLES = """ +# Using merged +# Before state + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# vyos@vyos:~$ + +- name: Merge provided configuration with device configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + aggregate_address: + - prefix: "203.0.113.0/24" + as_set: true + - prefix: "192.0.2.0/24" + summary_only: true + network: + - address: "192.1.13.0/24" + backdoor: true + redistribute: + - protocol: "kernel" + metric: 45 + - protocol: "connected" + route_map: "map01" + maximum_paths: + - path: "ebgp" + count: 20 + - path: "ibgp" + count: 55 + timers: + keepalive: 35 + bgp_params: + bestpath: + as_path: "confed" + compare_routerid: true + default: + no_ipv4_unicast: true + router_id: "192.1.2.9" + confederation: + - peers: 20 + - peers: 55 + - identifier: 66 + neighbor: + - address: "192.0.2.25" + disable_connected_check: true + timers: + holdtime: 30 + keepalive: 10 + - address: "203.0.113.5" + attribute_unchanged: + as_path: true + med: true + ebgp_multihop: 2 + remote_as: 101 + update_source: "192.0.2.25" + - address: "5001::64" + maximum_prefix: 34 + distribute_list: + - acl: 20 + action: "export" + - acl: 40 + action: "import" + state: merged + +# After State +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' +# vyos@vyos:~$ +# +# # Module Execution: +# +# "after": { +# "aggregate_address": [ +# { +# "prefix": "192.0.2.0/24", +# "summary_only": true +# }, +# { +# "prefix": "203.0.113.0/24", +# "as_set": true +# } +# ], +# "as_number": 65536, +# "bgp_params": { +# "bestpath": { +# "as_path": "confed", +# "compare_routerid": true +# }, +# "confederation": [ +# { +# "identifier": 66 +# }, +# { +# "peers": 20 +# }, +# { +# "peers": 55 +# } +# ], +# "default": { +# "no_ipv4_unicast": true +# }, +# "router_id": "192.1.2.9" +# }, +# "maximum_paths": [ +# { +# "count": 20, +# "path": "ebgp" +# }, +# { +# "count": 55, +# "path": "ibgp" +# } +# ], +# "neighbor": [ +# { +# "address": "192.0.2.25", +# "disable_connected_check": true, +# "timers": { +# "holdtime": 30, +# "keepalive": 10 +# } +# }, +# { +# "address": "203.0.113.5", +# "attribute_unchanged": { +# "as_path": true, +# "med": true, +# "next_hop": true +# }, +# "ebgp_multihop": 2, +# "remote_as": 101, +# "update_source": "192.0.2.25" +# }, +# { +# "address": "5001::64", +# "distribute_list": [ +# { +# "acl": 20, +# "action": "export" +# }, +# { +# "acl": 40, +# "action": "import" +# } +# ], +# "maximum_prefix": 34 +# } +# ], +# "network": [ +# { +# "address": "192.1.13.0/24", +# "backdoor": true +# } +# ], +# "redistribute": [ +# { +# "protocol": "connected", +# "route_map": "map01" +# }, +# { +# "metric": 45, +# "protocol": "kernel" +# } +# ], +# "timers": { +# "keepalive": 35 +# } +# }, +# "before": {}, +# "changed": true, +# "commands": [ +# "set protocols bgp neighbor 192.0.2.25 disable-connected-check", +# "set protocols bgp neighbor 192.0.2.25 timers holdtime 30", +# "set protocols bgp neighbor 192.0.2.25 timers keepalive 10", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged as-path", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged med", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged next-hop", +# "set protocols bgp neighbor 203.0.113.5 ebgp-multihop 2", +# "set protocols bgp neighbor 203.0.113.5 remote-as 101", +# "set protocols bgp neighbor 203.0.113.5 update-source 192.0.2.25", +# "set protocols bgp neighbor 5001::64 maximum-prefix 34", +# "set protocols bgp neighbor 5001::64 distribute-list export 20", +# "set protocols bgp neighbor 5001::64 distribute-list import 40", +# "set protocols bgp redistribute kernel metric 45", +# "set protocols bgp redistribute connected route-map map01", +# "set protocols bgp network 192.1.13.0/24 backdoor", +# "set protocols bgp aggregate-address 203.0.113.0/24 as-set", +# "set protocols bgp aggregate-address 192.0.2.0/24 summary-only", +# "set protocols bgp parameters bestpath as-path confed", +# "set protocols bgp parameters bestpath compare-routerid", +# "set protocols bgp parameters default no-ipv4-unicast", +# "set protocols bgp parameters router-id 192.1.2.9", +# "set protocols bgp parameters confederation peers 20", +# "set protocols bgp parameters confederation peers 55", +# "set protocols bgp parameters confederation identifier 66", +# "set protocols bgp maximum-paths ebgp 20", +# "set protocols bgp maximum-paths ibgp 55", +# "set protocols bgp timers keepalive 35" +# ], + +# Using replaced: +# -------------- + +# Before state: + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' +# vyos@vyos:~$ + +- name: Replace + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + network: + - address: "203.0.113.0/24" + route_map: map01 + redistribute: + - protocol: "static" + route_map: "map01" + neighbor: + - address: "192.0.2.40" + advertisement_interval: 72 + capability: + orf: "receive" + bgp_params: + bestpath: + as_path: "confed" + state: replaced +# After state: + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp redistribute static route-map 'map01' +# vyos@vyos:~$ +# +# +# Module Execution: +# +# "after": { +# "as_number": 65536, +# "bgp_params": { +# "bestpath": { +# "as_path": "confed" +# } +# }, +# "neighbor": [ +# { +# "address": "192.0.2.40", +# "advertisement_interval": 72, +# "capability": { +# "orf": "receive" +# } +# } +# ], +# "network": [ +# { +# "address": "203.0.113.0/24", +# "route_map": "map01" +# } +# ], +# "redistribute": [ +# { +# "protocol": "static", +# "route_map": "map01" +# } +# ] +# }, +# "before": { +# "aggregate_address": [ +# { +# "prefix": "192.0.2.0/24", +# "summary_only": true +# }, +# { +# "prefix": "203.0.113.0/24", +# "as_set": true +# } +# ], +# "as_number": 65536, +# "bgp_params": { +# "bestpath": { +# "as_path": "confed", +# "compare_routerid": true +# }, +# "confederation": [ +# { +# "identifier": 66 +# }, +# { +# "peers": 20 +# }, +# { +# "peers": 55 +# } +# ], +# "default": { +# "no_ipv4_unicast": true +# }, +# "router_id": "192.1.2.9" +# }, +# "maximum_paths": [ +# { +# "count": 20, +# "path": "ebgp" +# }, +# { +# "count": 55, +# "path": "ibgp" +# } +# ], +# "neighbor": [ +# { +# "address": "192.0.2.25", +# "disable_connected_check": true, +# "timers": { +# "holdtime": 30, +# "keepalive": 10 +# } +# }, +# { +# "address": "203.0.113.5", +# "attribute_unchanged": { +# "as_path": true, +# "med": true, +# "next_hop": true +# }, +# "ebgp_multihop": 2, +# "remote_as": 101, +# "update_source": "192.0.2.25" +# }, +# { +# "address": "5001::64", +# "distribute_list": [ +# { +# "acl": 20, +# "action": "export" +# }, +# { +# "acl": 40, +# "action": "import" +# } +# ], +# "maximum_prefix": 34 +# } +# ], +# "network": [ +# { +# "address": "192.1.13.0/24", +# "backdoor": true +# } +# ], +# "redistribute": [ +# { +# "protocol": "connected", +# "route_map": "map01" +# }, +# { +# "metric": 45, +# "protocol": "kernel" +# } +# ], +# "timers": { +# "keepalive": 35 +# } +# }, +# "changed": true, +# "commands": [ +# "delete protocols bgp timers", +# "delete protocols bgp maximum-paths ", +# "delete protocols bgp maximum-paths ", +# "delete protocols bgp parameters router-id 192.1.2.9", +# "delete protocols bgp parameters default", +# "delete protocols bgp parameters confederation", +# "delete protocols bgp parameters bestpath compare-routerid", +# "delete protocols bgp aggregate-address", +# "delete protocols bgp network 192.1.13.0/24", +# "delete protocols bgp redistribute kernel", +# "delete protocols bgp redistribute kernel", +# "delete protocols bgp redistribute connected", +# "delete protocols bgp redistribute connected", +# "delete protocols bgp neighbor 5001::64", +# "delete protocols bgp neighbor 203.0.113.5", +# "delete protocols bgp neighbor 192.0.2.25", +# "set protocols bgp neighbor 192.0.2.40 advertisement-interval 72", +# "set protocols bgp neighbor 192.0.2.40 capability orf prefix-list receive", +# "set protocols bgp redistribute static route-map map01", +# "set protocols bgp network 203.0.113.0/24 route-map map01" +# ], + +# Using deleted: +# ------------- + +# Before state: + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp redistribute static route-map 'map01' +# vyos@vyos:~$ + +- name: Delete configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + state: deleted + +# After state: + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp '65536' +# vyos@vyos:~$ +# +# +# Module Execution: +# +# "after": { +# "as_number": 65536 +# }, +# "before": { +# "as_number": 65536, +# "bgp_params": { +# "bestpath": { +# "as_path": "confed" +# } +# }, +# "neighbor": [ +# { +# "address": "192.0.2.40", +# "advertisement_interval": 72, +# "capability": { +# "orf": "receive" +# } +# } +# ], +# "network": [ +# { +# "address": "203.0.113.0/24", +# "route_map": "map01" +# } +# ], +# "redistribute": [ +# { +# "protocol": "static", +# "route_map": "map01" +# } +# ] +# }, +# "changed": true, +# "commands": [ +# "delete protocols bgp neighbor 192.0.2.40", +# "delete protocols bgp redistribute", +# "delete protocols bgp network", +# "delete protocols bgp parameters" +# ], + +# Using purged: + +# Before state: + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' +# vyos@vyos:~$ + + +- name: Purge configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + state: purged + +# After state: + +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# vyos@vyos:~$ +# +# Module Execution: +# +# "after": {}, +# "before": { +# "aggregate_address": [ +# { +# "prefix": "192.0.2.0/24", +# "summary_only": true +# }, +# { +# "prefix": "203.0.113.0/24", +# "as_set": true +# } +# ], +# "as_number": 65536, +# "bgp_params": { +# "bestpath": { +# "as_path": "confed", +# "compare_routerid": true +# }, +# "confederation": [ +# { +# "identifier": 66 +# }, +# { +# "peers": 20 +# }, +# { +# "peers": 55 +# } +# ], +# "default": { +# "no_ipv4_unicast": true +# }, +# "router_id": "192.1.2.9" +# }, +# "maximum_paths": [ +# { +# "count": 20, +# "path": "ebgp" +# }, +# { +# "count": 55, +# "path": "ibgp" +# } +# ], +# "neighbor": [ +# { +# "address": "192.0.2.25", +# "disable_connected_check": true, +# "timers": { +# "holdtime": 30, +# "keepalive": 10 +# } +# }, +# { +# "address": "203.0.113.5", +# "attribute_unchanged": { +# "as_path": true, +# "med": true, +# "next_hop": true +# }, +# "ebgp_multihop": 2, +# "remote_as": 101, +# "update_source": "192.0.2.25" +# }, +# { +# "address": "5001::64", +# "distribute_list": [ +# { +# "acl": 20, +# "action": "export" +# }, +# { +# "acl": 40, +# "action": "import" +# } +# ], +# "maximum_prefix": 34 +# } +# ], +# "network": [ +# { +# "address": "192.1.13.0/24", +# "backdoor": true +# } +# ], +# "redistribute": [ +# { +# "protocol": "connected", +# "route_map": "map01" +# }, +# { +# "metric": 45, +# "protocol": "kernel" +# } +# ], +# "timers": { +# "keepalive": 35 +# } +# }, +# "changed": true, +# "commands": [ +# "delete protocols bgp 65536" +# ], + + +# Deleted in presence of address family under neighbors: + +# Before state: +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' +# vyos@vyos:~$ ^C +# vyos@vyos:~$ + +- name: Delete configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + state: deleted + +# Module Execution: +# +# "changed": false, +# "invocation": { +# "module_args": { +# "config": { +# "aggregate_address": null, +# "as_number": 65536, +# "bgp_params": null, +# "maximum_paths": null, +# "neighbor": null, +# "network": null, +# "redistribute": null, +# "timers": null +# }, +# "running_config": null, +# "state": "deleted" +# } +# }, +# "msg": "Use the _bgp_address_family module to delete the address_family under neighbor 203.0.113.0, before replacing/deleting the neighbor." +# } + +# using gathered: +# -------------- + +# Before state: +# vyos@vyos:~$ show configuration commands | match "set protocols bgp" +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' +# vyos@vyos:~$ ^C + +- name: gather configs + vyos.vyos.vyos_vrrp: + state: gathered + +# Module Execution: +# "gathered": { +# "as_number": 65536, +# "bgp_params": { +# "always_compare_med": true, +# "bestpath": { +# "as_path": "confed", +# "compare_routerid": true +# }, +# "default": { +# "no_ipv4_unicast": true +# }, +# "distance": [ +# { +# "type": "external", +# "value": 66 +# }, +# { +# "type": "internal", +# "value": 20 +# }, +# { +# "type": "local", +# "value": 10 +# } +# ] +# }, +# "neighbor": [ +# { +# "address": "192.0.2.43", +# "advertisement_interval": 72, +# "capability": { +# "dynamic": true +# }, +# "disable_connected_check": true, +# "timers": { +# "holdtime": 30, +# "keepalive": 10 +# } +# }, +# { +# "address": "203.0.113.0", +# "capability": { +# "orf": "receive" +# } +# } +# ], +# "network": [ +# { +# "address": "203.0.113.0/24", +# "route_map": "map01" +# } +# ], +# "redistribute": [ +# { +# "protocol": "static", +# "route_map": "map01" +# } +# ] +# }, +# + +# Using parsed: +# ------------ + +# parsed.cfg + +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' + +- name: parse configs + vyos.vyos.vyos_vrrp: + running_config: "{{ lookup('file', './parsed.cfg') }}" + state: parsed + tags: + - parsed + +# Module execution: +# "parsed": { +# "as_number": 65536, +# "bgp_params": { +# "always_compare_med": true, +# "bestpath": { +# "as_path": "confed", +# "compare_routerid": true +# }, +# "default": { +# "no_ipv4_unicast": true +# }, +# "distance": [ +# { +# "type": "external", +# "value": 66 +# }, +# { +# "type": "internal", +# "value": 20 +# }, +# { +# "type": "local", +# "value": 10 +# } +# ] +# }, +# "neighbor": [ +# { +# "address": "192.0.2.43", +# "advertisement_interval": 72, +# "capability": { +# "dynamic": true +# }, +# "disable_connected_check": true, +# "timers": { +# "holdtime": 30, +# "keepalive": 10 +# } +# }, +# { +# "address": "203.0.113.0", +# "capability": { +# "orf": "receive" +# } +# } +# ], +# "network": [ +# { +# "address": "203.0.113.0/24", +# "route_map": "map01" +# } +# ], +# "redistribute": [ +# { +# "protocol": "static", +# "route_map": "map01" +# } +# ] +# } +# + +# Using rendered: +# -------------- + +- name: Render + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + network: + - address: "203.0.113.0/24" + route_map: map01 + redistribute: + - protocol: "static" + route_map: "map01" + bgp_params: + always_compare_med: true + dampening: + start_suppress_time: 5 + max_suppress_time: 20 + half_life: 33 + re_use: 60 + distance: + - type: "internal" + value: 20 + - type: "local" + value: 10 + - type: "external" + value: 66 + bestpath: + as_path: "confed" + compare_routerid: true + default: + no_ipv4_unicast: true + neighbor: + - address: "192.0.2.43" + disable_connected_check: true + advertisement_interval: 72 + capability: + dynamic: true + timers: + holdtime: 30 + keepalive: 10 + - address: "203.0.113.0" + capability: + orf: "receive" + state: rendered + +# Module Execution: +# "rendered": [ +# "set protocols bgp neighbor 192.0.2.43 disable-connected-check", +# "set protocols bgp neighbor 192.0.2.43 advertisement-interval 72", +# "set protocols bgp neighbor 192.0.2.43 capability dynamic", +# "set protocols bgp neighbor 192.0.2.43 timers holdtime 30", +# "set protocols bgp neighbor 192.0.2.43 timers keepalive 10", +# "set protocols bgp neighbor 203.0.113.0 capability orf prefix-list receive", +# "set protocols bgp redistribute static route-map map01", +# "set protocols bgp network 203.0.113.0/24 route-map map01", +# "set protocols bgp parameters always-compare-med", +# "set protocols bgp parameters dampening half-life 33", +# "set protocols bgp parameters dampening max-suppress-time 20", +# "set protocols bgp parameters dampening re-use 60", +# "set protocols bgp parameters dampening start-suppress-time 5", +# "set protocols bgp parameters distance global internal 20", +# "set protocols bgp parameters distance global local 10", +# "set protocols bgp parameters distance global external 66", +# "set protocols bgp parameters bestpath as-path confed", +# "set protocols bgp parameters bestpath compare-routerid", +# "set protocols bgp parameters default no-ipv4-unicast" +# ] +""" + +RETURN = """ +before: + description: The configuration prior to the module execution. + returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: dict + sample: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + This output will always be in the same format as the + module argspec. +commands: + description: The set of commands pushed to the remote device. + returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: list + sample: + - set protocols bgp redistribute static route-map map01 + - set protocols bgp network 203.0.113.0/24 route-map map01 + - set protocols bgp parameters always-compare-med +rendered: + description: The provided configuration in the task rendered in device-native format (offline). + returned: when I(state) is C(rendered) + type: list + sample: + - set protocols bgp redistribute static route-map map01 + - set protocols bgp network 203.0.113.0/24 route-map map01 + - set protocols bgp parameters always-compare-med +gathered: + description: Facts about the network resource gathered from the remote device as structured data. + returned: when I(state) is C(gathered) + type: list + sample: > + This output will always be in the same format as the + module argspec. +parsed: + description: The device native config provided in I(running_config) option parsed into structured data as per module argspec. + returned: when I(state) is C(parsed) + type: list + sample: > + This output will always be in the same format as the + module argspec. +""" + +from ansible.module_utils.basic import AnsibleModule + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.vrrp.vrrp import ( + VrrpArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.vrrp.vrrp import ( + Vrrp, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=VrrpArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Vrrp(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() From 39192ba2a60ad77a67032d8b03caa18574a93c12 Mon Sep 17 00:00:00 2001 From: omnom62 Date: Thu, 23 Oct 2025 14:36:11 -0500 Subject: [PATCH 02/32] RM Templates --- .../network/vyos/argspec/vrrp/vrrp.py | 8 ++++ .../network/vyos/facts/vrrp/vrrp.py | 47 ++++++++++++++----- .../network/vyos/rm_templates/vrrp.py | 17 +------ 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py b/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py index 41cd47ac2..86afeedc7 100644 --- a/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py @@ -36,6 +36,14 @@ class VrrpArgs(object): # pylint: disable=R0903 "type": "dict", "options": { "disable": {"aliases": ["disabled"], "type": "bool", "default": False}, + "virtual_server": { + "type": "list", + "elements": "dict", + "options": { + "name": {"required": True, "type": "str"}, + "address": {"type": "str"}, + }, + }, }, }, "state": { diff --git a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py index 43a70b95e..82b076f05 100644 --- a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py @@ -42,10 +42,28 @@ def get_config_set(self, data, connection): config_dict = {} for config_line in data.splitlines(): vrrp_grp = re.search(r"set high-availability vrrp group (\S+).*", config_line) + vrrp_snmp = re.search(r"set high-availability vrrp snmp", config_line) + vrrp_gp = re.search( + r"set high-availability vrrp global-parameters (\S+).*", + config_line, + ) + vrrp_sg = re.search(r"set high-availability vrrp sync-group (\S+).*", config_line) vrrp_vsrv = re.search(r"set high-availability virtual-server (\S+).*", config_line) vrrp_disable = re.search(r"set high-availability disable", config_line) if vrrp_disable: config_dict["disable"] = config_dict.get("disable", "") + config_line + "\n" + if vrrp_gp: + config_dict["global_parameters"] = ( + config_dict.get(vrrp_gp.group(1), "") + config_line + "\n" + ) + if vrrp_vsrv: + config_dict["virtual_server"] = ( + config_dict.get(vrrp_vsrv.group(1), "") + config_line + "\n" + ) + if vrrp_sg: + config_dict["sync_group"] = ( + config_dict.get(vrrp_sg.group(1), "") + config_line + "\n" + ) if vrrp_grp: config_dict[vrrp_grp.group(1)] = ( config_dict.get(vrrp_grp.group(1), "") + config_line + "\n" @@ -70,6 +88,9 @@ def populate_facts(self, connection, ansible_facts, data=None): data = self.get_device_data(connection) vrrp_facts = {} + groups = [] + sync_groups = [] + vsvrs = [] resources = self.get_config_set(data, connection) for resource in resources: @@ -78,19 +99,21 @@ def populate_facts(self, connection, ansible_facts, data=None): module=self._module, ) objs = vrrp_parser.parse() - self._module.fail_json(msg=str(resource.split("\n")) + str(objs)) + # self._module.fail_json(msg=str(resource.split("\n")) + "******" + str(objs)) if objs: - self._module.fail_json(msg=str(objs)) - - # for resource in data.splitlines(): - # if "address-family" not in resource: - # config_lines.append(re.sub("'", "", resource)) - # - # vrrp_parser = VrrpTemplate(lines=config_lines, module=self._module) - # - # objs = vrrp_parser.parse() - # self._module.fail_json(msg=objs) - + if "disable" in objs: + vrrp_facts.update(objs) + if "group" in objs: + groups.append(objs) + if "virtual_server" in objs: + vsvrs.append(objs) + if "sync_group" in objs: + sync_groups.append(objs) + + if groups: + vrrp_facts.update({"groups": groups}) + + self._module.fail_json(msg=str(vrrp_facts)) ansible_facts["ansible_network_resources"].pop("vrrp", None) params = utils.remove_empties( diff --git a/plugins/module_utils/network/vyos/rm_templates/vrrp.py b/plugins/module_utils/network/vyos/rm_templates/vrrp.py index c285416e3..01e77e974 100644 --- a/plugins/module_utils/network/vyos/rm_templates/vrrp.py +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -50,21 +50,6 @@ def __init__(self, lines=None, module=None): "disable": "{{ True if disable is defined }}", }, }, - { - "name": "vg_global_garp_interval", - "getval": re.compile( - r""" - ^set - \shigh-availability - \s(?Pdisable) - $""", - re.VERBOSE, - ), - "setval": "high-availability disable", - "result": { - "disable": "{{ True if disable is defined }}", - }, - }, { "name": "vg_addr", "getval": re.compile( @@ -206,7 +191,7 @@ def __init__(self, lines=None, module=None): \sgroup \s(?P\S+) \sdescription - \s(?P\S+) + \s(?P.*) $""", re.VERBOSE, ), From 2786c327da895160ce9ccbcfbd457c79c0375931 Mon Sep 17 00:00:00 2001 From: omnom62 Date: Fri, 24 Oct 2025 15:48:11 -0500 Subject: [PATCH 03/32] rm_templates for global_parameters --- .../network/vyos/facts/vrrp/vrrp.py | 4 +- .../network/vyos/rm_templates/vrrp.py | 163 +++++++++++++++++- 2 files changed, 164 insertions(+), 3 deletions(-) diff --git a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py index 82b076f05..db0b9da84 100644 --- a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py @@ -92,14 +92,14 @@ def populate_facts(self, connection, ansible_facts, data=None): sync_groups = [] vsvrs = [] resources = self.get_config_set(data, connection) - + self._module.fail_json(msg=resources) for resource in resources: vrrp_parser = VrrpTemplate( lines=resource.split("\n"), module=self._module, ) objs = vrrp_parser.parse() - # self._module.fail_json(msg=str(resource.split("\n")) + "******" + str(objs)) + self._module.fail_json(msg=str(resource.split("\n")) + "******" + str(objs)) if objs: if "disable" in objs: vrrp_facts.update(objs) diff --git a/plugins/module_utils/network/vyos/rm_templates/vrrp.py b/plugins/module_utils/network/vyos/rm_templates/vrrp.py index 01e77e974..aac66e958 100644 --- a/plugins/module_utils/network/vyos/rm_templates/vrrp.py +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -453,6 +453,167 @@ def __init__(self, lines=None, module=None): }, }, }, - + { + "name": "vg_gp_version", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sversion + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters version {{version}}", + "compval": "global_parameters.version", + "result": { + "global_parameters": { + "version": "{{ version }}", + }, + }, + }, + { + "name": "gp_startup_delay", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sstartup-delay + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters startup-delay {{startup_delay}}", + "compval": "global_parameters.startup_delay", + "result": { + "global_parameters": { + "startup_delay": "{{ startup_delay }}", + }, + }, + }, + { + "name": "gp_garp_interval", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sgarp + \sinterval + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters garp interval {{interval}}", + "compval": "global_parameters.garp.interval", + "result": { + "global_parameters": { + "garp": { + "interval": "{{ interval }}", + }, + }, + }, + }, + { + "name": "gp_garp_master_delay", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sgarp + \smaster-delay + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters garp master-delay {{master_delay}}", + "compval": "global_parameters.garp.master_delay", + "result": { + "global_parameters": { + "garp": { + "master_delay": "{{ master_delay }}", + }, + }, + }, + }, + { + "name": "gp_garp_master_refresh", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sgarp + \smaster-refresh + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters garp master-refresh {{master_refresh}}", + "compval": "global_parameters.garp.master_refresh", + "result": { + "global_parameters": { + "garp": { + "master_refresh": "{{ master_refresh }}", + }, + }, + }, + }, + { + "name": "gp_garp_master_refresh_repeat", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sgarp + \smaster-refresh-repeat + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters garp master-refresh_repeat {{master_refresh_repeat}}", + "compval": "global_parameters.garp.master_refersh_repeat", + "result": { + "global_parameters": { + "garp": { + "master_refresh_repeat": "{{ master_refresh_repeat }}", + }, + }, + }, + }, + { + "name": "gp_garp_master_repeat", + "getval": re.compile( + r""" + ^set + \shigh-availability + \svrrp + \sglobal-parameters + \sgarp + \smaster-refresh-repeat + \s(?P\S+) + $""", + re.VERBOSE, + ), + "setval": "high-availability vrrp global-parameters garp master-refresh-repeat {{master_refresh_repeat}}", + "compval": "global_parameters.garp.master_refersh_repeat", + "result": { + "global_parameters": { + "garp": { + "master_refresh_repeat": "{{ master_refresh_repeat }}", + }, + }, + }, + }, ] # fmt: on From 876babe65535fc2247f1c9280906d442e85b5af0 Mon Sep 17 00:00:00 2001 From: omnom62 Date: Sun, 26 Oct 2025 05:12:10 -0500 Subject: [PATCH 04/32] virtual servers rm_templates --- .../network/vyos/rm_templates/vrrp.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/plugins/module_utils/network/vyos/rm_templates/vrrp.py b/plugins/module_utils/network/vyos/rm_templates/vrrp.py index aac66e958..00ec03e3e 100644 --- a/plugins/module_utils/network/vyos/rm_templates/vrrp.py +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -33,6 +33,21 @@ def __init__(self, lines=None, module=None): module=module, ) + def _tmplt_vsrvs(config_data): + config_data = config_data["virtual-server"] + command = [] + # cmd = "service snmp v3 group {group}".format(**config_data) + # if "mode" in config_data: + # mode_cmd = cmd + " mode {mode}".format(**config_data) + # command.append(mode_cmd) + # if "seclevel" in config_data: + # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) + # command.append(sec_cmd) + # if "view" in config_data: + # view_cmd = cmd + " view {view}".format(**config_data) + # command.append(view_cmd) + return command + # fmt: off PARSERS = [ { @@ -615,5 +630,41 @@ def __init__(self, lines=None, module=None): }, }, }, + { + "name": "virtual_servers", + "getval": re.compile( + r""" + ^set + \shigh-availability\svirtual-server + \s+(?P\S+) + \s*(?P
address\s\S+)* + \s*(?Palgorithm\s\S+)* + \s*(?Pdelay-loop\s\S+)* + \s*(?Pforward-method\s\S+)* + \s*(?Pfwmark\s\S+)* + \s*(?Ppersistence-timeout\s\S+)* + \s*(?Pport\s\S+)* + \s*(?Pprotocol\s\S+)* + $""", + re.VERBOSE, + ), + "setval": _tmplt_vsrvs, + # "compval": "global_parameters.garp.master_refersh_repeat", + "result": { + "virtual_servers": { + "{{ alias }}": { + "alias": "{{ alias }}", + "address": "{{ address.split(" ")[1] if address is defined else None }}", + "algorithm": "{{ alg.split(" ")[1] if alo is defined else None }}", + "delay_loop": "{{ delay_loop.split(" ")[1] if delay_loop is defined else None }}", + "forward_method": "{{ fwmet.split(" ")[1] if fwmet is defined else None }}", + "fwmark": "{{ fwmark.split(" ")[1] if fwmark is defined else None }}", + "persistence_timeout": "{{ ptime.split(" ")[1] if ptime is defined else None }}", + "port": "{{ port.split(" ")[1] if port is defined else None }}", + "protocol": "{{ proto.split(" ")[1] if proto is defined else None }}", + }, + }, + }, + }, ] # fmt: on From 60f44fc19b8ef653dcea7f4fc1160e5d222f6c84 Mon Sep 17 00:00:00 2001 From: omnom62 Date: Sun, 26 Oct 2025 05:22:37 -0500 Subject: [PATCH 05/32] update --- docs/vyos.vyos.vyos_vrrp_module.rst | 1240 +++++++++++++++++++++++++++ 1 file changed, 1240 insertions(+) create mode 100644 docs/vyos.vyos.vyos_vrrp_module.rst diff --git a/docs/vyos.vyos.vyos_vrrp_module.rst b/docs/vyos.vyos.vyos_vrrp_module.rst new file mode 100644 index 000000000..a74b0802f --- /dev/null +++ b/docs/vyos.vyos.vyos_vrrp_module.rst @@ -0,0 +1,1240 @@ +.. _vyos.vyos.vyos_vrrp_module: + + +******************* +vyos.vyos.vyos_vrrp +******************* + +**High Availability (VRRP) resource module** + + +Version added: 1.0.0 + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- This module manages VRRP configuration of interfaces on devices running VYOS. +- The provided examples of commands are valid for VyOS 1.4+ + + + + +Parameters +---------- + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterChoices/DefaultsComments
+
+ config + +
+ dictionary +
+
+ +
A dict of VRRP configuration.
+
+
+ disable + +
+ boolean +
+
+
    Choices: +
  • no ←
  • +
  • yes
  • +
+
+
Disable instance
+
+
+ running_config + +
+ string +
+
+ +
This option is used only with state parsed.
+
The value of this option should be the output received from the EOS device by executing the command show running-config | section bgp.
+
The state parsed reads the configuration from running_config option and transforms it into Ansible structured data as per the resource module's argspec and the value is then returned in the parsed key within the result.
+
+
+ state + +
+ string +
+
+
    Choices: +
  • deleted
  • +
  • merged ←
  • +
  • purged
  • +
  • replaced
  • +
  • gathered
  • +
  • rendered
  • +
  • parsed
  • +
+
+
The state the configuration should be left in.
+
State purged removes all the BGP configurations from the target device. Use caution with this state.('delete protocols bgp <x>')
+
State deleted only removes BGP attributes that this modules manages and does not negate the BGP process completely. Thereby, preserving address-family related configurations under BGP context.
+
Running states deleted and replaced will result in an error if there are address-family configuration lines present under neighbor context that is is to be removed. Please use the vyos.vyos.vyos_bgp_address_family module for prior cleanup.
+
Refer to examples for more details.
+
+
+ + + + +Examples +-------- + +.. code-block:: yaml + + # Using merged + # Before state + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # vyos@vyos:~$ + + - name: Merge provided configuration with device configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + aggregate_address: + - prefix: "203.0.113.0/24" + as_set: true + - prefix: "192.0.2.0/24" + summary_only: true + network: + - address: "192.1.13.0/24" + backdoor: true + redistribute: + - protocol: "kernel" + metric: 45 + - protocol: "connected" + route_map: "map01" + maximum_paths: + - path: "ebgp" + count: 20 + - path: "ibgp" + count: 55 + timers: + keepalive: 35 + bgp_params: + bestpath: + as_path: "confed" + compare_routerid: true + default: + no_ipv4_unicast: true + router_id: "192.1.2.9" + confederation: + - peers: 20 + - peers: 55 + - identifier: 66 + neighbor: + - address: "192.0.2.25" + disable_connected_check: true + timers: + holdtime: 30 + keepalive: 10 + - address: "203.0.113.5" + attribute_unchanged: + as_path: true + med: true + ebgp_multihop: 2 + remote_as: 101 + update_source: "192.0.2.25" + - address: "5001::64" + maximum_prefix: 34 + distribute_list: + - acl: 20 + action: "export" + - acl: 40 + action: "import" + state: merged + + # After State + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' + # set protocols bgp aggregate-address 203.0.113.0/24 'as-set' + # set protocols bgp maximum-paths ebgp '20' + # set protocols bgp maximum-paths ibgp '55' + # set protocols bgp neighbor 192.0.2.25 'disable-connected-check' + # set protocols bgp neighbor 192.0.2.25 timers holdtime '30' + # set protocols bgp neighbor 192.0.2.25 timers keepalive '10' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' + # set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' + # set protocols bgp neighbor 203.0.113.5 remote-as '101' + # set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' + # set protocols bgp neighbor 5001::64 distribute-list export '20' + # set protocols bgp neighbor 5001::64 distribute-list import '40' + # set protocols bgp neighbor 5001::64 maximum-prefix '34' + # set protocols bgp network 192.1.13.0/24 'backdoor' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp parameters bestpath 'compare-routerid' + # set protocols bgp parameters confederation identifier '66' + # set protocols bgp parameters confederation peers '20' + # set protocols bgp parameters confederation peers '55' + # set protocols bgp parameters default 'no-ipv4-unicast' + # set protocols bgp parameters router-id '192.1.2.9' + # set protocols bgp redistribute connected route-map 'map01' + # set protocols bgp redistribute kernel metric '45' + # set protocols bgp timers keepalive '35' + # vyos@vyos:~$ + # + # # Module Execution: + # + # "after": { + # "aggregate_address": [ + # { + # "prefix": "192.0.2.0/24", + # "summary_only": true + # }, + # { + # "prefix": "203.0.113.0/24", + # "as_set": true + # } + # ], + # "as_number": 65536, + # "bgp_params": { + # "bestpath": { + # "as_path": "confed", + # "compare_routerid": true + # }, + # "confederation": [ + # { + # "identifier": 66 + # }, + # { + # "peers": 20 + # }, + # { + # "peers": 55 + # } + # ], + # "default": { + # "no_ipv4_unicast": true + # }, + # "router_id": "192.1.2.9" + # }, + # "maximum_paths": [ + # { + # "count": 20, + # "path": "ebgp" + # }, + # { + # "count": 55, + # "path": "ibgp" + # } + # ], + # "neighbor": [ + # { + # "address": "192.0.2.25", + # "disable_connected_check": true, + # "timers": { + # "holdtime": 30, + # "keepalive": 10 + # } + # }, + # { + # "address": "203.0.113.5", + # "attribute_unchanged": { + # "as_path": true, + # "med": true, + # "next_hop": true + # }, + # "ebgp_multihop": 2, + # "remote_as": 101, + # "update_source": "192.0.2.25" + # }, + # { + # "address": "5001::64", + # "distribute_list": [ + # { + # "acl": 20, + # "action": "export" + # }, + # { + # "acl": 40, + # "action": "import" + # } + # ], + # "maximum_prefix": 34 + # } + # ], + # "network": [ + # { + # "address": "192.1.13.0/24", + # "backdoor": true + # } + # ], + # "redistribute": [ + # { + # "protocol": "connected", + # "route_map": "map01" + # }, + # { + # "metric": 45, + # "protocol": "kernel" + # } + # ], + # "timers": { + # "keepalive": 35 + # } + # }, + # "before": {}, + # "changed": true, + # "commands": [ + # "set protocols bgp neighbor 192.0.2.25 disable-connected-check", + # "set protocols bgp neighbor 192.0.2.25 timers holdtime 30", + # "set protocols bgp neighbor 192.0.2.25 timers keepalive 10", + # "set protocols bgp neighbor 203.0.113.5 attribute-unchanged as-path", + # "set protocols bgp neighbor 203.0.113.5 attribute-unchanged med", + # "set protocols bgp neighbor 203.0.113.5 attribute-unchanged next-hop", + # "set protocols bgp neighbor 203.0.113.5 ebgp-multihop 2", + # "set protocols bgp neighbor 203.0.113.5 remote-as 101", + # "set protocols bgp neighbor 203.0.113.5 update-source 192.0.2.25", + # "set protocols bgp neighbor 5001::64 maximum-prefix 34", + # "set protocols bgp neighbor 5001::64 distribute-list export 20", + # "set protocols bgp neighbor 5001::64 distribute-list import 40", + # "set protocols bgp redistribute kernel metric 45", + # "set protocols bgp redistribute connected route-map map01", + # "set protocols bgp network 192.1.13.0/24 backdoor", + # "set protocols bgp aggregate-address 203.0.113.0/24 as-set", + # "set protocols bgp aggregate-address 192.0.2.0/24 summary-only", + # "set protocols bgp parameters bestpath as-path confed", + # "set protocols bgp parameters bestpath compare-routerid", + # "set protocols bgp parameters default no-ipv4-unicast", + # "set protocols bgp parameters router-id 192.1.2.9", + # "set protocols bgp parameters confederation peers 20", + # "set protocols bgp parameters confederation peers 55", + # "set protocols bgp parameters confederation identifier 66", + # "set protocols bgp maximum-paths ebgp 20", + # "set protocols bgp maximum-paths ibgp 55", + # "set protocols bgp timers keepalive 35" + # ], + + # Using replaced: + # -------------- + + # Before state: + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' + # set protocols bgp aggregate-address 203.0.113.0/24 'as-set' + # set protocols bgp maximum-paths ebgp '20' + # set protocols bgp maximum-paths ibgp '55' + # set protocols bgp neighbor 192.0.2.25 'disable-connected-check' + # set protocols bgp neighbor 192.0.2.25 timers holdtime '30' + # set protocols bgp neighbor 192.0.2.25 timers keepalive '10' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' + # set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' + # set protocols bgp neighbor 203.0.113.5 remote-as '101' + # set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' + # set protocols bgp neighbor 5001::64 distribute-list export '20' + # set protocols bgp neighbor 5001::64 distribute-list import '40' + # set protocols bgp neighbor 5001::64 maximum-prefix '34' + # set protocols bgp network 192.1.13.0/24 'backdoor' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp parameters bestpath 'compare-routerid' + # set protocols bgp parameters confederation identifier '66' + # set protocols bgp parameters confederation peers '20' + # set protocols bgp parameters confederation peers '55' + # set protocols bgp parameters default 'no-ipv4-unicast' + # set protocols bgp parameters router-id '192.1.2.9' + # set protocols bgp redistribute connected route-map 'map01' + # set protocols bgp redistribute kernel metric '45' + # set protocols bgp timers keepalive '35' + # vyos@vyos:~$ + + - name: Replace + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + network: + - address: "203.0.113.0/24" + route_map: map01 + redistribute: + - protocol: "static" + route_map: "map01" + neighbor: + - address: "192.0.2.40" + advertisement_interval: 72 + capability: + orf: "receive" + bgp_params: + bestpath: + as_path: "confed" + state: replaced + # After state: + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' + # set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' + # set protocols bgp network 203.0.113.0/24 route-map 'map01' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp redistribute static route-map 'map01' + # vyos@vyos:~$ + # + # + # Module Execution: + # + # "after": { + # "as_number": 65536, + # "bgp_params": { + # "bestpath": { + # "as_path": "confed" + # } + # }, + # "neighbor": [ + # { + # "address": "192.0.2.40", + # "advertisement_interval": 72, + # "capability": { + # "orf": "receive" + # } + # } + # ], + # "network": [ + # { + # "address": "203.0.113.0/24", + # "route_map": "map01" + # } + # ], + # "redistribute": [ + # { + # "protocol": "static", + # "route_map": "map01" + # } + # ] + # }, + # "before": { + # "aggregate_address": [ + # { + # "prefix": "192.0.2.0/24", + # "summary_only": true + # }, + # { + # "prefix": "203.0.113.0/24", + # "as_set": true + # } + # ], + # "as_number": 65536, + # "bgp_params": { + # "bestpath": { + # "as_path": "confed", + # "compare_routerid": true + # }, + # "confederation": [ + # { + # "identifier": 66 + # }, + # { + # "peers": 20 + # }, + # { + # "peers": 55 + # } + # ], + # "default": { + # "no_ipv4_unicast": true + # }, + # "router_id": "192.1.2.9" + # }, + # "maximum_paths": [ + # { + # "count": 20, + # "path": "ebgp" + # }, + # { + # "count": 55, + # "path": "ibgp" + # } + # ], + # "neighbor": [ + # { + # "address": "192.0.2.25", + # "disable_connected_check": true, + # "timers": { + # "holdtime": 30, + # "keepalive": 10 + # } + # }, + # { + # "address": "203.0.113.5", + # "attribute_unchanged": { + # "as_path": true, + # "med": true, + # "next_hop": true + # }, + # "ebgp_multihop": 2, + # "remote_as": 101, + # "update_source": "192.0.2.25" + # }, + # { + # "address": "5001::64", + # "distribute_list": [ + # { + # "acl": 20, + # "action": "export" + # }, + # { + # "acl": 40, + # "action": "import" + # } + # ], + # "maximum_prefix": 34 + # } + # ], + # "network": [ + # { + # "address": "192.1.13.0/24", + # "backdoor": true + # } + # ], + # "redistribute": [ + # { + # "protocol": "connected", + # "route_map": "map01" + # }, + # { + # "metric": 45, + # "protocol": "kernel" + # } + # ], + # "timers": { + # "keepalive": 35 + # } + # }, + # "changed": true, + # "commands": [ + # "delete protocols bgp timers", + # "delete protocols bgp maximum-paths ", + # "delete protocols bgp maximum-paths ", + # "delete protocols bgp parameters router-id 192.1.2.9", + # "delete protocols bgp parameters default", + # "delete protocols bgp parameters confederation", + # "delete protocols bgp parameters bestpath compare-routerid", + # "delete protocols bgp aggregate-address", + # "delete protocols bgp network 192.1.13.0/24", + # "delete protocols bgp redistribute kernel", + # "delete protocols bgp redistribute kernel", + # "delete protocols bgp redistribute connected", + # "delete protocols bgp redistribute connected", + # "delete protocols bgp neighbor 5001::64", + # "delete protocols bgp neighbor 203.0.113.5", + # "delete protocols bgp neighbor 192.0.2.25", + # "set protocols bgp neighbor 192.0.2.40 advertisement-interval 72", + # "set protocols bgp neighbor 192.0.2.40 capability orf prefix-list receive", + # "set protocols bgp redistribute static route-map map01", + # "set protocols bgp network 203.0.113.0/24 route-map map01" + # ], + + # Using deleted: + # ------------- + + # Before state: + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' + # set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' + # set protocols bgp network 203.0.113.0/24 route-map 'map01' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp redistribute static route-map 'map01' + # vyos@vyos:~$ + + - name: Delete configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + state: deleted + + # After state: + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp '65536' + # vyos@vyos:~$ + # + # + # Module Execution: + # + # "after": { + # "as_number": 65536 + # }, + # "before": { + # "as_number": 65536, + # "bgp_params": { + # "bestpath": { + # "as_path": "confed" + # } + # }, + # "neighbor": [ + # { + # "address": "192.0.2.40", + # "advertisement_interval": 72, + # "capability": { + # "orf": "receive" + # } + # } + # ], + # "network": [ + # { + # "address": "203.0.113.0/24", + # "route_map": "map01" + # } + # ], + # "redistribute": [ + # { + # "protocol": "static", + # "route_map": "map01" + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "delete protocols bgp neighbor 192.0.2.40", + # "delete protocols bgp redistribute", + # "delete protocols bgp network", + # "delete protocols bgp parameters" + # ], + + # Using purged: + + # Before state: + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' + # set protocols bgp aggregate-address 203.0.113.0/24 'as-set' + # set protocols bgp maximum-paths ebgp '20' + # set protocols bgp maximum-paths ibgp '55' + # set protocols bgp neighbor 192.0.2.25 'disable-connected-check' + # set protocols bgp neighbor 192.0.2.25 timers holdtime '30' + # set protocols bgp neighbor 192.0.2.25 timers keepalive '10' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' + # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' + # set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' + # set protocols bgp neighbor 203.0.113.5 remote-as '101' + # set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' + # set protocols bgp neighbor 5001::64 distribute-list export '20' + # set protocols bgp neighbor 5001::64 distribute-list import '40' + # set protocols bgp neighbor 5001::64 maximum-prefix '34' + # set protocols bgp network 192.1.13.0/24 'backdoor' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp parameters bestpath 'compare-routerid' + # set protocols bgp parameters confederation identifier '66' + # set protocols bgp parameters confederation peers '20' + # set protocols bgp parameters confederation peers '55' + # set protocols bgp parameters default 'no-ipv4-unicast' + # set protocols bgp parameters router-id '192.1.2.9' + # set protocols bgp redistribute connected route-map 'map01' + # set protocols bgp redistribute kernel metric '45' + # set protocols bgp timers keepalive '35' + # vyos@vyos:~$ + + + - name: Purge configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + state: purged + + # After state: + + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # vyos@vyos:~$ + # + # Module Execution: + # + # "after": {}, + # "before": { + # "aggregate_address": [ + # { + # "prefix": "192.0.2.0/24", + # "summary_only": true + # }, + # { + # "prefix": "203.0.113.0/24", + # "as_set": true + # } + # ], + # "as_number": 65536, + # "bgp_params": { + # "bestpath": { + # "as_path": "confed", + # "compare_routerid": true + # }, + # "confederation": [ + # { + # "identifier": 66 + # }, + # { + # "peers": 20 + # }, + # { + # "peers": 55 + # } + # ], + # "default": { + # "no_ipv4_unicast": true + # }, + # "router_id": "192.1.2.9" + # }, + # "maximum_paths": [ + # { + # "count": 20, + # "path": "ebgp" + # }, + # { + # "count": 55, + # "path": "ibgp" + # } + # ], + # "neighbor": [ + # { + # "address": "192.0.2.25", + # "disable_connected_check": true, + # "timers": { + # "holdtime": 30, + # "keepalive": 10 + # } + # }, + # { + # "address": "203.0.113.5", + # "attribute_unchanged": { + # "as_path": true, + # "med": true, + # "next_hop": true + # }, + # "ebgp_multihop": 2, + # "remote_as": 101, + # "update_source": "192.0.2.25" + # }, + # { + # "address": "5001::64", + # "distribute_list": [ + # { + # "acl": 20, + # "action": "export" + # }, + # { + # "acl": 40, + # "action": "import" + # } + # ], + # "maximum_prefix": 34 + # } + # ], + # "network": [ + # { + # "address": "192.1.13.0/24", + # "backdoor": true + # } + # ], + # "redistribute": [ + # { + # "protocol": "connected", + # "route_map": "map01" + # }, + # { + # "metric": 45, + # "protocol": "kernel" + # } + # ], + # "timers": { + # "keepalive": 35 + # } + # }, + # "changed": true, + # "commands": [ + # "delete protocols bgp 65536" + # ], + + + # Deleted in presence of address family under neighbors: + + # Before state: + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' + # set protocols bgp neighbor 192.0.2.43 capability 'dynamic' + # set protocols bgp neighbor 192.0.2.43 'disable-connected-check' + # set protocols bgp neighbor 192.0.2.43 timers holdtime '30' + # set protocols bgp neighbor 192.0.2.43 timers keepalive '10' + # set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' + # set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' + # set protocols bgp network 203.0.113.0/24 route-map 'map01' + # set protocols bgp parameters 'always-compare-med' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp parameters bestpath 'compare-routerid' + # set protocols bgp parameters dampening half-life '33' + # set protocols bgp parameters dampening max-suppress-time '20' + # set protocols bgp parameters dampening re-use '60' + # set protocols bgp parameters dampening start-suppress-time '5' + # set protocols bgp parameters default 'no-ipv4-unicast' + # set protocols bgp parameters distance global external '66' + # set protocols bgp parameters distance global internal '20' + # set protocols bgp parameters distance global local '10' + # set protocols bgp redistribute static route-map 'map01' + # vyos@vyos:~$ ^C + # vyos@vyos:~$ + + - name: Delete configuration + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + state: deleted + + # Module Execution: + # + # "changed": false, + # "invocation": { + # "module_args": { + # "config": { + # "aggregate_address": null, + # "as_number": 65536, + # "bgp_params": null, + # "maximum_paths": null, + # "neighbor": null, + # "network": null, + # "redistribute": null, + # "timers": null + # }, + # "running_config": null, + # "state": "deleted" + # } + # }, + # "msg": "Use the _bgp_address_family module to delete the address_family under neighbor 203.0.113.0, before replacing/deleting the neighbor." + # } + + # using gathered: + # -------------- + + # Before state: + # vyos@vyos:~$ show configuration commands | match "set protocols bgp" + # set protocols bgp system-as 65536 + # set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' + # set protocols bgp neighbor 192.0.2.43 capability 'dynamic' + # set protocols bgp neighbor 192.0.2.43 'disable-connected-check' + # set protocols bgp neighbor 192.0.2.43 timers holdtime '30' + # set protocols bgp neighbor 192.0.2.43 timers keepalive '10' + # set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' + # set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' + # set protocols bgp network 203.0.113.0/24 route-map 'map01' + # set protocols bgp parameters 'always-compare-med' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp parameters bestpath 'compare-routerid' + # set protocols bgp parameters dampening half-life '33' + # set protocols bgp parameters dampening max-suppress-time '20' + # set protocols bgp parameters dampening re-use '60' + # set protocols bgp parameters dampening start-suppress-time '5' + # set protocols bgp parameters default 'no-ipv4-unicast' + # set protocols bgp parameters distance global external '66' + # set protocols bgp parameters distance global internal '20' + # set protocols bgp parameters distance global local '10' + # set protocols bgp redistribute static route-map 'map01' + # vyos@vyos:~$ ^C + + - name: gather configs + vyos.vyos.vyos_vrrp: + state: gathered + + # Module Execution: + # "gathered": { + # "as_number": 65536, + # "bgp_params": { + # "always_compare_med": true, + # "bestpath": { + # "as_path": "confed", + # "compare_routerid": true + # }, + # "default": { + # "no_ipv4_unicast": true + # }, + # "distance": [ + # { + # "type": "external", + # "value": 66 + # }, + # { + # "type": "internal", + # "value": 20 + # }, + # { + # "type": "local", + # "value": 10 + # } + # ] + # }, + # "neighbor": [ + # { + # "address": "192.0.2.43", + # "advertisement_interval": 72, + # "capability": { + # "dynamic": true + # }, + # "disable_connected_check": true, + # "timers": { + # "holdtime": 30, + # "keepalive": 10 + # } + # }, + # { + # "address": "203.0.113.0", + # "capability": { + # "orf": "receive" + # } + # } + # ], + # "network": [ + # { + # "address": "203.0.113.0/24", + # "route_map": "map01" + # } + # ], + # "redistribute": [ + # { + # "protocol": "static", + # "route_map": "map01" + # } + # ] + # }, + # + + # Using parsed: + # ------------ + + # parsed.cfg + + # set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' + # set protocols bgp neighbor 192.0.2.43 capability 'dynamic' + # set protocols bgp neighbor 192.0.2.43 'disable-connected-check' + # set protocols bgp neighbor 192.0.2.43 timers holdtime '30' + # set protocols bgp neighbor 192.0.2.43 timers keepalive '10' + # set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' + # set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' + # set protocols bgp network 203.0.113.0/24 route-map 'map01' + # set protocols bgp parameters 'always-compare-med' + # set protocols bgp parameters bestpath as-path 'confed' + # set protocols bgp parameters bestpath 'compare-routerid' + # set protocols bgp parameters dampening half-life '33' + # set protocols bgp parameters dampening max-suppress-time '20' + # set protocols bgp parameters dampening re-use '60' + # set protocols bgp parameters dampening start-suppress-time '5' + # set protocols bgp parameters default 'no-ipv4-unicast' + # set protocols bgp parameters distance global external '66' + # set protocols bgp parameters distance global internal '20' + # set protocols bgp parameters distance global local '10' + # set protocols bgp redistribute static route-map 'map01' + + - name: parse configs + vyos.vyos.vyos_vrrp: + running_config: "{{ lookup('file', './parsed.cfg') }}" + state: parsed + tags: + - parsed + + # Module execution: + # "parsed": { + # "as_number": 65536, + # "bgp_params": { + # "always_compare_med": true, + # "bestpath": { + # "as_path": "confed", + # "compare_routerid": true + # }, + # "default": { + # "no_ipv4_unicast": true + # }, + # "distance": [ + # { + # "type": "external", + # "value": 66 + # }, + # { + # "type": "internal", + # "value": 20 + # }, + # { + # "type": "local", + # "value": 10 + # } + # ] + # }, + # "neighbor": [ + # { + # "address": "192.0.2.43", + # "advertisement_interval": 72, + # "capability": { + # "dynamic": true + # }, + # "disable_connected_check": true, + # "timers": { + # "holdtime": 30, + # "keepalive": 10 + # } + # }, + # { + # "address": "203.0.113.0", + # "capability": { + # "orf": "receive" + # } + # } + # ], + # "network": [ + # { + # "address": "203.0.113.0/24", + # "route_map": "map01" + # } + # ], + # "redistribute": [ + # { + # "protocol": "static", + # "route_map": "map01" + # } + # ] + # } + # + + # Using rendered: + # -------------- + + - name: Render + vyos.vyos.vyos_vrrp: + config: + as_number: "65536" + network: + - address: "203.0.113.0/24" + route_map: map01 + redistribute: + - protocol: "static" + route_map: "map01" + bgp_params: + always_compare_med: true + dampening: + start_suppress_time: 5 + max_suppress_time: 20 + half_life: 33 + re_use: 60 + distance: + - type: "internal" + value: 20 + - type: "local" + value: 10 + - type: "external" + value: 66 + bestpath: + as_path: "confed" + compare_routerid: true + default: + no_ipv4_unicast: true + neighbor: + - address: "192.0.2.43" + disable_connected_check: true + advertisement_interval: 72 + capability: + dynamic: true + timers: + holdtime: 30 + keepalive: 10 + - address: "203.0.113.0" + capability: + orf: "receive" + state: rendered + + # Module Execution: + # "rendered": [ + # "set protocols bgp neighbor 192.0.2.43 disable-connected-check", + # "set protocols bgp neighbor 192.0.2.43 advertisement-interval 72", + # "set protocols bgp neighbor 192.0.2.43 capability dynamic", + # "set protocols bgp neighbor 192.0.2.43 timers holdtime 30", + # "set protocols bgp neighbor 192.0.2.43 timers keepalive 10", + # "set protocols bgp neighbor 203.0.113.0 capability orf prefix-list receive", + # "set protocols bgp redistribute static route-map map01", + # "set protocols bgp network 203.0.113.0/24 route-map map01", + # "set protocols bgp parameters always-compare-med", + # "set protocols bgp parameters dampening half-life 33", + # "set protocols bgp parameters dampening max-suppress-time 20", + # "set protocols bgp parameters dampening re-use 60", + # "set protocols bgp parameters dampening start-suppress-time 5", + # "set protocols bgp parameters distance global internal 20", + # "set protocols bgp parameters distance global local 10", + # "set protocols bgp parameters distance global external 66", + # "set protocols bgp parameters bestpath as-path confed", + # "set protocols bgp parameters bestpath compare-routerid", + # "set protocols bgp parameters default no-ipv4-unicast" + # ] + + + +Return Values +------------- +Common return values are documented `here `_, the following are the fields unique to this module: + +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyReturnedDescription
+
+ after + +
+ dictionary +
+
when changed +
The resulting configuration after module execution.
+
+
Sample:
+
This output will always be in the same format as the module argspec.
+
+
+ before + +
+ dictionary +
+
when state is merged, replaced, overridden, deleted or purged +
The configuration prior to the module execution.
+
+
Sample:
+
This output will always be in the same format as the module argspec.
+
+
+ commands + +
+ list +
+
when state is merged, replaced, overridden, deleted or purged +
The set of commands pushed to the remote device.
+
+
Sample:
+
['set protocols bgp redistribute static route-map map01', 'set protocols bgp network 203.0.113.0/24 route-map map01', 'set protocols bgp parameters always-compare-med']
+
+
+ gathered + +
+ list +
+
when state is gathered +
Facts about the network resource gathered from the remote device as structured data.
+
+
Sample:
+
This output will always be in the same format as the module argspec.
+
+
+ parsed + +
+ list +
+
when state is parsed +
The device native config provided in running_config option parsed into structured data as per module argspec.
+
+
Sample:
+
This output will always be in the same format as the module argspec.
+
+
+ rendered + +
+ list +
+
when state is rendered +
The provided configuration in the task rendered in device-native format (offline).
+
+
Sample:
+
['set protocols bgp redistribute static route-map map01', 'set protocols bgp network 203.0.113.0/24 route-map map01', 'set protocols bgp parameters always-compare-med']
+
+

+ + +Status +------ + + +Authors +~~~~~~~ + +- Evgeny Molotkov (@omnom62) From 42cfefcde9ec85cbb408fb9c65e85fd47c1786aa Mon Sep 17 00:00:00 2001 From: omnom62 Date: Tue, 28 Oct 2025 03:10:14 -0500 Subject: [PATCH 06/32] sync-group rm_tempalte --- .../network/vyos/facts/vrrp/vrrp.py | 7 +- .../network/vyos/rm_templates/vrrp.py | 163 ++++++++++++++++++ 2 files changed, 165 insertions(+), 5 deletions(-) diff --git a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py index db0b9da84..74a141b71 100644 --- a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py @@ -57,9 +57,7 @@ def get_config_set(self, data, connection): config_dict.get(vrrp_gp.group(1), "") + config_line + "\n" ) if vrrp_vsrv: - config_dict["virtual_server"] = ( - config_dict.get(vrrp_vsrv.group(1), "") + config_line + "\n" - ) + config_dict["virtual_server"] = config_dict.get(vrrp_vsrv, "") + config_line + "\n" if vrrp_sg: config_dict["sync_group"] = ( config_dict.get(vrrp_sg.group(1), "") + config_line + "\n" @@ -86,13 +84,12 @@ def populate_facts(self, connection, ansible_facts, data=None): if not data: data = self.get_device_data(connection) - vrrp_facts = {} groups = [] sync_groups = [] vsvrs = [] resources = self.get_config_set(data, connection) - self._module.fail_json(msg=resources) + self._module.fail_json(msg="test: " + str(resources)) for resource in resources: vrrp_parser = VrrpTemplate( lines=resource.split("\n"), diff --git a/plugins/module_utils/network/vyos/rm_templates/vrrp.py b/plugins/module_utils/network/vyos/rm_templates/vrrp.py index 00ec03e3e..f2f005701 100644 --- a/plugins/module_utils/network/vyos/rm_templates/vrrp.py +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -48,6 +48,51 @@ def _tmplt_vsrvs(config_data): # command.append(view_cmd) return command + def _tmplt_vsrvs_rsrv(config_data): + config_data = config_data["virtual-server"]["real_servers"] + command = [] + # cmd = "service snmp v3 group {group}".format(**config_data) + # if "mode" in config_data: + # mode_cmd = cmd + " mode {mode}".format(**config_data) + # command.append(mode_cmd) + # if "seclevel" in config_data: + # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) + # command.append(sec_cmd) + # if "view" in config_data: + # view_cmd = cmd + " view {view}".format(**config_data) + # command.append(view_cmd) + return command + + def _tmplt_sgroup_hc(config_data): + config_data = config_data["sync-group"]["health-check"] + command = [] + # cmd = "service snmp v3 group {group}".format(**config_data) + # if "mode" in config_data: + # mode_cmd = cmd + " mode {mode}".format(**config_data) + # command.append(mode_cmd) + # if "seclevel" in config_data: + # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) + # command.append(sec_cmd) + # if "view" in config_data: + # view_cmd = cmd + " view {view}".format(**config_data) + # command.append(view_cmd) + return command + + def _tmplt_sgroup_ts(config_data): + config_data = config_data["sync-group"]["transition-script"] + command = [] + # cmd = "service snmp v3 group {group}".format(**config_data) + # if "mode" in config_data: + # mode_cmd = cmd + " mode {mode}".format(**config_data) + # command.append(mode_cmd) + # if "seclevel" in config_data: + # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) + # command.append(sec_cmd) + # if "view" in config_data: + # view_cmd = cmd + " view {view}".format(**config_data) + # command.append(view_cmd) + return command + # fmt: off PARSERS = [ { @@ -666,5 +711,123 @@ def _tmplt_vsrvs(config_data): }, }, }, + { + "name": "virtual_servers.real_servers", + "getval": re.compile( + r""" + ^set\shigh-availability\svirtual-server + \s+(?P\S+) + \sreal-server + \s+(?P\S+) + (?:\s+port\s+(?P\S+))? + (?:\s+health-check\sscript\s+(?P\S+))? + (?:\s+connection-timeout\s+(?P\S+))? + $ + """, + re.VERBOSE, + ), + "setval": _tmplt_vsrvs_rsrv, + # "compval": "global_parameters.garp.master_refersh_repeat", + "result": { + "virtual_servers": { + "{{ alias }}": { + "alias": "{{ alias }}", + "real_servers": { + "{{ name }}": { + "name": "{{ name }}", + "port": "{{ portif port is defined else None }}", + "health_check_script": "{{ hcscript f hcscript is defined else None }}", + "connection_timeout": "{{ cont if cont is defined else None }}", + }, + }, + }, + }, + }, + }, + { + "name": "sync_group.member", + "getval": re.compile( + r""" + ^set\shigh-availability\svrrp\ssync-group + \s+(?P\S+) + \smember + \s+(?P\S+) + $ + """, + re.VERBOSE, + ), + "setval": "set high-availability vrrp sync-group {{sgname}} member {{member}}", + "compval": "sync_groups.member", + "result": { + "sync_groups": { + "{{ sgname }}": { + "name": "{{ sgname }}", + "member": "{{ member }}", + }, + }, + }, + }, + { + "name": "sync_group.health_check", + "getval": re.compile( + r""" + ^set\shigh-availability\svrrp\ssync-group + \s+(?P\S+) + \shealth-check + (?:\s+failure-count\s+(?P\S+)) + ?(?:\s+interval\s+(?P\S+)) + ?(?:\s+ping\s+(?P\S+)) + ?(?:\s+script\s+(?P