1# -*- coding: utf-8 -*- 2# Copyright 2020 Red Hat 3# GNU General Public License v3.0+ 4# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 6from __future__ import absolute_import, division, print_function 7 8__metaclass__ = type 9 10""" 11The iosxr ospf_interfaces fact class 12It is in this file the configuration is collected from the device 13for a given resource, parsed, and the facts tree is populated 14based on the configuration. 15""" 16 17from copy import deepcopy 18import re 19from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( 20 utils, 21) 22from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospf_interfaces import ( 23 Ospf_interfacesTemplate, 24) 25from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospf_interfaces.ospf_interfaces import ( 26 Ospf_interfacesArgs, 27) 28 29 30class Ospf_interfacesFacts(object): 31 """ The iosxr ospf_interfaces facts class 32 """ 33 34 def __init__(self, module, subspec="config", options="options"): 35 self._module = module 36 self.argument_spec = Ospf_interfacesArgs.argument_spec 37 spec = deepcopy(self.argument_spec) 38 if subspec: 39 if options: 40 facts_argument_spec = spec[subspec][options] 41 else: 42 facts_argument_spec = spec[subspec] 43 else: 44 facts_argument_spec = spec 45 46 self.generated_spec = utils.generate_dict(facts_argument_spec) 47 48 def get_ospf_interfaces(self, connection, flag): 49 cmd = "show running-config router " + flag 50 return connection.get(cmd) 51 52 def populate_facts(self, connection, ansible_facts, data=None): 53 """ Populate the facts for Ospf_interfaces network resource 54 55 :param connection: the device connection 56 :param ansible_facts: Facts dictionary 57 :param data: previously collected conf 58 59 :rtype: dictionary 60 :returns: facts 61 """ 62 facts = {} 63 objs = [] 64 if not data: 65 data = self.get_ospf_interfaces(connection, flag="ospf") 66 data += "\n" + self.get_ospf_interfaces(connection, flag="ospfv3") 67 end_flag, end_mark, count, v_read = 0, 0, 0, False 68 areas, config_commands = [], [] 69 area_str, process, curr_process = "", "", "" 70 data = data.splitlines() 71 72 for line in data: 73 if ( 74 line.startswith("router") 75 and curr_process != "" 76 and curr_process != line 77 ): 78 end_mark, count, end_flag, area_str = 0, 0, 0, "" 79 if end_mark == 0 and count == 0 and line.startswith("router ospf"): 80 curr_process = line 81 process = re.sub("\n", "", line) 82 count += 1 83 config_commands.append(process) 84 else: 85 if line.startswith(" area") or line.startswith(" vrf"): 86 area_str = process + re.sub("\n", "", line) 87 config_commands.append(area_str.replace(" ", " ")) 88 end_flag += 1 89 elif line.startswith(" interface"): 90 ospf_int = area_str + re.sub("\n", "", line) 91 # default output format has more spaces with default identation 92 # reset the spaces with replace 93 config_commands.append(ospf_int.replace(" ", " ")) 94 v_read = True 95 elif v_read: 96 if "!" not in line: 97 command = ospf_int.replace(" ", " ") + re.sub( 98 "\n", "", line 99 ) 100 config_commands.append(command.replace(" ", " ")) 101 else: 102 v_read = False 103 elif end_flag > 0 and "!" not in line: 104 command = area_str + re.sub("\n", "", line) 105 config_commands.append(command.replace(" ", " ")) 106 elif "!" in line: 107 end_flag = 0 108 end_mark += 1 109 if end_mark == 3: 110 end_mark, count = 0, 0 111 area_str = "" 112 else: 113 command = process + line 114 command.replace(" ", " ") 115 config_commands.append(re.sub("\n", "", command)) 116 areas.append(re.sub("\n", "", command)) 117 data = config_commands 118 119 ospf_interfaces_parser = Ospf_interfacesTemplate( 120 lines=data, module=self._module 121 ) 122 objs = list(ospf_interfaces_parser.parse().values()) 123 if objs: 124 for item in objs: 125 item["address_family"] = list(item["address_family"].values()) 126 for af in item["address_family"]: 127 if af.get("processes"): 128 af["processes"] = list(af["processes"].values()) 129 130 ansible_facts["ansible_network_resources"].pop("ospf_interfaces", None) 131 132 params = utils.remove_empties( 133 ospf_interfaces_parser.validate_config( 134 self.argument_spec, {"config": objs}, redact=True 135 ) 136 ) 137 138 facts["ospf_interfaces"] = params.get("config", []) 139 ansible_facts["ansible_network_resources"].update(facts) 140 141 return ansible_facts 142