Example #1
0
def setup_config():
    api_config.register_config()
    config.register()
    cfg.CONF(
        args=sys.argv[1:],
        project='bagpipe-bgp',
        default_config_files=['/etc/bagpipe-bgp/bgp.conf'],
        version=(
            '%%(prog)s %s' %
            pbr.version.VersionInfo('networking-bagpipe').release_string()))
Example #2
0
def main():
    api_config.register_config()
    cfg.CONF(args=[],
             project='bagpipe-rest-attach',
             default_config_files=['/etc/bagpipe-bgp/bgp.conf'])

    usage = "usage: %prog [--attach|--detach] --network-type (ipvpn|evpn) "\
        "--port (<port>|netns) --ip <ip>[/<mask>] [options] (see --help)"
    parser = optparse.OptionParser(usage)

    parser.add_option("--attach",
                      dest="operation",
                      action="store_const",
                      const="attach",
                      help="attach local port")
    parser.add_option("--detach",
                      dest="operation",
                      action="store_const",
                      const="detach",
                      help="detach local port")

    parser.add_option("--network-type",
                      dest="network_type",
                      help="network type (ipvpn or evpn)",
                      choices=[const.IPVPN, const.EVPN])
    parser.add_option("--vpn-instance-id",
                      dest="vpn_instance_id",
                      help="UUID for the network instance "
                      "(default: %default-(ipvpn|evpn))",
                      default=DEFAULT_VPN_INSTANCE_ID)
    parser.add_option("--port",
                      dest="port",
                      help="local port to attach/detach (use special port "
                      "'netns[:if]' to have an interface to a local network "
                      "namespace attached/detached "
                      "[with 'if' as the name of the interface to the netns]")
    parser.add_option("--direction",
                      dest="direction",
                      choices=[const.TO_PORT, const.FROM_PORT, const.BOTH],
                      default=const.BOTH,
                      help=("local port direction (to-port|from-port|both) "
                            "in VPN (default: %default)"))
    parser.add_option("--rt",
                      dest="route_targets",
                      help="route target [default: 64512:0] (can be "
                      "specified multiple times)",
                      default=[],
                      action="append")
    parser.add_option("--import-rt",
                      dest="import_only_rts",
                      help="import-only route target (can be specified"
                      "multiple times)",
                      default=[],
                      action="append")
    parser.add_option("--export-rt",
                      dest="export_only_rts",
                      help="export-only route target (can be specified"
                      "multiple times)",
                      default=[],
                      action="append")

    parser.add_option("--ip",
                      dest="ip",
                      help="IP prefix / mask (mask defaults to /24)")
    parser.add_option("--gateway-ip",
                      dest="gw_ip",
                      help="IP address of network gateway (optional, "
                      "defaults to last IP in range)")
    parser.add_option("--mac",
                      dest="mac",
                      help="MAC address (required for evpn if port"
                      " is not 'netns')")

    parser.set_defaults(advertise_subnet=False)
    parser.add_option("--advertise-singleton",
                      action="store_false",
                      dest="advertise_subnet",
                      help="advertise IP address as a /32 (default)")

    parser.add_option("--advertise-subnet",
                      action="store_true",
                      dest="advertise_subnet",
                      help="advertise the whole IP subnet")

    parser.add_option("--ovs-preplug",
                      action="store_true",
                      dest="ovs_preplug",
                      default=False,
                      help="should we prealably plug the port "
                      "into an OVS bridge")
    parser.add_option("--ovs-bridge",
                      dest="bridge",
                      default="br-int",
                      help="if preplug, specifies which OVS bridge to use"
                      " (default: %default)")
    parser.add_option("--ovs-vlan",
                      dest="ovs_vlan",
                      type='int',
                      help="if specified, only this VLAN from the OVS "
                      "interface will be attached to the VPN instance "
                      "(optional)")

    parser.add_option("--netns",
                      dest="netns",
                      help="name of network namespace (optional, for use with"
                      " --port netns)")
    parser.add_option("--if2vpn",
                      dest="if2vpn",
                      default=NS2VPN_DEFAULT_IFNAME,
                      help="name of interface in netns toward VPN"
                      "defaults to %default "
                      "(optional, for use with --port netns)")

    parser.add_option("--readv-from-rt",
                      dest="readv_from_rts",
                      help="enables route readvertisement from these RTs,"
                      " works in conjunction with --readv-to-rt",
                      default=[],
                      action="append")

    parser.add_option("--readv-to-rt",
                      dest="readv_to_rts",
                      help="enables route readvertisement to these RTs,"
                      " works in conjunction with --readv-from-rt",
                      default=[],
                      action="append")

    parser.add_option("--redirect-rts",
                      dest="redirect_rts",
                      help="Redirection Route Targets to attract traffic, "
                      "matching the traffic classifier, in specified VRF from "
                      "any VRF importing this route target",
                      default=[],
                      action="append")
    parser.add_option("--source-prefix",
                      dest="sourcePrefix",
                      type="string",
                      help="Traffic classifier source prefix "
                      "filter",
                      action="callback",
                      callback=classifier_callback)
    parser.add_option("--destination-prefix",
                      dest="destinationPrefix",
                      type="string",
                      help="Traffic classifier destination "
                      "prefix filter",
                      action="callback",
                      callback=classifier_callback)
    parser.add_option("--source-port",
                      dest="sourcePort",
                      type="string",
                      help="Traffic classifier source port "
                      "number or range filter",
                      action="callback",
                      callback=classifier_callback)
    parser.add_option("--destination-port",
                      dest="destinationPort",
                      type="string",
                      help="Traffic classifier destination port"
                      " number or range filter",
                      action="callback",
                      callback=classifier_callback)
    parser.add_option("--protocol",
                      dest="protocol",
                      type="string",
                      help="Traffic classifier IP protocol "
                      "filter",
                      action="callback",
                      callback=classifier_callback)
    parser.add_option("--attract-to-rt",
                      dest="attract_to_rts",
                      help="enables route advertisement to these RTs,"
                      " works in conjunction with "
                      "--static-destination-prefix",
                      default=[],
                      action="append")
    parser.add_option("--static-destination-prefix",
                      dest="static_dest_prefixes",
                      help="static destination prefix to advertise,"
                      " works in conjunction with --attract-to-rts",
                      default=[],
                      action="append")
    parser.add_option("--lb-consistent-hash-order",
                      dest="lb_consistent_hash_order",
                      default=0,
                      type="int",
                      help="Load Balancing consistent hash sort order")
    parser.add_option("--vni",
                      dest="vni",
                      default=0,
                      type="int",
                      help="VXLAN VNI to use for this VPN instance (optional)")
    parser.add_option("--local-pref",
                      dest="local_pref",
                      default=None,
                      type="int",
                      help="BGP LOCAL PREF attribute (optional)")
    (options, _) = parser.parse_args()

    if not (options.operation):
        parser.error("Need to specify --attach or --detach")

    if not (options.port):
        parser.error("Need to specify --port <localport>")

    if not (options.network_type):
        parser.error("Need to specify --network-type")

    if not (options.ip):
        parser.error("Need to specify --ip")

    if (len(options.route_targets) == 0
            and not (options.import_only_rts or options.export_only_rts)):
        if options.network_type == const.IPVPN:
            options.route_targets = ["64512:512"]
        else:
            options.route_targets = ["64512:513"]

    import_rts = copy.copy(options.route_targets or [])
    for rt in options.import_only_rts:
        import_rts.append(rt)

    export_rts = copy.copy(options.route_targets or [])
    for rt in options.export_only_rts:
        export_rts.append(rt)

    if not re.match('.*/[0-9]+$', options.ip):
        options.ip = options.ip + "/24"

    if not (options.gw_ip):
        net = netaddr.IPNetwork(options.ip)
        print("using %s as gateway address" % str(net[-2]))
        options.gw_ip = str(net[-2])

    if options.vpn_instance_id == DEFAULT_VPN_INSTANCE_ID:
        options.vpn_instance_id = "%s-%s" % (options.network_type,
                                             options.vpn_instance_id)

    if options.port.startswith("netns"):

        if not options.netns:
            options.netns = options.vpn_instance_id

        try:
            (_, options.if2netns) = options.port.split(":")
        except Exception:
            options.if2netns = get_vpn2ns_if_name(options.netns)

        if options.operation == "attach":
            create_special_netns_port(options)

        options.port = options.if2netns
        if not options.mac:
            options.mac = net_utils.get_device_mac(run_log_command,
                                                   options.if2vpn,
                                                   options.netns)

        print("Local port: %s (%s)" % (options.port, options.mac))
        run_log_command("ip link show %s" % options.port)

    local_port = {}
    if options.port[:5] == "evpn:":
        if (options.network_type == const.IPVPN):
            print("will plug evpn %s into the IPVPN" % options.port[5:])
            local_port['evpn'] = {'id': options.port[5:]}
        else:
            raise Exception("Can only plug an evpn into an ipvpn")
    else:
        local_port['linuxif'] = options.port

        # currently our only the MPLS OVS driver for ipvpn requires preplug
        if (options.ovs_preplug and options.network_type == const.IPVPN):
            print("pre-plugging %s into %s" % (options.port, options.bridge))
            run_log_command("ovs-vsctl del-port %s %s" %
                            (options.bridge, options.port),
                            raise_on_error=False)
            run_log_command("ovs-vsctl add-port %s %s" %
                            (options.bridge, options.port))

            local_port['ovs'] = {'port_name': options.port, 'plugged': True}

            if options.ovs_vlan:
                local_port['ovs']['vlan'] = options.ovs_vlan

    if not options.mac:
        if options.network_type == const.IPVPN:
            options.mac = "52:54:00:99:99:22"
        else:
            parser.error("Need to specify --mac for an EVPN network "
                         "attachment if port is not 'netns'")

    readvertise = None
    if options.readv_to_rts:
        readvertise = {
            "from_rt": options.readv_from_rts,
            "to_rt": options.readv_to_rts
        }

    attract_traffic = dict()
    if options.redirect_rts:
        if options.classifier:
            attract_traffic.update(
                dict(redirect_rts=options.redirect_rts,
                     classifier=options.classifier))
        else:
            parser.error("Need to specify --redirect-rt and at least one "
                         "traffic classifier option")

        if options.attract_to_rts:
            if options.static_dest_prefixes:
                attract_traffic.update(
                    dict(to=options.attract_to_rts,
                         static_destination_prefixes=options.
                         static_dest_prefixes))
            else:
                parser.error("Need to specify --attract-to-rt and at least "
                             "one static destination prefix option")

    data = {
        "import_rt": import_rts,
        "export_rt": export_rts,
        "local_port": local_port,
        "vpn_instance_id": options.vpn_instance_id,
        "vpn_type": options.network_type,
        "gateway_ip": options.gw_ip,
        "mac_address": options.mac,
        "ip_address": options.ip,
        "advertise_subnet": options.advertise_subnet,
        "readvertise": readvertise,
        "attract_traffic": attract_traffic,
        "lb_consistent_hash_order": options.lb_consistent_hash_order,
        "vni": options.vni
    }

    if options.local_pref:
        data['local_pref'] = options.local_pref

    if options.direction:
        data['direction'] = options.direction

    json_data = jsonutils.dumps(data)

    print("request: %s" % json_data)

    os.environ['NO_PROXY'] = "127.0.0.1"
    req = urllib2.Request(
        "http://127.0.0.1:%d/%s_localport" %
        (cfg.CONF.API.port, options.operation), json_data,
        {'Content-Type': 'application/json'})
    try:
        response = urllib2.urlopen(req)
        response_content = response.read()
        response.close()

        print("response: %d %s" % (response.getcode(), response_content))
    except urllib2.HTTPError as e:
        error_content = e.read()
        print("   %s" % error_content)
        sys.exit("error %d, reason: %s" % (e.code, e.reason))
