Beispiel #1
0
    def create_config(self):
        # Currently, supports only single peer
        c = CmdBuffer('\n')
        c << '[DEFAULT]'
        c << 'log_dir = {0}'.format(self.SHARED_VOLUME)
        c << 'use_stderr = False'
        c << '[message]'
        c << 'write_disk = True'
        c << 'write_dir = {0}/data/bgp/'.format(self.SHARED_VOLUME)
        c << 'format = json'

        if self.peers:
            info = next(iter(list(self.peers.values())))
            remote_as = info['remote_as']
            neigh_addr = info['neigh_addr'].split('/')[0]
            local_as = info['local_as'] or self.asn
            local_addr = info['local_addr'].split('/')[0]
            c << '[bgp]'
            c << 'afi_safi = ipv4, ipv6, vpnv4, vpnv6, flowspec, evpn'
            c << 'remote_as = {0}'.format(remote_as)
            c << 'remote_addr = {0}'.format(neigh_addr)
            c << 'local_as = {0}'.format(local_as)
            c << 'local_addr = {0}'.format(local_addr)

        with open('{0}/yabgp.ini'.format(self.config_dir), 'w') as f:
            print(yellow('[{0}\'s new yabgp.ini]'.format(self.name)))
            print(yellow(indent(str(c))))
            f.writelines(str(c))
Beispiel #2
0
 def reload_config(self):
     daemon = ['gobgpd']
     if self.zebra:
         daemon.append('zebra')
         if self.ospfd_config:
             daemon.append('ospfd')
     for d in daemon:
         cmd = '/usr/bin/pkill {0} -SIGHUP'.format(d)
         self.local(cmd)
     for v in chain.from_iterable(self.routes.itervalues()):
         if v['rf'] == 'ipv4' or v['rf'] == 'ipv6':
             r = CmdBuffer(' ')
             r << 'gobgp global -a {0}'.format(v['rf'])
             r << 'rib add {0}'.format(v['prefix'])
             if v['identifier']:
                 r << 'identifier {0}'.format(v['identifier'])
             if v['next-hop']:
                 r << 'nexthop {0}'.format(v['next-hop'])
             if v['local-pref']:
                 r << 'local-pref {0}'.format(v['local-pref'])
             if v['med']:
                 r << 'med {0}'.format(v['med'])
             if v['community']:
                 r << 'community {0}'.format(','.join(
                     v['community']) if isinstance(v['community'], (
                         list, tuple)) else v['community'])
             cmd = str(r)
         elif v['rf'] == 'ipv4-flowspec' or v['rf'] == 'ipv6-flowspec':
             cmd = 'gobgp global '\
                   'rib add match {0} then {1} -a {2}'.format(' '.join(v['matchs']), ' '.join(v['thens']), v['rf'])
         else:
             raise Exception('unsupported route faily: {0}'.format(v['rf']))
         self.local(cmd)
Beispiel #3
0
 def reload_config(self):
     for daemon in self._get_enabled_quagga_daemons():
         self.local('pkill {0} -SIGHUP'.format(daemon), capture=True)
     self.local('pkill gobgpd -SIGHUP', capture=True)
     self._wait_for_boot()
     for v in chain.from_iterable(self.routes.itervalues()):
         if v['rf'] == 'ipv4' or v['rf'] == 'ipv6':
             r = CmdBuffer(' ')
             r << 'gobgp global -a {0}'.format(v['rf'])
             r << 'rib add {0}'.format(v['prefix'])
             if v['identifier']:
                 r << 'identifier {0}'.format(v['identifier'])
             if v['next-hop']:
                 r << 'nexthop {0}'.format(v['next-hop'])
             if v['local-pref']:
                 r << 'local-pref {0}'.format(v['local-pref'])
             if v['med']:
                 r << 'med {0}'.format(v['med'])
             if v['community']:
                 r << 'community {0}'.format(
                     ','.join(v['community'])
                     if isinstance(v['community'], (list, tuple)) else v['community'])
             cmd = str(r)
         elif v['rf'] == 'ipv4-flowspec' or v['rf'] == 'ipv6-flowspec':
             cmd = 'gobgp global '\
                   'rib add match {0} then {1} -a {2}'.format(' '.join(v['matchs']), ' '.join(v['thens']), v['rf'])
         else:
             raise Exception('unsupported route family: {0}'.format(v['rf']))
         self.local(cmd)
