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.arista.eos.plugins.module_utils.network.eos.providers.providers import ( 15 CliProvider, 16) 17from ansible_collections.arista.eos.plugins.module_utils.network.eos.providers.cli.config.bgp.neighbors import ( 18 AFNeighbors, 19) 20 21 22class AddressFamily(CliProvider): 23 def render(self, config=None): 24 commands = list() 25 safe_list = list() 26 27 router_context = "router bgp %s" % self.get_value("config.bgp_as") 28 context_config = None 29 30 for item in self.get_value("config.address_family"): 31 context = "address-family %s" % item["afi"] 32 context_commands = list() 33 34 if config: 35 context_path = [router_context, context] 36 context_config = self.get_config_context( 37 config, context_path, indent=2 38 ) 39 40 for key, value in iteritems(item): 41 if value is not None: 42 meth = getattr(self, "_render_%s" % key, None) 43 if meth: 44 resp = meth(item, context_config) 45 if resp: 46 context_commands.extend(to_list(resp)) 47 48 if context_commands: 49 commands.append(context) 50 commands.extend(context_commands) 51 commands.append("exit") 52 53 safe_list.append(context) 54 55 if self.params["operation"] == "replace": 56 if config: 57 resp = self._negate_config(config, safe_list) 58 commands.extend(resp) 59 60 return commands 61 62 def _negate_config(self, config, safe_list=None): 63 commands = list() 64 matches = re.findall(r"(address-family .+)$", config, re.M) 65 for item in set(matches).difference(safe_list): 66 commands.append("no %s" % item) 67 return commands 68 69 def _render_auto_summary(self, item, config=None): 70 cmd = "auto-summary" 71 if item["auto_summary"] is False: 72 cmd = "no %s" % cmd 73 if not config or cmd not in config: 74 return cmd 75 76 def _render_synchronization(self, item, config=None): 77 cmd = "synchronization" 78 if item["synchronization"] is False: 79 cmd = "no %s" % cmd 80 if not config or cmd not in config: 81 return cmd 82 83 def _render_networks(self, item, config=None): 84 commands = list() 85 safe_list = list() 86 87 for entry in item["networks"]: 88 network = entry["prefix"] 89 if entry["masklen"]: 90 network = "%s/%s" % (entry["prefix"], entry["masklen"]) 91 safe_list.append(network) 92 93 cmd = "network %s" % network 94 95 if entry["route_map"]: 96 cmd += " route-map %s" % entry["route_map"] 97 98 if not config or cmd not in config: 99 commands.append(cmd) 100 101 if self.params["operation"] == "replace": 102 if config: 103 matches = re.findall(r"network (\S+)", config, re.M) 104 for entry in set(matches).difference(safe_list): 105 commands.append("no network %s" % entry) 106 107 return commands 108 109 def _render_redistribute(self, item, config=None): 110 commands = list() 111 safe_list = list() 112 113 for entry in item["redistribute"]: 114 option = entry["protocol"] 115 116 cmd = "redistribute %s" % entry["protocol"] 117 118 if entry["route_map"]: 119 cmd += " route-map %s" % entry["route_map"] 120 121 if not config or cmd not in config: 122 commands.append(cmd) 123 124 safe_list.append(option) 125 126 if self.params["operation"] == "replace": 127 if config: 128 matches = re.findall( 129 r"redistribute (\S+)(?:\s*)(\d*)", config, re.M 130 ) 131 for i in range(0, len(matches)): 132 matches[i] = " ".join(matches[i]).strip() 133 for entry in set(matches).difference(safe_list): 134 commands.append("no redistribute %s" % entry) 135 136 return commands 137 138 def _render_neighbors(self, item, config): 139 """generate bgp neighbor configuration""" 140 return AFNeighbors(self.params).render( 141 config, nbr_list=item["neighbors"] 142 ) 143