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#
5import re
6
7from ansible.module_utils.six import iteritems
8from ansible.module_utils.network.common.utils import to_list
9from ansible.module_utils.network.ios.providers.providers import CliProvider
10
11
12class Neighbors(CliProvider):
13
14    def render(self, config=None, nbr_list=None):
15        commands = list()
16        safe_list = list()
17        if not nbr_list:
18            nbr_list = self.get_value('config.neighbors')
19
20        for item in nbr_list:
21            neighbor_commands = list()
22            context = 'neighbor %s' % item['neighbor']
23            cmd = '%s remote-as %s' % (context, item['remote_as'])
24
25            if not config or cmd not in config:
26                neighbor_commands.append(cmd)
27
28            for key, value in iteritems(item):
29                if value is not None:
30                    meth = getattr(self, '_render_%s' % key, None)
31                    if meth:
32                        resp = meth(item, config)
33                        if resp:
34                            neighbor_commands.extend(to_list(resp))
35
36            commands.extend(neighbor_commands)
37            safe_list.append(context)
38
39        if self.params['operation'] == 'replace':
40            if config and safe_list:
41                commands.extend(self._negate_config(config, safe_list))
42
43        return commands
44
45    def _negate_config(self, config, safe_list=None):
46        commands = list()
47        matches = re.findall(r'(neighbor \S+)', config, re.M)
48        for item in set(matches).difference(safe_list):
49            commands.append('no %s' % item)
50        return commands
51
52    def _render_local_as(self, item, config=None):
53        cmd = 'neighbor %s local-as %s' % (item['neighbor'], item['local_as'])
54        if not config or cmd not in config:
55            return cmd
56
57    def _render_port(self, item, config=None):
58        cmd = 'neighbor %s port %s' % (item['neighbor'], item['port'])
59        if not config or cmd not in config:
60            return cmd
61
62    def _render_description(self, item, config=None):
63        cmd = 'neighbor %s description %s' % (item['neighbor'], item['description'])
64        if not config or cmd not in config:
65            return cmd
66
67    def _render_enabled(self, item, config=None):
68        cmd = 'neighbor %s shutdown' % item['neighbor']
69        if item['enabled'] is True:
70            if not config or cmd in config:
71                cmd = 'no %s' % cmd
72                return cmd
73        elif not config or cmd not in config:
74            return cmd
75
76    def _render_update_source(self, item, config=None):
77        cmd = 'neighbor %s update-source %s' % (item['neighbor'], item['update_source'])
78        if not config or cmd not in config:
79            return cmd
80
81    def _render_password(self, item, config=None):
82        cmd = 'neighbor %s password %s' % (item['neighbor'], item['password'])
83        if not config or cmd not in config:
84            return cmd
85
86    def _render_ebgp_multihop(self, item, config=None):
87        cmd = 'neighbor %s ebgp-multihop %s' % (item['neighbor'], item['ebgp_multihop'])
88        if not config or cmd not in config:
89            return cmd
90
91    def _render_peer_group(self, item, config=None):
92        cmd = 'neighbor %s peer-group %s' % (item['neighbor'], item['peer_group'])
93        if not config or cmd not in config:
94            return cmd
95
96    def _render_timers(self, item, config):
97        """generate bgp timer related configuration
98        """
99        keepalive = item['timers']['keepalive']
100        holdtime = item['timers']['holdtime']
101        min_neighbor_holdtime = item['timers']['min_neighbor_holdtime']
102        neighbor = item['neighbor']
103
104        if keepalive and holdtime:
105            cmd = 'neighbor %s timers %s %s' % (neighbor, keepalive, holdtime)
106            if min_neighbor_holdtime:
107                cmd += ' %s' % min_neighbor_holdtime
108            if not config or cmd not in config:
109                return cmd
110
111
112class AFNeighbors(CliProvider):
113
114    def render(self, config=None, nbr_list=None):
115        commands = list()
116        if not nbr_list:
117            return
118
119        for item in nbr_list:
120            neighbor_commands = list()
121            for key, value in iteritems(item):
122                if value is not None:
123                    meth = getattr(self, '_render_%s' % key, None)
124                    if meth:
125                        resp = meth(item, config)
126                        if resp:
127                            neighbor_commands.extend(to_list(resp))
128
129            commands.extend(neighbor_commands)
130
131        return commands
132
133    def _render_advertisement_interval(self, item, config=None):
134        cmd = 'neighbor %s advertisement-interval %s' % (item['neighbor'], item['advertisement_interval'])
135        if not config or cmd not in config:
136            return cmd
137
138    def _render_route_reflector_client(self, item, config=None):
139        cmd = 'neighbor %s route-reflector-client' % item['neighbor']
140        if item['route_reflector_client'] is False:
141            if not config or cmd in config:
142                cmd = 'no %s' % cmd
143                return cmd
144        elif not config or cmd not in config:
145            return cmd
146
147    def _render_route_server_client(self, item, config=None):
148        cmd = 'neighbor %s route-server-client' % item['neighbor']
149        if item['route_server_client'] is False:
150            if not config or cmd in config:
151                cmd = 'no %s' % cmd
152                return cmd
153        elif not config or cmd not in config:
154            return cmd
155
156    def _render_remove_private_as(self, item, config=None):
157        cmd = 'neighbor %s remove-private-as' % item['neighbor']
158        if item['remove_private_as'] is False:
159            if not config or cmd in config:
160                cmd = 'no %s' % cmd
161                return cmd
162        elif not config or cmd not in config:
163            return cmd
164
165    def _render_next_hop_self(self, item, config=None):
166        cmd = 'neighbor %s next-hop-self' % item['neighbor']
167        if item['next_hop_self'] is False:
168            if not config or cmd in config:
169                cmd = 'no %s' % cmd
170                return cmd
171        elif not config or cmd not in config:
172            return cmd
173
174    def _render_activate(self, item, config=None):
175        cmd = 'neighbor %s activate' % item['neighbor']
176        if item['activate'] is False:
177            if not config or cmd in config:
178                cmd = 'no %s' % cmd
179                return cmd
180        elif not config or cmd not in config:
181            return cmd
182
183    def _render_maximum_prefix(self, item, config=None):
184        cmd = 'neighbor %s maximum-prefix %s' % (item['neighbor'], item['maximum_prefix'])
185        if not config or cmd not in config:
186            return cmd
187