Beispiel #4
0
    def del_route(self, route, identifier=None, reload_config=False):
        if not self._is_running():
            raise RuntimeError('Quagga/Zebra is not yet running')

        path = None
        new_paths = []
        for p in self.routes.get(route, []):
            if p['identifier'] != identifier:
                new_paths.append(p)
            else:
                path = p
        if not path:
            return

        rf = path['rf']
        c = CmdBuffer(' ')
        c << "vtysh -c 'configure terminal'"
        c << "-c 'router bgp {0}'".format(self.asn)
        c << "-c 'address-family {0} unicast'".format(rf)
        c << "-c 'no network {0}'".format(route)
        self.local(str(c), capture=True)

        # Delete route-map after deleting prefix
        self._vtysh_del_route_map(path)

        self.routes[route] = new_paths
Beispiel #5
0
    def create_config(self):
        # Manpage of exabgp.conf(5):
        # https://github.com/Exa-Networks/exabgp/blob/master/doc/man/exabgp.conf.5
        cmd = CmdBuffer('\n')
        for peer, info in self.peers.iteritems():
            cmd << 'neighbor {0} {{'.format(info['neigh_addr'].split('/')[0])
            cmd << '    router-id {0};'.format(self.router_id)
            cmd << '    local-address {0};'.format(
                info['local_addr'].split('/')[0])
            cmd << '    local-as {0};'.format(self.asn)
            cmd << '    peer-as {0};'.format(peer.asn)

            caps = []
            if info['as2']:
                caps.append('        asn4 disable;')
            if info['addpath']:
                caps.append('        add-path send/receive;')
            if caps:
                cmd << '    capability {'
                for cap in caps:
                    cmd << cap
                cmd << '    }'

            if info['passwd']:
                cmd << '    md5-password "{0}";'.format(info['passwd'])

            if info['passive']:
                cmd << '    passive;'
            cmd << '}'

        with open('{0}/exabgpd.conf'.format(self.config_dir), 'w') as f:
            print colors.yellow('[{0}\'s new exabgpd.conf]'.format(self.name))
            print colors.yellow(str(cmd))
            f.write(str(cmd))
Beispiel #6
0
 def _construct_ip_unicast(self, path):
     cmd = CmdBuffer(' ')
     cmd << str(path['prefix'])
     if path['next-hop']:
         cmd << 'next-hop {0}'.format(path['next-hop'])
     else:
         cmd << 'next-hop self'
     return str(cmd)
Beispiel #7
0
 def _curl_send_update(self, path, peer):
     c = CmdBuffer(' ')
     c << "curl -X POST"
     c << "-u admin:admin"
     c << "-H 'Content-Type: application/json'"
     c << "http://localhost:8801/v1/peer/{0}/send/update".format(peer)
     c << "-d '{0}'".format(json.dumps(path))
     return json.loads(self.local(str(c), capture=True))
Beispiel #8
0
 def reload_config(self):
     cmd = CmdBuffer(' ')
     cmd << 'docker exec'
     cmd << '{0} cp {1}/bgp.conf'.format(self.name, self.SHARED_VOLUME)
     cmd << '/etc/bagpipe-bgp/'
     local(str(cmd), capture=True)
     cmd = 'docker exec {0} service bagpipe-bgp restart'.format(self.name)
     local(cmd, capture=True)
Beispiel #9
0
 def _curl_is_running(self):
     c = CmdBuffer(' ')
     c << "curl -X GET"
     c << "-u admin:admin"
     c << "-H 'Content-Type: application/json'"
     c << "http://localhost:8801/v1/"
     c << "> /dev/null 2>&1; echo $?"
     return self.local(str(c), capture=True) == '0'
