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
10from copy import deepcopy
11import re
12
13from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv3 import (
14    Ospfv3Template,
15)
16from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
17    utils,
18)
19from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv3.ospfv3 import (
20    Ospfv3Args,
21)
22from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
23    NetworkTemplate,
24)
25
26
27class Ospfv3Facts(object):
28    """ The iosxr snmp fact class
29    """
30
31    def __init__(self, module, subspec="config", options="options"):
32        self._module = module
33        self.argument_spec = Ospfv3Args.argument_spec
34
35        spec = deepcopy(self.argument_spec)
36        if subspec:
37            if options:
38                facts_argument_spec = spec[subspec][options]
39            else:
40                facts_argument_spec = spec[subspec]
41        else:
42            facts_argument_spec = spec
43
44        self.generated_spec = utils.generate_dict(facts_argument_spec)
45
46    def get_ospfv3_data(self, connection):
47        return connection.get("show running-config router ospfv3")
48
49    def populate_facts(self, connection, ansible_facts, data=None):
50        """ Populate the facts for interfaces
51        :param connection: the device connection
52        :param ansible_facts: Facts dictionary
53        :param data: previously collected conf
54        :rtype: dictionary
55        :returns: facts
56        """
57
58        if not data:
59            data = self.get_ospfv3_data(connection)
60        end_flag, end_mark, count, v_read = 0, 0, 0, False
61        areas, config_commands = [], []
62        area_str, process, curr_process = "", "", ""
63        data = data.splitlines()
64        for line in data:
65            if (
66                line.startswith("router ospfv3")
67                and curr_process != ""
68                and curr_process != line
69            ):
70                end_mark, count, end_flag, area_str = 0, 0, 0, ""
71            if (
72                end_mark == 0
73                and count == 0
74                and line.startswith("router ospfv3")
75            ):
76                curr_process = line
77                process = re.sub("\n", "", line)
78                count += 1
79                config_commands.append(process)
80            else:
81                if line.startswith(" area") or line.startswith(" vrf"):
82                    area_str = process + re.sub("\n", "", line)
83                    config_commands.append(area_str.replace("  ", " "))
84                    end_flag += 1
85                elif line.startswith("  virtual-link"):
86                    virtual_str = area_str + re.sub("\n", "", line)
87                    config_commands.append(virtual_str.replace("  ", " "))
88                    v_read = True
89                elif v_read:
90                    if "!" not in line:
91                        command = virtual_str.replace("  ", " ") + re.sub(
92                            "\n", "", line
93                        )
94                        config_commands.append(command.replace("   ", " "))
95                    else:
96                        v_read = False
97                elif end_flag > 0 and "!" not in line:
98                    command = area_str + re.sub("\n", "", line)
99                    config_commands.append(command.replace("  ", " "))
100                elif "!" in line:
101                    end_flag = 0
102                    end_mark += 1
103                    if end_mark == 3:
104                        end_mark, count = 0, 0
105                    area_str = ""
106                else:
107                    command = process + line
108                    command.replace("  ", " ")
109                    config_commands.append(re.sub("\n", "", command))
110                    areas.append(re.sub("\n", "", command))
111        data = config_commands
112        ipv4 = {"processes": []}
113        rmmod = NetworkTemplate(
114            lines=data, tmplt=Ospfv3Template(), module=self._module
115        )
116        current = rmmod.parse()
117
118        # convert some of the dicts to lists
119        for key, sortv in [("processes", "process_id")]:
120            if key in current and current[key]:
121                current[key] = current[key].values()
122                current[key] = sorted(
123                    current[key], key=lambda k, sk=sortv: k[sk]
124                )
125
126        for process in current.get("processes", []):
127            if "areas" in process:
128                process["areas"] = list(process["areas"].values())
129                process["areas"] = sorted(
130                    process["areas"], key=lambda k, sk="area_id": k[sk]
131                )
132                for area in process["areas"]:
133                    if "ranges" in area:
134                        area["ranges"] = sorted(
135                            area["ranges"], key=lambda k, s="ranges": k[s]
136                        )
137                    if "virtual_link" in area:
138                        area["virtual_link"] = list(
139                            area["virtual_link"].values()
140                        )
141                        area["virtual_link"] = sorted(
142                            area["virtual_link"], key=lambda k, sk="id": k[sk]
143                        )
144            ipv4["processes"].append(process)
145
146        ansible_facts["ansible_network_resources"].pop("ospfv3", None)
147        facts = {}
148        if current:
149            params = rmmod.validate_config(
150                self.argument_spec, {"config": ipv4}, redact=True
151            )
152            params = utils.remove_empties(params)
153
154            facts["ospfv3"] = params["config"]
155
156            ansible_facts["ansible_network_resources"].update(facts)
157        return ansible_facts
158