Example #3
0
def main():
    api_config.register_config()
    try:
        cfg.CONF(args=[],
                 project='bagpipe-looking-glass',
                 default_config_files=['/etc/bagpipe-bgp/bgp.conf'])
        api_port = cfg.CONF.API.port
    except cfg.ConfigFilesNotFoundError:
        api_port = api_config.DEFAULT_PORT

    usage = """ %prog [--server <ip>] path to object in looking-glass

e.g.: %prog vpns instances"""
    parser = optparse.OptionParser(usage)

    parser.add_option(
        "--server",
        dest="server",
        default="127.0.0.1",
        help="IP address of BaGPipe BGP (optional, default: %default)")

    parser.add_option("--port",
                      dest="port",
                      type="int",
                      default=api_port,
                      help="Port of BaGPipe BGP (optional, default: %default)")

    parser.add_option(
        "--prefix",
        dest="prefix",
        default=LOOKING_GLASS_BASE,
        help="Looking-glass URL Prefix (optional, default: %default)")

    parser.add_option(
        "-r",
        "--recurse",
        dest="recurse",
        action="store_true",
        default=False,
        help="Recurse down into the whole looking-glass (disabled by default)")

    (options, args) = parser.parse_args()

    quoted_args = [urllib2.quote(arg) for arg in args]
    target_url = "http://%s:%d/%s/%s" % (options.server, options.port,
                                         options.prefix, "/".join(quoted_args))
    try:
        os.environ['NO_PROXY'] = options.server
        response = urllib2.urlopen(target_url)

        if response.getcode() == 200:
            data = jsonutils.load(response)

            if (isinstance(data, dict) and "href" in data):
                target_url_bis = data["href"]
                response_bis = urllib2.urlopen(target_url_bis)
                if response.getcode() == 200:
                    target_url = target_url_bis
                    data = jsonutils.load(response_bis)

            pretty_print_recurse(data,
                                 0,
                                 options.recurse,
                                 target_url,
                                 already_anew_line=True)

    except urllib2.HTTPError as e:
        if e.code == 404:
            print("No such looking glass path: %s\n(%s)" %
                  (" ".join(quoted_args), target_url))
        else:
            print("Error code %d: %s" % (e.getcode(), e.read()))
        return
    except urllib2.URLError as e:
        print("No server at http://%s:%d : %s" %
              (options.server, options.port, e))