Beispiel #10
0
 def _start_exabgp(self):
     cmd = CmdBuffer(' ')
     cmd << 'env exabgp.log.destination={0}/exabgpd.log'.format(
         self.SHARED_VOLUME)
     cmd << "exabgp.tcp.bind='0.0.0.0' exabgp.tcp.port=179"
     cmd << './exabgp/sbin/exabgp {0}/exabgpd.conf'.format(
         self.SHARED_VOLUME)
     self.local(str(cmd), detach=True)
Beispiel #11
0
    def add_route(self,
                  route,
                  rf='ipv4',
                  attribute=None,
                  aspath=None,
                  community=None,
                  med=None,
                  extendedcommunity=None,
                  nexthop=None,
                  matchs=None,
                  thens=None,
                  local_pref=None,
                  identifier=None,
                  reload_config=False):
        if not self._is_running():
            raise RuntimeError('GoBGP is not yet running')

        self.routes.setdefault(route, [])
        path = {
            'prefix': route,
            'rf': rf,
            'attr': attribute,
            'next-hop': nexthop,
            'as-path': aspath,
            'community': community,
            'med': med,
            'local-pref': local_pref,
            'extended-community': extendedcommunity,
            'identifier': identifier,
            'matchs': matchs,
            'thens': thens,
        }

        c = CmdBuffer(' ')
        c << 'gobgp global rib -a {0} add'.format(rf)
        if rf in ('ipv4', 'ipv6'):
            c << route
            if path['identifier']:
                c << 'identifier {0}'.format(path['identifier'])
            if path['next-hop']:
                c << 'nexthop {0}'.format(path['next-hop'])
            if path['local-pref']:
                c << 'local-pref {0}'.format(path['local-pref'])
            if path['med']:
                c << 'med {0}'.format(path['med'])
            if path['community']:
                comm = str(path['community'])
                if isinstance(path['community'], (list, tuple)):
                    comm = ','.join(path['community'])
                c << 'community {0}'.format(comm)
        elif rf.endswith('-flowspec'):
            c << 'match {0}'.format(' '.join(path['matchs']))
            c << 'then {0}'.format(' '.join(path['thens']))
        else:
            raise Exception('unsupported address family: {0}'.format(rf))
        self.local(str(c), capture=True)

        self.routes[route].append(path)
Beispiel #12
0
    def _vtysh_del_route_map(self, path):
        route_map_name = path.get('route_map', '')
        if not route_map_name:
            return

        c = CmdBuffer(' ')
        c << "vtysh -c 'configure terminal'"
        c << "-c 'no route-map {0}'".format(route_map_name)
        self.local(str(c), capture=True)
Beispiel #13
0
 def run(self):
     super(BagpipeContainer, self).run()
     cmd = CmdBuffer(' ')
     cmd << 'docker exec'
     cmd << '{0} cp {1}/bgp.conf'.format(self.name, self.SHARED_VOLUME)
     cmd << '/etc/bagpipe-bgp/'
     local(str(cmd), capture=True)
     cmd = 'docker exec {0} service bagpipe-bgp start'.format(self.name)
     local(cmd, capture=True)
Beispiel #14
0
 def _get_adj_rib(self, peer, in_out='in'):
     peer_addr = self.peer_name(peer)
     c = CmdBuffer(' ')
     c << "curl -X GET"
     c << "-u admin:admin"
     c << "-H 'Content-Type: application/json'"
     c << "http://localhost:8801/v1-ext/peer/{0}/adj-rib-{1}".format(
         peer_addr, in_out)
     return json.loads(self.local(str(c), capture=True))
Beispiel #15
0
 def _start_bird(self):
     c = CmdBuffer()
     c << '#!/bin/sh'
     c << 'bird'
     cmd = 'echo "{0:s}" > {1}/start.sh'.format(c, self.config_dir)
     local(cmd)
     cmd = 'chmod 755 {0}/start.sh'.format(self.config_dir)
     local(cmd)
     self.local('{0}/start.sh'.format(self.SHARED_VOLUME))
