diff --git a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py index 5dadec03..a7b3291d 100644 --- a/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/facts/vrrp/vrrp.py @@ -1,117 +1,122 @@ # -*- 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_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[vrrp_vsrv.group(1)] = ( config_dict.get(vrrp_vsrv.group(1), "") + config_line + "\n" ) if vrrp_sg: config_dict[vrrp_sg.group(1)] = ( 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" ) return list(config_dict.values()) + def deep_merge(self, dest, src): + for key, value in src.items(): + if key in dest and isinstance(dest[key], dict) and isinstance(value, dict): + self.deep_merge(dest[key], value) + else: + dest[key] = value + return dest + 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 = {} + vrrp_facts = {"virtual_servers": {}, "sync_groups": {}} groups = [] - sync_groups = [] - vsvrs = [] resources = self.get_config_set(data, connection) - # self._module.fail_json(msg=resources) for resource in data.splitlines(): # resources: vrrp_parser = VrrpTemplate( lines=resource.split("\n"), module=self._module, ) objs = vrrp_parser.parse() - if "virtual_servers" in objs: - objs["virtual_servers"] = sorted( - list(objs["virtual_servers"].values()), - key=lambda k, sk="alias": k[sk], - ) - self._module.fail_json(msg=str(objs)) + for section in ("virtual_servers", "sync_groups"): + if section in objs: + for name, data in objs[section].items(): + existing = vrrp_facts[section].get(name, {}) + vrrp_facts[section][name] = self.deep_merge(existing, data) + self._module.fail_json(msg=str(vrrp_facts)) 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) + self._module.fail_json(msg="STOP") 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 index 3b373dd2..5e270f96 100644 --- a/plugins/module_utils/network/vyos/rm_templates/vrrp.py +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -1,628 +1,628 @@ # -*- 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, ) 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 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 def _tmplt_vrrp_gp(config_data): config_data = config_data["vrrp"]["global-parameters"] 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_vrrp_gp_garp(config_data): config_data = config_data["vrrp"]["global-parameters"]["garp"] 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_vrrp_group(config_data): config_data = config_data["vrrp"]["group"] 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_vrrp_group_track(config_data): config_data = config_data["vrrp"]["group"]["track"] 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_vrrp_group_hc(config_data): config_data = config_data["vrrp"]["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_vrrp_group_ts(config_data): config_data = config_data["vrrp"]["group"]["transcription-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 def _tmplt_vrrp_group_garp(config_data): config_data = config_data["vrrp"]["group"]["garp"] 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_vrrp_group_auth(config_data): config_data = config_data["vrrp"]["group"]["authentication"] 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 = [ { "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": "virtual_servers", "getval": re.compile( r""" ^set\shigh-availability\svirtual-server \s+(?P\S+) (?:\s+address\s+(?P
\S+))? (?:\s+algorithm\s+(?P\S+))? (?:\s+delay-loop\s+(?P\S+))? (?:\s+forward-method\s+(?P\S+))? (?:\s+fwmark\s+(?P\S+))? (?:\s+persistence-timeout\s+(?P\S+))? (?:\s+port\s+(?P\S+))? (?:\s+protocol\s+(?P\S+))? $ """, re.VERBOSE, ), "setval": _tmplt_vsrvs, "result": { "virtual_servers": { "{{ alias }}": { "alias": "{{ alias }}", "address": "{{ address if address is defined else None }}", "algorithm": "{{ algorithm if algorithm is defined else None }}", "delay_loop": "{{ delay_loop if delay_loop is defined else None }}", "forward_method": "{{ forward_method if forward_method is defined else None }}", "fwmark": "{{ fwmark if fwmark is defined else None }}", "persistence_timeout": "{{ persistence_timeout if persistence_timeout is defined else None }}", "port": "{{ port if port is defined else None }}", "protocol": "{{ protocol if protocol is defined else None }}", }, }, }, }, - # { - # "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