def main():
    api_config.register_config()
    try:
        cfg.CONF(args=[],
                 project='bagpipe-impex2dot',
                 default_config_files=['/etc/bagpipe-bgp/bgp.conf'])
        api_port = cfg.CONF.API.port
    except cfg.ConfigFilesNotFoundError:
        api_port = api_config.DEFAULT_PORT

    usage = """ %prog [options]

Example: bagpipe-impex2dot --server s1 --server s2 | dot -Tpdf > impex.pdf
    """
    parser = optparse.OptionParser(usage)

    parser.add_option(
        "--server", dest="servers", default=[], action="append",
        help="IP address of a BaGPipe BGP instances (default: localhost)")

    parser.add_option(
        "--port", dest="port", type="int", default=api_port,
        help="Port of BaGPipe BGP (optional, default: %default)")

    parser.add_option(
        "--prefix", dest="prefix", default=LOOKING_GLASS_BASE,
        help="Looking-glass URL Prefix (optional, default: %default)")

    (options, _) = parser.parse_args()

    if len(options.servers) == 0:
        options.servers = ["localhost"]

    ports = set()
    dests = set()
    print('digraph import_export {')

    print('   node [fontname="Helvetica"];')
    print('   edge [fontname="Helvetica"];')
    print('   nodesep=0.55;')

    (rts, vpns) = get_all(options)
    print('   subgraph rts {')
    print('       rank=same;')
    for rt in rts:
        label = rt.upper().replace('_', '\\n')
        print('        %s [shape="circle",label="%s",%s];' % (rt, label,
                                                              RT_TXT_STYLE))
    print('    }')

    print('    subgraph ipvpns {')
    print('        rank=same;')
    for (server, vpn, _) in filter(lambda x: x[2] == 'VRF', vpns):
        server_spec = ("\\n[%s]" % server) if server != 'localhost' else ''
        print('        %s [label="{<0>VRF\\n%s%s|<readv>}",'
              'shape="record"];' % (vpn_uid(server, vpn), vpn_short(vpn),
                                    server_spec))
    print('    }')

    print('    subgraph evpns {')
    for (server, vpn, _) in filter(lambda x: x[2] == 'EVI', vpns):
        server_spec = ("\\n[%s]" % server) if server != 'localhost' else ''
        print('        %s [label="{<0>EVI\\n%s%s}",'
              'shape="record"];' % (vpn_uid(server, vpn), vpn_short(vpn),
                                    server_spec))
    print('    }')

    for (server, vpn, _) in vpns:
        print('    /* %s:%s */' % (server, vpn))
        uid = vpn_uid(server, vpn)

        for rt_i in request(options, server, ["vpns", "instances", vpn,
                                              "route_targets", "import"]):
            print('    %s -> %s:0 [%s];' % (normalize(rt_i), uid,
                                            RT_STYLE))

        for rt_e in request(options, server, ["vpns", "instances", vpn,
                                              "route_targets", "export"]):
            print('    %s:0 -> %s [%s];' % (uid, normalize(rt_e),
                                            RT_STYLE))

        readvertise = request(options, server, ["vpns", "instances",
                                                vpn, "readvertise"])
        if readvertise:
            readv = "%s:readv" % vpn_uid(server, vpn)
            print('    %s -> %s [label="",%s];' %
                  (normalize(readvertise['from'][0]),
                   readv,
                   RT_STYLE_REDIR_FROM_RT))
            print('    %s -> %s [label="",%s];' %
                  (readv,
                   normalize(readvertise['to'][0]),
                   RT_STYLE_REDIR_TO_RT))

            attract = readvertise.get('attract_traffic', None)
            if attract:
                intermediate = "%s_%s_attract" % (normalize(server),
                                                  normalize(vpn))
                print('    %s [style=invis,height=0,width=0,'
                      'fixedsize=true,rank=1]' % intermediate)

                redir_rt = attract['redirect_rts'][0]

                # readv -> intermediate
                print('    %s -> %s [label="flow",%s];' %
                      (readv, intermediate,
                       RT_STYLE_FLOWSPEC_INTER))

                # intermediate -> flowspec route RT
                print('    %s -> %s [label="",weight=50,%s];' %
                      (intermediate, normalize(redir_rt),
                       RT_STYLE_FLOWSPEC))

                # intermediate -> flowspec route redirect action  RT
                print('    %s -> %s [label="action",%s,arrowhead=none'
                      ',weight=20];' %
                      (intermediate, normalize(readvertise['to'][0]),
                       RT_STYLE_FLOWSPEC_ACTION))

        for port in request(options, server, ["vpns", "instances",
                                              vpn, "ports"]).keys():
            print('    %s -> port_%s_%s [%s,weight=5];' % (uid,
                                                           normalize(server),
                                                           normalize(port),
                                                           PORT_LINK_STYLE))
            ports.add((server, normalize(port)))

        # possible link between an E-VPN and an IPVPN ?
        ipvpn = request(options, server, ["vpns", "instances",
                                          vpn, "gateway_port", "ipvpn"])
        if ipvpn:
            ipvpn_id = ipvpn['external_instance_id']
            print('    %s -> %s [weight=500];' % (uid,
                                                  vpn_uid(server, ipvpn_id))
                  )

    for (server, port) in ports:
        print('    port_%s_%s [label="",style=invis,height=0,width=0,'
              'fixedsize=true];' % (normalize(server),
                                    normalize(port)))
        if port.startswith('to_'):
            dest = port.split('_')[1]
            print('    port_%s_%s -> dest_%s_%s [style=dashed,'
                  'dir=none,color="gray"'
                  ',weight=5];' %
                  (normalize(server), normalize(port), normalize(server),
                   dest))
            dests.add((server, dest))

    for (server, dest) in dests:
        print('    dest_%s_%s [label="%s\\n[%s]",shape="square",'
              'color="gray"];' % (normalize(server),
                                  normalize(dest), dest, server))

    print('}')