#!/usr/bin/python # -- coding: utf-8 -- # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. import logging from . import CsHelper from .CsDatabag import CsDataBag from .CsFile import CsFile FRR_DIR = "/etc/frr/" FRR_DAEMONS = "/etc/frr/daemons" FRR_CONFIG = "/etc/frr/frr.conf" class CsBgpPeers(CsDataBag): def process(self): logging.info("Processing CsBgpPeers file ==> %s" % self.dbag) if self.config.is_vpc(): self.public_ip = self.cl.get_source_nat_ip() else: self.public_ip = self.cl.get_eth2_ip() self.peers = {} for item in self.dbag: if item == "id": continue self._process_dbag_item(self.dbag[item]) restart_frr = False CsHelper.mkdir(FRR_DIR, 0o755, False) self.frr_daemon = CsFile(FRR_DAEMONS) self.frr_daemon.replaceIfFound("bgpd=no", "bgpd=yes") if self.frr_daemon.commit(): restart_frr = True self.frr_conf = CsFile(FRR_CONFIG) self.frr_conf.repopulate() self._pre_set() self._process_peers() self._post_set() if self.frr_conf.commit(): restart_frr = True if restart_frr: CsHelper.execute("systemctl enable frr") CsHelper.execute("systemctl restart frr") def _process_dbag_item(self, item): as_number = item['network_as_number'] if as_number not in self.peers.keys(): self.peers[as_number] = {} self.peers[as_number]['ip4_peers'] = [] self.peers[as_number]['ip6_peers'] = [] if 'ip4_address' in item and 'guest_ip4_cidr' in item: self.peers[as_number]['ip4_peers'].append(item) if 'ip6_address' in item and 'guest_ip6_cidr' in item: self.peers[as_number]['ip6_peers'].append(item) def _pre_set(self): self.frr_conf.add("frr version 6.0") self.frr_conf.add("frr defaults traditional") self.frr_conf.add("hostname {}".format(CsHelper.get_hostname())) self.frr_conf.add("service integrated-vtysh-config") self.frr_conf.add("ip nht resolve-via-default") return def _process_peers(self): for as_number in self.peers.keys(): self.frr_conf.add("router bgp {}".format(as_number)) self.frr_conf.add(" bgp router-id {}".format(self.public_ip)) if self.peers[as_number]['ip6_peers']: self.frr_conf.add(" bgp default ipv6-unicast") for ip4_peer in self.peers[as_number]['ip4_peers']: self.frr_conf.add(" neighbor {} remote-as {}".format(ip4_peer['ip4_address'], ip4_peer['peer_as_number'])) if 'peer_password' in ip4_peer: self.frr_conf.add(" neighbor {} password {}".format(ip4_peer['ip4_address'], ip4_peer['peer_password'])) if 'details' in ip4_peer: if 'EBGP_MultiHop' in ip4_peer['details']: self.frr_conf.add(" neighbor {} ebgp-multihop {}".format(ip4_peer['ip4_address'], ip4_peer['details']['EBGP_MultiHop'])) for ip6_peer in self.peers[as_number]['ip6_peers']: self.frr_conf.add(" neighbor {} remote-as {}".format(ip6_peer['ip6_address'], ip6_peer['peer_as_number'])) if 'peer_password' in ip6_peer: self.frr_conf.add(" neighbor {} password {}".format(ip6_peer['ip6_address'], ip6_peer['peer_password'])) if 'details' in ip6_peer: if 'EBGP_MultiHop' in ip6_peer['details']: self.frr_conf.add(" neighbor {} ebgp-multihop {}".format(ip6_peer['ip6_address'], ip6_peer['details']['EBGP_MultiHop'])) if self.peers[as_number]['ip4_peers']: self.frr_conf.add(" address-family ipv4 unicast") ip4_cidrs = set({ip4_peer['guest_ip4_cidr'] for ip4_peer in self.peers[as_number]['ip4_peers']}) for ip4_cidr in ip4_cidrs: self.frr_conf.add(" network {}".format(ip4_cidr)) self.frr_conf.add(" exit-address-family") if self.peers[as_number]['ip6_peers']: self.frr_conf.add(" address-family ipv6 unicast") ip6_cidrs = set({ip6_peer['guest_ip6_cidr'] for ip6_peer in self.peers[as_number]['ip6_peers']}) for ip6_cidr in ip6_cidrs: self.frr_conf.add(" network {}".format(ip6_cidr)) self.frr_conf.add(" exit-address-family") def _post_set(self): self.frr_conf.add("line vty")