1#
2# (c) 2019, Ansible by Red Hat, inc
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4#
5from __future__ import absolute_import, division, print_function
6
7__metaclass__ = type
8import re
9
10from ansible.module_utils.six import iteritems
11from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
12    to_list,
13)
14from ansible_collections.cisco.ios.plugins.module_utils.network.ios.providers.providers import (
15    CliProvider,
16)
17
18
19class Neighbors(CliProvider):
20    def render(self, config=None, nbr_list=None):
21        commands = list()
22        safe_list = list()
23        if not nbr_list:
24            nbr_list = self.get_value("config.neighbors")
25
26        for item in nbr_list:
27            neighbor_commands = list()
28            context = "neighbor %s" % item["neighbor"]
29            cmd = "%s remote-as %s" % (context, item["remote_as"])
30
31            if not config or cmd not in config:
32                neighbor_commands.append(cmd)
33
34            for key, value in iteritems(item):
35                if value is not None:
36                    meth = getattr(self, "_render_%s" % key, None)
37                    if meth:
38                        resp = meth(item, config)
39                        if resp:
40                            neighbor_commands.extend(to_list(resp))
41
42            commands.extend(neighbor_commands)
43            safe_list.append(context)
44
45        if self.params["operation"] == "replace":
46            if config and safe_list:
47                commands.extend(self._negate_config(config, safe_list))
48
49        return commands
50
51    def _negate_config(self, config, safe_list=None):
52        commands = list()
53        matches = re.findall(r"(neighbor \S+)", config, re.M)
54        for item in set(matches).difference(safe_list):
55            commands.append("no %s" % item)
56        return commands
57
58    def _render_local_as(self, item, config=None):
59        cmd = "neighbor %s local-as %s" % (item["neighbor"], item["local_as"])
60        if not config or cmd not in config:
61            return cmd
62
63    def _render_port(self, item, config=None):
64        cmd = "neighbor %s port %s" % (item["neighbor"], item["port"])
65        if not config or cmd not in config:
66            return cmd
67
68    def _render_description(self, item, config=None):
69        cmd = "neighbor %s description %s" % (
70            item["neighbor"],
71            item["description"],
72        )
73        if not config or cmd not in config:
74            return cmd
75
76    def _render_enabled(self, item, config=None):
77        cmd = "neighbor %s shutdown" % item["neighbor"]
78        if item["enabled"] is True:
79            if not config or cmd in config:
80                cmd = "no %s" % cmd
81                return cmd
82        elif not config or cmd not in config:
83            return cmd
84
85    def _render_update_source(self, item, config=None):
86        cmd = "neighbor %s update-source %s" % (
87            item["neighbor"],
88            item["update_source"],
89        )
90        if not config or cmd not in config:
91            return cmd
92
93    def _render_password(self, item, config=None):
94        cmd = "neighbor %s password %s" % (item["neighbor"], item["password"])
95        if not config or cmd not in config:
96            return cmd
97
98    def _render_ebgp_multihop(self, item, config=None):
99        cmd = "neighbor %s ebgp-multihop %s" % (
100            item["neighbor"],
101            item["ebgp_multihop"],
102        )
103        if not config or cmd not in config:
104            return cmd
105
106    def _render_peer_group(self, item, config=None):
107        cmd = "neighbor %s peer-group %s" % (
108            item["neighbor"],
109            item["peer_group"],
110        )
111        if not config or cmd not in config:
112            return cmd
113
114    def _render_timers(self, item, config):
115        """generate bgp timer related configuration
116        """
117        keepalive = item["timers"]["keepalive"]
118        holdtime = item["timers"]["holdtime"]
119        min_neighbor_holdtime = item["timers"]["min_neighbor_holdtime"]
120        neighbor = item["neighbor"]
121
122        if keepalive and holdtime:
123            cmd = "neighbor %s timers %s %s" % (neighbor, keepalive, holdtime)
124            if min_neighbor_holdtime:
125                cmd += " %s" % min_neighbor_holdtime
126            if not config or cmd not in config:
127                return cmd
128
129
130class AFNeighbors(CliProvider):
131    def render(self, config=None, nbr_list=None):
132        commands = list()
133        if not nbr_list:
134            return
135
136        for item in nbr_list:
137            neighbor_commands = list()
138            for key, value in iteritems(item):
139                if value is not None:
140                    meth = getattr(self, "_render_%s" % key, None)
141                    if meth:
142                        resp = meth(item, config)
143                        if resp:
144                            neighbor_commands.extend(to_list(resp))
145
146            commands.extend(neighbor_commands)
147
148        return commands
149
150    def _render_advertisement_interval(self, item, config=None):
151        cmd = "neighbor %s advertisement-interval %s" % (
152            item["neighbor"],
153            item["advertisement_interval"],
154        )
155        if not config or cmd not in config:
156            return cmd
157
158    def _render_route_reflector_client(self, item, config=None):
159        cmd = "neighbor %s route-reflector-client" % item["neighbor"]
160        if item["route_reflector_client"] is False:
161            if not config or cmd in config:
162                cmd = "no %s" % cmd
163                return cmd
164        elif not config or cmd not in config:
165            return cmd
166
167    def _render_route_server_client(self, item, config=None):
168        cmd = "neighbor %s route-server-client" % item["neighbor"]
169        if item["route_server_client"] is False:
170            if not config or cmd in config:
171                cmd = "no %s" % cmd
172                return cmd
173        elif not config or cmd not in config:
174            return cmd
175
176    def _render_remove_private_as(self, item, config=None):
177        cmd = "neighbor %s remove-private-as" % item["neighbor"]
178        if item["remove_private_as"] is False:
179            if not config or cmd in config:
180                cmd = "no %s" % cmd
181                return cmd
182        elif not config or cmd not in config:
183            return cmd
184
185    def _render_next_hop_self(self, item, config=None):
186        cmd = "neighbor %s next-hop-self" % item["neighbor"]
187        if item["next_hop_self"] is False:
188            if not config or cmd in config:
189                cmd = "no %s" % cmd
190                return cmd
191        elif not config or cmd not in config:
192            return cmd
193
194    def _render_activate(self, item, config=None):
195        cmd = "neighbor %s activate" % item["neighbor"]
196        if item["activate"] is False:
197            if not config or cmd in config:
198                cmd = "no %s" % cmd
199                return cmd
200        elif not config or cmd not in config:
201            return cmd
202
203    def _render_maximum_prefix(self, item, config=None):
204        cmd = "neighbor %s maximum-prefix %s" % (
205            item["neighbor"],
206            item["maximum_prefix"],
207        )
208        if not config or cmd not in config:
209            return cmd
210
211    def _render_prefix_list_in(self, item, config=None):
212        cmd = "neighbor %s prefix-list %s in" % (
213            item["neighbor"],
214            item["prefix_list_in"],
215        )
216        if not config or cmd not in config:
217            return cmd
218
219    def _render_prefix_list_out(self, item, config=None):
220        cmd = "neighbor %s prefix-list %s out" % (
221            item["neighbor"],
222            item["prefix_list_out"],
223        )
224        if not config or cmd not in config:
225            return cmd
226