Beispiel #16
0
 def _start_exabgp(self):
     cmd = CmdBuffer(' ')
     cmd << 'env exabgp.log.destination={0}/exabgpd.log'.format(
         self.SHARED_VOLUME)
     cmd << 'exabgp.daemon.user=root'
     cmd << 'exabgp.daemon.pid={0}'.format(self.PID_FILE)
     cmd << 'exabgp.tcp.bind="0.0.0.0" exabgp.tcp.port=179'
     cmd << 'exabgp {0}/exabgpd.conf'.format(self.SHARED_VOLUME)
     self.local(str(cmd), detach=True)
Beispiel #17
0
 def _start_gobgp(self, graceful_restart=False):
     c = CmdBuffer()
     c << '#!/bin/sh'
     c << '/go/bin/gobgpd -f {0}/gobgpd.conf -l {1} -p {2} -t {3} > ' \
          '{0}/gobgpd.log 2>&1'.format(self.SHARED_VOLUME, self.log_level, '-r' if graceful_restart else '', self.config_format)
     cmd = 'echo "{0:s}" > {1}/start.sh'.format(str(c), self.config_dir)
     local(cmd, capture=True)
     cmd = "chmod 755 {0}/start.sh".format(self.config_dir)
     local(cmd, capture=True)
     self.local("{0}/start.sh".format(self.SHARED_VOLUME), detach=True)
Beispiel #18
0
 def _construct_flowspec(self, path):
     cmd = CmdBuffer(' ')
     cmd << '{ match {'
     for match in path['matchs']:
         cmd << '{0};'.format(match)
     cmd << '} then {'
     for then in path['thens']:
         cmd << '{0};'.format(then)
     cmd << '} }'
     return str(cmd)
Beispiel #19
0
    def add_route(self,
                  route,
                  rf='ipv4',
                  attribute=None,
                  aspath=None,
                  community=None,
                  med=None,
                  extendedcommunity=None,
                  nexthop=None,
                  matchs=None,
                  thens=None,
                  local_pref=None,
                  identifier=None,
                  reload_config=False):
        if not self._is_running():
            raise RuntimeError('Quagga/Zebra is not yet running')

        if rf not in ('ipv4', 'ipv6'):
            raise ValueError('Unsupported address family: {0}'.format(rf))

        self.routes.setdefault(route, [])
        path = {
            'prefix': route,
            'rf': rf,
            'next-hop': nexthop,
            'as-path': aspath,
            'community': community,
            'med': med,
            'local-pref': local_pref,
            'extended-community': extendedcommunity,
            # Note: The following settings are not yet supported on this
            # implementation.
            'attr': None,
            'identifier': None,
            'matchs': None,
            'thens': None,
        }

        # Prepare route-map before adding prefix
        route_map_name = self._vtysh_add_route_map(path)
        path['route_map'] = route_map_name

        c = CmdBuffer(' ')
        c << "vtysh -c 'configure terminal'"
        c << "-c 'router bgp {0}'".format(self.asn)
        if rf == 'ipv6':
            c << "-c 'address-family ipv6'"
        if route_map_name:
            c << "-c 'network {0} route-map {1}'".format(route, route_map_name)
        else:
            c << "-c 'network {0}'".format(route)
        self.local(str(c), capture=True)

        self.routes[route].append(path)
Beispiel #20
0
    def _create_config_zebra(self):
        c = CmdBuffer()
        c << 'hostname zebra'
        c << 'password zebra'
        c << 'log file {0}/zebra.log'.format(self.QUAGGA_VOLUME)
        c << 'debug zebra packet'
        c << 'debug zebra kernel'
        c << 'debug zebra rib'
        c << ''

        with open('{0}/zebra.conf'.format(self.quagga_config_dir), 'w') as f:
            print colors.yellow('[{0}\'s new zebra.conf]'.format(self.name))
            print colors.yellow(indent(str(c)))
            f.writelines(str(c))
Beispiel #21
0
    def create_config(self):
        c = CmdBuffer()
        c << 'router id {0};'.format(self.router_id)
        for peer, info in self.peers.items():
            c << 'protocol bgp {'
            c << '  local as {0};'.format(self.asn)
            n_addr = info['neigh_addr'].split('/')[0]
            c << '  neighbor {0} as {1};'.format(n_addr, peer.asn)
            c << '  multihop;'
            c << '}'

        with open('{0}/bird.conf'.format(self.config_dir), 'w') as f:
            print(yellow('[{0}\'s new bird.conf]'.format(self.name)))
            print(yellow(indent(str(c))))
            f.writelines(str(c))
Beispiel #22
0
    def _create_config_ospfd(self):
        c = CmdBuffer()
        c << 'hostname ospfd'
        c << 'password zebra'
        c << 'router ospf'
        for redistribute in self.ospfd_config.get('redistributes', []):
            c << ' redistribute {0}'.format(redistribute)
        for network, area in list(self.ospfd_config.get('networks', {}).items()):
            c << ' network {0} area {1}'.format(network, area)
        c << 'log file {0}/ospfd.log'.format(self.QUAGGA_VOLUME)
        c << ''

        with open('{0}/ospfd.conf'.format(self.quagga_config_dir), 'w') as f:
            print(yellow('[{0}\'s new ospfd.conf]'.format(self.name)))
            print(yellow(indent(str(c))))
            f.writelines(str(c))
Beispiel #23
0
    def _create_config_zebra(self):
        c = CmdBuffer()
        c << 'hostname zebra'
        c << 'password zebra'
        c << 'log file {0}/zebra.log'.format(self.SHARED_VOLUME)
        c << 'debug zebra packet'
        c << 'debug zebra kernel'
        c << 'debug zebra rib'
        c << 'ipv6 forwarding'
        c << ''

        with open('{0}/zebra.conf'.format(self.config_dir), 'w') as f:
            print(yellow('[{0}\'s new zebra.conf]'.format(self.name)))
            c = str(c).strip()
            print(yellow(indent(c)))
            f.writelines(c)
Beispiel #24
0
 def del_route(self, route, identifier=None, reload_config=True):
     if route not in self.routes:
         return
     new_paths = []
     for path in self.routes[route]:
         if path['identifier'] != identifier:
             new_paths.append(path)
         else:
             r = CmdBuffer(' ')
             r << 'gobgp global -a {0}'.format(path['rf'])
             r << 'rib del {0}'.format(path['prefix'])
             if identifier:
                 r << 'identifier {0}'.format(identifier)
             cmd = str(r)
             self.local(cmd)
     self.routes[route] = new_paths
Beispiel #25
0
 def _construct_path_attributes(self, path):
     cmd = CmdBuffer(' ')
     if path['as-path']:
         cmd << 'as-path [{0}]'.format(' '.join(
             str(i) for i in path['as-path']))
     if path['med']:
         cmd << 'med {0}'.format(path['med'])
     if path['local-pref']:
         cmd << 'local-preference {0}'.format(path['local-pref'])
     if path['community']:
         cmd << 'community [{0}]'.format(' '.join(
             c for c in path['community']))
     if path['extended-community']:
         cmd << 'extended-community [{0}]'.format(
             path['extended-community'])
     if path['attr']:
         cmd << 'attribute [ {0} ]'.format(path['attr'])
     return str(cmd)
Beispiel #26
0
    def _create_config_zebra(self):
        c = CmdBuffer()
        c << 'hostname zebra'
        c << 'password zebra'
        for name, settings in self.zebra_config.get('interfaces', {}).items():
            c << 'interface {0}'.format(name)
            for setting in settings:
                c << str(setting)
        for route in self.zebra_config.get('routes', []):
            c << str(route)
        c << 'log file {0}/zebra.log'.format(self.SHARED_VOLUME)
        c << 'debug zebra packet'
        c << 'debug zebra kernel'
        c << 'debug zebra rib'
        c << ''

        with open('{0}/zebra.conf'.format(self.config_dir), 'w') as f:
            print colors.yellow('[{0}\'s new zebra.conf]'.format(self.name))
            print colors.yellow(indent(str(c)))
            f.writelines(str(c))
Beispiel #27
0
    def _construct_path(self, path, rf='ipv4', is_withdraw=False):
        cmd = CmdBuffer(' ')

        if rf in ['ipv4', 'ipv6']:
            cmd << 'route'
            cmd << self._construct_ip_unicast(path)
        elif rf in ['ipv4-flowspec', 'ipv6-flowspec']:
            cmd << 'flow route'
            cmd << self._construct_flowspec(path)
        else:
            raise ValueError('unsupported address family: %s' % rf)

        if path['identifier']:
            cmd << 'path-information {0}'.format(path['identifier'])

        if not is_withdraw:
            # Withdrawal should not require path attributes
            cmd << self._construct_path_attributes(path)

        return str(cmd)
Beispiel #28
0
    def _update_exabgp(self):
        if self.exabgp_path == '':
            return
        c = CmdBuffer()
        c << '#!/bin/bash'

        remotepath = '/root/exabgp'
        localpath = self.exabgp_path
        local('cp -r {0} {1}'.format(localpath, self.config_dir))
        c << 'cp {0}/etc/exabgp/exabgp.env {1}'.format(remotepath, self.SHARED_VOLUME)
        c << 'sed -i -e \'s/all = false/all = true/g\' {0}/exabgp.env'.format(self.SHARED_VOLUME)
        c << 'cp -r {0}/exabgp {1}'.format(self.SHARED_VOLUME,
                                           remotepath[:-1 * len('exabgp')])
        c << 'cp {0}/exabgp.env {1}/etc/exabgp/'.format(self.SHARED_VOLUME, remotepath)
        cmd = 'echo "{0:s}" > {1}/update.sh'.format(c, self.config_dir)
        local(cmd, capture=True)
        cmd = 'chmod 755 {0}/update.sh'.format(self.config_dir)
        local(cmd, capture=True)
        cmd = '{0}/update.sh'.format(self.SHARED_VOLUME)
        self.local(cmd)
Beispiel #29
0
    def create_config(self):
        c = CmdBuffer()
        c << '[BGP]'
        if len(self.ip_addrs) > 0:
            c << 'local_address={0}'.format(self.ip_addrs[0][1].split('/')[0])
        for info in list(self.peers.values()):
            c << 'peers={0}'.format(info['neigh_addr'].split('/')[0])
        c << 'my_as={0}'.format(self.asn)
        c << 'enable_rtc=True'
        c << '[API]'
        c << 'api_host=localhost'
        c << 'api_port=8082'
        c << '[DATAPLANE_DRIVER_IPVPN]'
        c << 'dataplane_driver = DummyDataplaneDriver'
        c << '[DATAPLANE_DRIVER_EVPN]'
        c << 'dataplane_driver = DummyDataplaneDriver'

        with open('{0}/bgp.conf'.format(self.config_dir), 'w') as f:
            print(yellow(str(c)))
            f.writelines(str(c))
Beispiel #30
0
    def _vtysh_add_route_map(self, path):
        supported_attributes = (
            'next-hop',
            'as-path',
            'community',
            'med',
            'local-pref',
            'extended-community',
        )
        if not any([path[k] for k in supported_attributes]):
            return ''

        c = CmdBuffer(' ')
        route_map_name = 'RM-{0}'.format(path['prefix'])
        c << "vtysh -c 'configure terminal'"
        c << "-c 'route-map {0} permit 10'".format(route_map_name)
        if path['next-hop']:
            if path['rf'] == 'ipv4':
                c << "-c 'set ip next-hop {0}'".format(path['next-hop'])
            elif path['rf'] == 'ipv6':
                c << "-c 'set ipv6 next-hop {0}'".format(path['next-hop'])
            else:
                raise ValueError('Unsupported address family: {0}'.format(
                    path['rf']))
        if path['as-path']:
            as_path = ' '.join([str(n) for n in path['as-path']])
            c << "-c 'set as-path prepend {0}'".format(as_path)
        if path['community']:
            comm = ' '.join(path['community'])
            c << "-c 'set community {0}'".format(comm)
        if path['med']:
            c << "-c 'set metric {0}'".format(path['med'])
        if path['local-pref']:
            c << "-c 'set local-preference {0}'".format(path['local-pref'])
        if path['extended-community']:
            # Note: Currently only RT is supported.
            extcomm = ' '.join(path['extended-community'])
            c << "-c 'set extcommunity rt {0}'".format(extcomm)
        self.local(str(c), capture=True)

        return route_map_name