From 30daf22b671c0a207c31444f60deb322cb951302 Mon Sep 17 00:00:00 2001 From: Thomas Morin Date: Tue, 23 May 2017 16:55:34 +0200 Subject: [PATCH] bgpvpn-routes-control extension This change defines the bgpvpn-routes-control extension. Beyond the already defined resources for network and router associations with BGPVPNs, this extension defines port associations allowing to control BGPVPN connectivity at the granularity of a neutron port. Additionally, this extension provides features to control what routes are advertised to a BGPVPN, as summarized in neutron_lib/api-ref/source/v2/bgpvpn-overview.inc: With the ``bgpvpn`` extension, when associations between networks or routers and BGVPNs are defined, the routes corresponding to fixed IPs of neutron ports will be advertised to BGPVPNs. For router associations, extra routes of the router ('routes' attribute of a ``router`` resource) may also be advertized to BGPVPNs. To provide more flexibility, the ``bgpvpn-routes-control`` extension provides a way to: - advertise other routes to a BGPVPN, for instances a prefix that is reachable via a neutron port, or routes leaked from another BGPVPN; this is implemented thanks to the ``routes`` attribute of a BGPVPN port association - not advertise the fixed IPs of a neutron port to a BGPVPN, which can be particularly relevant when other IP prefixes are reachable via the port; this is implemented thanks to the ``advertise_fixed_ips`` attribute of a BGPVPN port association - explictly control whether extra routes of a router are to be advertized to a BGPVPN; this is implemented thanks to the ``advertise_extra_routes`` attribute of a BGPVPN router association - optionally control the value of the LOCAL_PREF BGP attribute of advertized routes, for all routes of a BGPVPN (thanks to the ``local_pref`` attribute of a BGPVPN resource) and/or per route (thanks to the ``local_pref`` in a port association route) Partially Implements: blueprint routes-control Change-Id: Ib2cefcb6a345887435b754fbdcff3584329d45d2 --- api-ref/source/v2/bgpvpn-bgpvpns.inc | 20 +- .../source/v2/bgpvpn-network_associations.inc | 2 +- api-ref/source/v2/bgpvpn-overview.inc | 34 ++- .../source/v2/bgpvpn-port_associations.inc | 248 ++++++++++++++++++ .../source/v2/bgpvpn-router_associations.inc | 69 ++++- api-ref/source/v2/index.rst | 1 + api-ref/source/v2/parameters.yaml | 145 +++++++++- .../bgpvpns/bgpvpn-create-response.json | 3 +- .../bgpvpn/bgpvpns/bgpvpn-show-response.json | 3 +- .../bgpvpns/bgpvpn-update-response.json | 3 +- .../bgpvpn/bgpvpns/bgpvpns-list-response.json | 3 +- .../port_association-create-request.json | 11 + .../port_association-create-response.json | 14 + .../port_association-list-response.json | 16 ++ .../port_association-show-response.json | 14 + .../port_association-update-request.json | 13 + .../port_association-update-response.json | 15 ++ .../router_association-create-response.json | 3 +- .../router_association-list-response.json | 3 +- .../router_association-show-response.json | 11 +- .../router_association-update-request.json | 6 + .../router_association-update-response.json | 8 + neutron_lib/api/definitions/__init__.py | 2 + neutron_lib/api/definitions/base.py | 1 + .../api/definitions/bgpvpn_routes_control.py | 168 ++++++++++++ .../definitions/test_bgpvpn_routes_control.py | 25 ++ ...gpvpn-routes-control-51cd95d6ab265cb1.yaml | 8 + 27 files changed, 821 insertions(+), 28 deletions(-) create mode 100644 api-ref/source/v2/bgpvpn-port_associations.inc create mode 100644 api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-request.json create mode 100644 api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-response.json create mode 100644 api-ref/source/v2/samples/bgpvpn/port_associations/port_association-list-response.json create mode 100644 api-ref/source/v2/samples/bgpvpn/port_associations/port_association-show-response.json create mode 100644 api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-request.json create mode 100644 api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-response.json create mode 100644 api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-request.json create mode 100644 api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-response.json create mode 100644 neutron_lib/api/definitions/bgpvpn_routes_control.py create mode 100644 neutron_lib/tests/unit/api/definitions/test_bgpvpn_routes_control.py create mode 100644 releasenotes/notes/bgpvpn-routes-control-51cd95d6ab265cb1.yaml diff --git a/api-ref/source/v2/bgpvpn-bgpvpns.inc b/api-ref/source/v2/bgpvpn-bgpvpns.inc index bb6f21e00..7f7218f3b 100644 --- a/api-ref/source/v2/bgpvpn-bgpvpns.inc +++ b/api-ref/source/v2/bgpvpn-bgpvpns.inc @@ -8,9 +8,11 @@ A new BGPVPN resource is introduced. It contains a set of parameters for a BGP-based VPN. A BGPVPN is created by the admin and given to a tenant who can then associate -it to Networks or Routers. +it to Networks, Routers or Ports (the latter when the ``bgpvpn-routes-control`` +extension is available). -The BGP VPNs API lists, shows details for, creates, updates, and deletes BGP VPNs. +The BGP VPNs API lists, shows details for, creates, updates, and deletes +BGP VPNs. List BGP VPNs ============= @@ -51,6 +53,8 @@ Response Parameters - export_targets: bgpvpn-export_targets-required - networks: bgpvpn-networks-required - routers: bgpvpn-routers-required + - ports: bgpvpn-ports + - local_pref: bgpvpn-local_pref - tenant_id: project_id - project_id: project_id @@ -82,6 +86,7 @@ Request - route_targets: bgpvpn-route_targets - import_targets: bgpvpn-import_targets - export_targets: bgpvpn-export_targets + - local_pref: bgpvpn-local_pref-request - tenant_id: tenant_id-request - project_id: project_id-request - type: bgpvpn-type @@ -106,6 +111,8 @@ Response Parameters - export_targets: bgpvpn-export_targets-required - networks: bgpvpn-networks-required - routers: bgpvpn-routers-required + - ports: bgpvpn-ports + - local_pref: bgpvpn-local_pref - tenant_id: project_id - project_id: project_id @@ -148,6 +155,8 @@ Response Parameters - export_targets: bgpvpn-export_targets-required - networks: bgpvpn-networks-required - routers: bgpvpn-routers-required + - ports: bgpvpn-ports + - local_pref: bgpvpn-local_pref - tenant_id: project_id - project_id: project_id @@ -182,6 +191,7 @@ admin privileges. - route_targets: bgpvpn-route_targets - import_targets: bgpvpn-import_targets - export_targets: bgpvpn-export_targets + - local_pref: bgpvpn-local_pref-request Request Example --------------- @@ -204,6 +214,8 @@ Response Parameters - export_targets: bgpvpn-export_targets-required - networks: bgpvpn-networks-required - routers: bgpvpn-routers-required + - ports: bgpvpn-ports + - local_pref: bgpvpn-local_pref - tenant_id: project_id - project_id: project_id @@ -220,9 +232,9 @@ Delete BGP VPN Deletes a BGP VPN and its network and/or router associations. -Normal response codes: 202 +Normal response codes: 204 -Error response codes: 400, 401, 403, 404 +Error response codes: 401, 403, 404 Request ------- diff --git a/api-ref/source/v2/bgpvpn-network_associations.inc b/api-ref/source/v2/bgpvpn-network_associations.inc index 73433c1f9..e8b01e0fa 100644 --- a/api-ref/source/v2/bgpvpn-network_associations.inc +++ b/api-ref/source/v2/bgpvpn-network_associations.inc @@ -139,7 +139,7 @@ Delete Network Association Deletes a network association. -Normal response codes: 202, 204 +Normal response codes: 204 Error response codes: 400, 401, 403, 404 diff --git a/api-ref/source/v2/bgpvpn-overview.inc b/api-ref/source/v2/bgpvpn-overview.inc index 6c181cfdd..1044bb670 100644 --- a/api-ref/source/v2/bgpvpn-overview.inc +++ b/api-ref/source/v2/bgpvpn-overview.inc @@ -8,8 +8,8 @@ routers with Multiprotocol Label Switching (MPLS) Virtual Private Networks (VPNs) via Border Gateway Protocol (BGP) peering. BGP-MPLS VPNs are commonly provided by telecommunications service providers to customers in addition to or instead of Internet connectivity for Wide -Area Networking. This API enables the interconnection of with these -WANs using *Route Targets* to indicate the desired network(s). +Area Networking. This API enables the interconnection with these +WAN VPNs using *Route Targets* to indicate the desired network(s). On Route Targets ================ @@ -50,6 +50,36 @@ Valid strings for a Route Target or a Route Distinguisher are the following: - <4-byte AS#>:<16bit-number> - <4-byte IPv4>:<16bit-number> +Control of routes advertised to BGPVPNs +======================================= + +With the ``bgpvpn`` extension, when associations between networks or routers +and BGVPNs are defined, the routes corresponding to fixed IPs of neutron ports +will be advertised to BGPVPNs. For router associations, extra routes of the +router ('routes' attribute of a ``router`` resource) may also be advertised +to BGPVPNs. + +To provide more flexibility, the ``bgpvpn-routes-control`` extension provides +a way to: + +- advertise other routes to a BGPVPN, for instances a prefix that is reachable + via a neutron port, or routes leaked from another BGPVPN; this is implemented + thanks to the ``routes`` attribute of a BGPVPN port association + +- not advertise the fixed IPs of a neutron port to a BGPVPN, which can be + particularly relevant when other IP prefixes are reachable via the port; this + is implemented thanks to the ``advertise_fixed_ips`` attribute of a BGPVPN + port association + +- explictly control whether extra routes of a router are to be advertised + to a BGPVPN; this is implemented thanks to the ``advertise_extra_routes`` + attribute of a BGPVPN router association + +- optionally control the value of the LOCAL_PREF BGP attribute of advertised + routes, for all routes of a BGPVPN (thanks to the ``local_pref`` attribute + of a BGPVPN resource) and/or per route (thanks to the ``local_pref`` + in a port association route) + ====================== BGP - MPLS VPN Caveats ====================== diff --git a/api-ref/source/v2/bgpvpn-port_associations.inc b/api-ref/source/v2/bgpvpn-port_associations.inc new file mode 100644 index 000000000..eb3c3bfb7 --- /dev/null +++ b/api-ref/source/v2/bgpvpn-port_associations.inc @@ -0,0 +1,248 @@ +================= +Port Associations +================= + +Port associations are available if the ``bgpvpn-routes-control`` extension +is available. + +Associating or disassociating a BGPVPN to a Port is done by manipulating a +Port association API resource as a sub-resource of the BGPVPN resource. + +The semantic behind this API call is a form of policy-based routing: the +traffic from the given Port will be processed according to dataplane lookups +specific to this Port. This means, in particular that Ports belonging to a +given neutron network will possibly see a different L2 or L3 connectivity if +they have different BGPVPN associations. + +When, a port association is defined for a given port, and at the same time, +a network association is defined for the port's network, both associations are +considered simultaneously active and the connectivity will be established +between the port and the BGPVPNs in both associations. This is true also in +the case where multiple associations are made, and for a router associations +of a router connected to the port's network. + +Port routes +=========== + +Additionally to providing Port-level granularity in the definition of BGPVPN +connectivity, port associations also provide a way to control the +advertisement of routes other than only the fixed IPs of neutron ports. + +So-called static routes are defined as follows: to indicate that prefix +20.1.0.0/16 is reachable via port A and should be advertised +accordingly in BGPVPN X, a port association is defined between port A +and BGPVPN X, with the ``routes`` attribute set to ``[ {'type': 'prefix', +'prefix': '20.1.0.0/16'} ]``. + +Route leaking of the routes of a given BGPVPN into another BGPVPN belonging +to the same tenant, is supported similarily: to indicate that all the prefixes +advertised to BGPVPN Y are reachable via port A (i.e. the routes tagged with at +least an RT belonging to ``route_targets`` or ``import_targets`` of BGPVPN Y), +and that they should be leaked into BGPVPN X, a port association is defined +between port A and BGPVPN X, with the ``routes`` attribute set to +``[ {'type': 'bgpvpn', 'bgpvpn_id': } ]``. + +Control of BGP LOCAL_PREF attribute +=================================== + +The BGP LOCAL_PREF for a specific route can be controlled to take a different +value than the one defined in the BGPVPN ``local_pref`` attribute, by +adding a ``'local_pref': VALUE`` in a route in the ``routes`` attribute (see +example in port association Update request). + +List Port Associations +====================== + +.. rest_method:: GET /v2.0/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations + +Lists port associations for a given BGP VPN. + +Use the ``fields`` query parameter to control which fields are +returned in the response body. Additionally, you can filter results +by using query string parameters. For information, see `Filtering +and Column Selection `__. + +Normal response codes: 200 + +Error response codes: 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - bgpvpn_id: bgpvpn-id-path + - fields: fields + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - port_associations: bgpvpn-port_associations + - id: bgpvpn-port_association_id + - port_id: bgpvpn-port_id + - project_id: project_id + - routes: bgpvpn-routes + - advertise_fixed_ips: bgpvpn-advertise_fixed_ips + +Response Example +---------------- + +.. literalinclude:: samples/bgpvpn/port_associations/port_association-list-response.json + :language: javascript + +Create Port Association +======================= + +.. rest_method:: POST /v2.0/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations + +Creates a port association for a given BGP VPN + +Normal response codes: 201 + +Error response codes: 400, 401, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - bgpvpn_id: bgpvpn-id-path + - port_association: bgpvpn-port_association + - port_id: bgpvpn-port_id + - routes: bgpvpn-routes-request + - advertise_fixed_ips: bgpvpn-advertise_fixed_ips-request + +Request Example +--------------- + +.. literalinclude:: samples/bgpvpn/port_associations/port_association-create-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - port_association: bgpvpn-port_association + - id: bgpvpn-port_association_id + - port_id: bgpvpn-port_id + - project_id: project_id + - routes: bgpvpn-routes + - advertise_fixed_ips: bgpvpn-advertise_fixed_ips + +Response Example +---------------- + +.. literalinclude:: samples/bgpvpn/port_associations/port_association-create-response.json + :language: javascript + +Show Port Association details +============================= + +.. rest_method:: GET /v2.0/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations/{port_association_id} + +Shows details for a port association. + +Normal response codes: 200 + +Error response codes: 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - bgpvpn_id: bgpvpn-id-path + - port_association_id: bgpvpn-port_association_id-path + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - port_association: bgpvpn-port_association + - id: bgpvpn-port_association_id + - port_id: bgpvpn-port_id + - project_id: project_id + - routes: bgpvpn-routes + - advertise_fixed_ips: bgpvpn-advertise_fixed_ips + +Response Example +---------------- + +.. literalinclude:: samples/bgpvpn/port_associations/port_association-show-response.json + :language: javascript + +Update a Port Association +========================= + +.. rest_method:: PUT /v2.0/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations/{port_association_id} + +Updates a port Association. + +Normal response codes: 201 + +Error response codes: 400, 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - bgpvpn_id: bgpvpn-id-path + - port_association_id: bgpvpn-port_association_id-path + - port_association: bgpvpn-port_association + - routes: bgpvpn-routes-request + - advertise_fixed_ips: bgpvpn-advertise_fixed_ips-request + +Request Example +--------------- + +.. literalinclude:: samples/bgpvpn/port_associations/port_association-update-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - port_association: bgpvpn-port_association + - id: bgpvpn-port_association_id + - port_id: bgpvpn-port_id + - project_id: project_id + - routes: bgpvpn-routes + - advertise_fixed_ips: bgpvpn-advertise_fixed_ips + +Response Example +---------------- + +.. literalinclude:: samples/bgpvpn/port_associations/port_association-update-response.json + :language: javascript + + +Delete Port Association +======================= + +.. rest_method:: DELETE /v2.0/bgpvpn/bgpvpns/{bgpvpn_id}/port_associations/{port_association_id} + +Deletes a port association. + +Normal response codes: 204 + +Error response codes: 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - bgpvpn_id: bgpvpn-id-path + - port_association_id: bgpvpn-port_association_id-path + +Response +-------- + +There is no body content for the response of a successful DELETE request. diff --git a/api-ref/source/v2/bgpvpn-router_associations.inc b/api-ref/source/v2/bgpvpn-router_associations.inc index 148656095..fca3b3234 100644 --- a/api-ref/source/v2/bgpvpn-router_associations.inc +++ b/api-ref/source/v2/bgpvpn-router_associations.inc @@ -13,6 +13,22 @@ A said Router can be associated with multiple BGPVPNs. Associating or disassociating a BGPVPN to a Router is done by manipulating a Router association API resource as a sub-resource of the BGPVPN resource: +Advertising router extra routes to a BGPVPN +=========================================== + +The ``bgpvpn-routes-control`` API extension allows to control the +re-advertisement of a router extra routes in a BGPVPN ("extra routes" are +routes defined in the ``routes`` attribute of a router when the ``extraroute`` +extension is available). + +The ``advertise_extra_routes`` attribute can in this case be set on a +router_association: + +- ``true``: the extra routes defined in the ``routes`` attribute of + the router will be advertised to the BGPVPN (default value) +- ``false``: the extra routes defined in the ``routes`` attribute of + the router will **not** be advertised to the BGPVPN + List Router Associations ========================= @@ -134,6 +150,55 @@ Response Example .. literalinclude:: samples/bgpvpn/router_associations/router_association-show-response.json :language: javascript + +Update a Router Association ('bgpvpn-routes-control' extension) +=============================================================== + +.. note:: This operation is only available when the ``bgpvpn-routes-control`` + API extension is enabled. + +.. rest_method:: PUT /v2.0/bgpvpn/bgpvpns/{bgpvpn_id}/router_associations/{router_association_id} + +Updates a router association. + +Normal response codes: 201 + +Error response codes: 400, 401, 403, 404 + +Request +------- + +.. rest_parameters:: parameters.yaml + + - bgpvpn_id: bgpvpn-id-path + - router_association_id: bgpvpn-router_association_id-path + - router_association: bgpvpn-router_association + - advertise_extra_routes: bgpvpn-advertise_extra_routes-request + +Request Example +--------------- + +.. literalinclude:: samples/bgpvpn/router_associations/router_association-update-request.json + :language: javascript + +Response Parameters +------------------- + +.. rest_parameters:: parameters.yaml + + - router_association: bgpvpn-router_association + - id: bgpvpn-router_association_id + - router_id: bgpvpn-router_id + - project_id: project_id + - advertise_extra_routes: bgpvpn-advertise_extra_routes + +Response Example +---------------- + +.. literalinclude:: samples/bgpvpn/router_associations/router_association-update-response.json + :language: javascript + + Delete Router Association ========================== @@ -141,9 +206,9 @@ Delete Router Association Deletes a router association. -Normal response codes: 202 +Normal response codes: 204 -Error response codes: 400, 401, 403, 404 +Error response codes: 401, 403, 404 Request ------- diff --git a/api-ref/source/v2/index.rst b/api-ref/source/v2/index.rst index 6dfa5f514..160e94b7b 100644 --- a/api-ref/source/v2/index.rst +++ b/api-ref/source/v2/index.rst @@ -74,3 +74,4 @@ BGP/MPLS VPN Interconnection .. include:: bgpvpn-bgpvpns.inc .. include:: bgpvpn-network_associations.inc .. include:: bgpvpn-router_associations.inc +.. include:: bgpvpn-port_associations.inc \ No newline at end of file diff --git a/api-ref/source/v2/parameters.yaml b/api-ref/source/v2/parameters.yaml index 018aaed23..595caad31 100644 --- a/api-ref/source/v2/parameters.yaml +++ b/api-ref/source/v2/parameters.yaml @@ -13,6 +13,12 @@ bgpvpn-network_association_id-path: in: path required: true type: string +bgpvpn-port_association_id-path: + description: | + The ID of an association between a port and a BGP VPN. + in: path + required: true + type: string bgpvpn-router_association_id-path: description: | The ID of an association between a router and a BGP VPN. @@ -630,6 +636,35 @@ bgpvpn: in: body required: true type: object +bgpvpn-advertise_extra_routes: + description: | + Boolean flag controlling whether or not the routes specified in the + ``routes`` attribute of the router will be advertised to the BGPVPN. + in: body + required: true + type: boolean +bgpvpn-advertise_extra_routes-request: + description: | + Boolean flag controlling whether or not the routes specified in the + ``routes`` attribute of the router will be advertised to the BGPVPN + (default: true). + in: body + required: false + type: boolean +bgpvpn-advertise_fixed_ips: + description: | + Boolean flag controlling whether or not the fixed IPs of a port will + be advertised to the BGPVPN. + in: body + required: true + type: boolean +bgpvpn-advertise_fixed_ips-request: + description: | + Boolean flag controlling whether or not the fixed IPs of a port will + be advertised to the BGPVPN (default: true). + in: body + required: false + type: boolean bgpvpn-export_targets: description: | Additional Route Targets that will be used for export. @@ -660,6 +695,20 @@ bgpvpn-import_targets-required: in: body required: true type: array +bgpvpn-local_pref: + description: | + The default BGP LOCAL_PREF of routes that will be advertised to the + BGPVPN (unless overriden per-route). + in: body + required: true + type: integer +bgpvpn-local_pref-request: + description: | + The default BGP LOCAL_PREF of routes that will be advertised to the + BGPVPN (unless overriden per-route). + in: body + required: false + type: integer bgpvpn-name: description: | The user meaningful name of the BGP VPN. @@ -674,7 +723,7 @@ bgpvpn-name-required: type: string bgpvpn-network_association: description: | - A ``network_association`` object represents the binding of an MPLS network + A ``network_association`` object represents the binding of a BGP VPN to a Neutron network. in: body required: true @@ -700,25 +749,63 @@ bgpvpn-network_id: type: string bgpvpn-networks: description: | - This read-only list of network IDs reflects the associations defined by Network association API resources. + This read-only list of network IDs reflects the associations defined by + Network association API resources. in: body required: false type: array bgpvpn-networks-required: description: | - This read-only list of network IDs reflects the associations defined by Network association API resources. + This read-only list of network IDs reflects the associations defined by + Network association API resources. + in: body + required: true + type: array +bgpvpn-port_association: + description: | + A ``port_association`` object represents the binding of a BGP VPN + to a Neutron port. + in: body + required: true + type: object +bgpvpn-port_association_id: + description: | + The ID of an association between a port and a BGP VPN. + in: body + required: true + type: string +bgpvpn-port_associations: + description: | + A list of ``port_association`` objects which represent bindings + of MPLS networks to Neutron ports. + in: body + required: true + type: array +bgpvpn-port_id: + description: | + The ID of a Neutron port with which to associate the BGP VPN. + in: body + required: true + type: string +bgpvpn-ports: + description: | + This read-only list of port IDs reflects the associations defined by Port + association API resources (only present if the ``bgpvpn-routes-control`` + API extension is enabled). in: body required: true type: array bgpvpn-route_distinguishers: description: | - List of route distinguisher strings. If this parameter is specified, one of these RDs will be used to advertise VPN routes. + List of route distinguisher strings. If this parameter is specified, one + of these RDs will be used to advertise VPN routes. in: body required: false type: array bgpvpn-route_distinguishers-required: description: | - List of route distinguisher strings. If this parameter is specified, one of these RDs will be used to advertise VPN routes. + List of route distinguisher strings. If this parameter is specified, one + of these RDs will be used to advertise VPN routes. in: body required: true type: array @@ -736,7 +823,7 @@ bgpvpn-route_targets-required: type: array bgpvpn-router_association: description: | - A ``router_association`` object represents the binding of an MPLS network + A ``router_association`` object represents the binding of a BGP VPN to a Neutron router. in: body required: true @@ -762,16 +849,58 @@ bgpvpn-router_id: type: string bgpvpn-routers: description: | - This read-only list of router IDs reflects the associations defined by Router association API resources. + This read-only list of router IDs reflects the associations defined by + Router association API resources. in: body required: false type: array bgpvpn-routers-required: description: | - This read-only list of router IDs reflects the associations defined by Router association API resources. + This read-only list of router IDs reflects the associations defined by + Router association API resources. in: body required: true type: array +bgpvpn-routes: + description: | + List of routes, each route being a dict with at least a ``type`` key, + which can be ``prefix`` or ``bgpvpn``. + + For the ``prefix`` type, the IP prefix (v4 or v6) to advertise + is specified in the ``prefix`` key. + + For the ``bgpvpn`` type, the ``bgpvpn_id`` key specifies the BGPVPN from + which routes will be readvertised with the association port as the + nexthop (any route carrying an RT among ``route_targets`` or + ``import_targets`` of this BGPVPN, will be re-announced toward the RTs + of the associated BGPVPN (``export_targets`` + ``route_targets``), with + their next-hop/label pointing to this port). + + For both types, the ``local_pref`` key can be used to control the + value of the BGP LOCAL_PREF of the routes that will be advertised. + in: body + required: true + type: array +bgpvpn-routes-request: + description: | + List of routes, each route being a dict with at least a ``type`` key, + which can be ``prefix`` or ``bgpvpn``. + + For the ``prefix`` type, the IP prefix (v4 or v6) to advertise + is specified in the ``prefix`` key. + + For the ``bgpvpn`` type, the ``bgpvpn_id`` key specifies the BGPVPN from + which routes will be readvertised with the association port as the + nexthop (any route carrying an RT among ``route_targets`` or + ``import_targets`` of this BGPVPN, will be re-announced toward the RTs + of the associated BGPVPN (``export_targets`` + ``route_targets``), with + their next-hop/label pointing to this port). + + For both types, the ``local_pref`` key can be used to control the + value of the BGP LOCAL_PREF of the routes that will be advertised. + in: body + required: false + type: array bgpvpn-type: description: | Selection of the type of VPN and the technology behind it. Allowed diff --git a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-create-response.json b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-create-response.json index dbecc0642..0a5a9d2a7 100644 --- a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-create-response.json +++ b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-create-response.json @@ -20,6 +20,7 @@ ], "type": "l3", "id": "0f9d472a-908f-40f5-8574-b4e8a63ccbf0", - "networks": [] + "networks": [], + "local_pref": null } } diff --git a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-show-response.json b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-show-response.json index 719e9c948..7a2a073e2 100644 --- a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-show-response.json +++ b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-show-response.json @@ -12,6 +12,7 @@ "route_distinguishers": [], "networks": [ "a4f2b8df-cb42-4893-a333-d0b5c36ade17" - ] + ], + "local_pref": null } } diff --git a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-update-response.json b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-update-response.json index 0d6292f6b..1897e75e5 100644 --- a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-update-response.json +++ b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpn-update-response.json @@ -11,6 +11,7 @@ "route_targets": ["64512:1444"], "type": "l3", "id": "4d627abf-06dd-45ab-920b-8e61422bb984", - "networks": [] + "networks": [], + "local_pref": null } } diff --git a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpns-list-response.json b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpns-list-response.json index a17368369..09d4ceac4 100644 --- a/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpns-list-response.json +++ b/api-ref/source/v2/samples/bgpvpn/bgpvpns/bgpvpns-list-response.json @@ -21,7 +21,8 @@ ], "type": "l3", "id": "0f9d472a-908f-40f5-8574-b4e8a63ccbf0", - "networks": [] + "networks": [], + "local_pref": null } ] } diff --git a/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-request.json b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-request.json new file mode 100644 index 000000000..6e44ffa8f --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-request.json @@ -0,0 +1,11 @@ +{ + "port_association": { + "port_id": "b58a6241-6e49-4b11-87c6-8e0606dde796", + "routes": [ + { + "type": "prefix", + "prefix": "20.1.0.0/16" + } + ] + } +} diff --git a/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-response.json b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-response.json new file mode 100644 index 000000000..80d163d7c --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-create-response.json @@ -0,0 +1,14 @@ +{ + "port_association": { + "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", + "port_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "project_id": "b7549121395844bea941bb92feb3fad9", + "routes": [ + { + "type": "prefix", + "prefix": "20.1.0.0/16" + } + ], + "advertise_fixed_ips": true + } +} diff --git a/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-list-response.json b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-list-response.json new file mode 100644 index 000000000..d067b06e0 --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-list-response.json @@ -0,0 +1,16 @@ +{ + "port_associations": [ + { + "id": "95277be7-a231-4e96-9625-8f9fe41de9d6", + "port_id": "61222227-49eb-4dcc-b2d6-66bbfb2fdd7a", + "project_id": "b7549121395844bea941bb92feb3fad9", + "routes": [ + { + "type": "prefix", + "prefix": "20.1.0.0/16" + } + ], + "advertise_fixed_ips": true + } + ] +} diff --git a/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-show-response.json b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-show-response.json new file mode 100644 index 000000000..80d163d7c --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-show-response.json @@ -0,0 +1,14 @@ +{ + "port_association": { + "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", + "port_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "project_id": "b7549121395844bea941bb92feb3fad9", + "routes": [ + { + "type": "prefix", + "prefix": "20.1.0.0/16" + } + ], + "advertise_fixed_ips": true + } +} diff --git a/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-request.json b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-request.json new file mode 100644 index 000000000..20e313717 --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-request.json @@ -0,0 +1,13 @@ +{ + "port_association": { + "port_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "routes": [ + { + "type": "bgpvpn", + "bgpvpn_id": "180630e3-9eae-4ba7-9939-d5f47966e1f0", + "local_pref": 111 + } + ], + "advertise_fixed_ips": false + } +} diff --git a/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-response.json b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-response.json new file mode 100644 index 000000000..ca260c018 --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/port_associations/port_association-update-response.json @@ -0,0 +1,15 @@ +{ + "port_association": { + "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", + "port_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "project_id": "b7549121395844bea941bb92feb3fad9", + "routes": [ + { + "type": "bgpvpn", + "bgpvpn_id": "180630e3-9eae-4ba7-9939-d5f47966e1f0", + "local_pref": 111 + } + ], + "advertise_fixed_ips": false + } +} diff --git a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-create-response.json b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-create-response.json index 4567d3796..6781f3d07 100644 --- a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-create-response.json +++ b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-create-response.json @@ -3,6 +3,7 @@ "router_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", "tenant_id": "b7549121395844bea941bb92feb3fad9", "project_id": "b7549121395844bea941bb92feb3fad9", - "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3" + "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", + "advertise_extra_routes": true } } diff --git a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-list-response.json b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-list-response.json index 8ddf4083f..f45079ea5 100644 --- a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-list-response.json +++ b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-list-response.json @@ -4,7 +4,8 @@ "router_id": "61222227-49eb-4dcc-b2d6-66bbfb2fdd7a", "tenant_id": "b7549121395844bea941bb92feb3fad9", "project_id": "b7549121395844bea941bb92feb3fad9", - "id": "95277be7-a231-4e96-9625-8f9fe41de9d6" + "id": "95277be7-a231-4e96-9625-8f9fe41de9d6", + "advertise_extra_routes": true } ] } diff --git a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-show-response.json b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-show-response.json index a93b41757..bfafdb943 100644 --- a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-show-response.json +++ b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-show-response.json @@ -1,8 +1,9 @@ { "router_association": { - "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", - "router_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", - "tenant_id": "b7549121395844bea941bb92feb3fad9", - "project_id": "b7549121395844bea941bb92feb3fad9" - } + "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", + "router_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "advertise_extra_routes": true + } } diff --git a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-request.json b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-request.json new file mode 100644 index 000000000..6a312af61 --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-request.json @@ -0,0 +1,6 @@ +{ + "router_association": { + "router_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "advertise_extra_routes": false + } +} diff --git a/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-response.json b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-response.json new file mode 100644 index 000000000..60e591644 --- /dev/null +++ b/api-ref/source/v2/samples/bgpvpn/router_associations/router_association-update-response.json @@ -0,0 +1,8 @@ +{ + "router_association": { + "id": "c63149a0-a0b3-4ca7-aba4-9aaa1b39d7f3", + "project_id": "b7549121395844bea941bb92feb3fad9", + "router_id": "46a1a80b-7c42-4c45-88fd-b531e636969f", + "advertise_extra_routes": false + } +} \ No newline at end of file diff --git a/neutron_lib/api/definitions/__init__.py b/neutron_lib/api/definitions/__init__.py index a97e2eccd..247c5bfa0 100644 --- a/neutron_lib/api/definitions/__init__.py +++ b/neutron_lib/api/definitions/__init__.py @@ -11,6 +11,7 @@ # under the License. from neutron_lib.api.definitions import bgpvpn +from neutron_lib.api.definitions import bgpvpn_routes_control from neutron_lib.api.definitions import data_plane_status from neutron_lib.api.definitions import extra_dhcp_opt from neutron_lib.api.definitions import fip64 @@ -33,6 +34,7 @@ from neutron_lib.api.definitions import trunk_details _ALL_API_DEFINITIONS = { bgpvpn, + bgpvpn_routes_control, data_plane_status, extra_dhcp_opt, fip64, diff --git a/neutron_lib/api/definitions/base.py b/neutron_lib/api/definitions/base.py index 1e189ec4a..d69e21e32 100644 --- a/neutron_lib/api/definitions/base.py +++ b/neutron_lib/api/definitions/base.py @@ -121,6 +121,7 @@ KNOWN_EXTENSIONS = ( 'fwaasrouterinsertion', 'fwaas_v2', 'bgpvpn', # https://git.openstack.org/cgit/openstack/networking-bgpvpn + 'bgpvpn-routes-control', ) KNOWN_KEYWORDS = ( diff --git a/neutron_lib/api/definitions/bgpvpn_routes_control.py b/neutron_lib/api/definitions/bgpvpn_routes_control.py new file mode 100644 index 000000000..9f63b4dd9 --- /dev/null +++ b/neutron_lib/api/definitions/bgpvpn_routes_control.py @@ -0,0 +1,168 @@ +# All rights reserved. +# +# Licensed 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. + +from neutron_lib.api import converters +from neutron_lib.api.definitions import bgpvpn +from neutron_lib.db import constants as db_const + + +# The alias of the extension. +ALIAS = 'bgpvpn-routes-control' + +# The label to lookup the plugin in the plugin directory. It can match the +# alias, as required. +LABEL = ALIAS + +# Whether or not this extension is simply signaling behavior to the user +# or it actively modifies the attribute map (mandatory). +IS_SHIM_EXTENSION = False + +# Whether the extension is marking the adoption of standardattr model for +# legacy resources, or introducing new standardattr attributes. False or +# None if the standardattr model is adopted since the introduction of +# resource extension (mandatory). +# If this is True, the alias for the extension should be prefixed with +# 'standard-attr-'. +IS_STANDARD_ATTR_EXTENSION = False + +# The name of the extension (mandatory). +NAME = 'BGPVPN Routes Control Extension' + +# The description of the extension (mandatory). +DESCRIPTION = "Provides support for controlling routes advertised to a BGPVPN" + +# A timestamp of when the extension was introduced (mandatory). +UPDATED_TIMESTAMP = "2017-05-20T00:00:00-00:00" + +# The specific resources and/or attributes for the extension (optional). +# In case of simple extensions, with single resource, the string constants +# RESOURCE_NAME and COLLECTION_NAME can be used, otherwise string literals +# can be used instead. + +# The name of the resource introduced or being extended (later case) +RESOURCE_NAME = bgpvpn.RESOURCE_NAME + +# The plural for the resource introduced or being extended (later case) +COLLECTION_NAME = bgpvpn.COLLECTION_NAME + +LOCAL_PREF_KEY = 'local_pref' +LOCAL_PREF_RANGE = [0, 2**32-1], # RFC 4271, section 4.3 (p.18) + +RESOURCE_ATTRIBUTE_MAP = { + COLLECTION_NAME: { + 'ports': {'allow_post': False, 'allow_put': False, + 'is_visible': True, + 'enforce_policy': True}, + LOCAL_PREF_KEY: { + 'allow_post': True, 'allow_put': True, + 'is_visible': True, + 'default': None, + 'validate': {'type:range': LOCAL_PREF_RANGE}, + 'enforce_policy': True} + } +} + +PORT_ASSOCIATION = 'port_association' +PORT_ASSOCIATIONS = 'port_associations' + +ROUTES = 'routes' + +PREFIX_TYPE = 'prefix' +BGPVPN_TYPE = 'bgpvpn' +ROUTE_TYPES = [PREFIX_TYPE, BGPVPN_TYPE] + +ADV_FIXED_IPS = 'advertise_fixed_ips' + +TYPE = 'type' + +PREFIX = 'prefix' +BGPVPN_ID = 'bgpvpn_id' + +ADV_EXTRA_ROUTES = 'advertise_extra_routes' + +LOCAL_PREF_KEY_SPEC = {'type:range': LOCAL_PREF_RANGE, + 'required': False} + +ROUTE_SPECS = EXTRA_DHCP_OPT_KEY_SPECS = [ + {'type': {'type:values': [PREFIX_TYPE], + 'required': True}, + 'prefix': {'type:subnet': None, + 'required': True}, + LOCAL_PREF_KEY: LOCAL_PREF_KEY_SPEC, + }, + {'type': {'type:values': [BGPVPN_TYPE], + 'required': True}, + 'bgpvpn_id': {'type:uuid': None, + 'required': True}, + LOCAL_PREF_KEY: LOCAL_PREF_KEY_SPEC, + }, +] + +SUB_RESOURCE_ATTRIBUTE_MAP = { + PORT_ASSOCIATIONS: { + 'parent': { + 'collection_name': COLLECTION_NAME, + 'member_name': RESOURCE_NAME}, + 'parameters': { + 'id': {'allow_post': False, 'allow_put': False, + 'validate': {'type:uuid': None}, + 'is_visible': True, + 'primary_key': True}, + 'project_id': {'allow_post': True, 'allow_put': False, + 'validate': { + 'type:string': db_const.PROJECT_ID_FIELD_SIZE}, + 'required_by_policy': True, + 'is_visible': True, + 'enforce_policy': True}, + 'port_id': {'allow_post': True, 'allow_put': False, + 'validate': {'type:uuid': None}, + 'is_visible': True, + 'enforce_policy': True}, + ROUTES: {'allow_post': True, 'allow_put': False, + 'default': [], + 'convert_list_to': converters.convert_kvp_list_to_dict, + 'validate': { + 'type:list_of_any_key_specs_or_none': ROUTE_SPECS + }, + 'enforce_policy': True, + 'is_visible': True}, + ADV_FIXED_IPS: {'allow_post': True, 'allow_put': True, + 'default': True, + 'convert_to': converters.convert_to_boolean, + 'is_visible': True}, + }, + }, + bgpvpn.ROUTER_ASSOCIATIONS: { + 'parent': {'collection_name': COLLECTION_NAME, + 'member_name': RESOURCE_NAME}, + 'parameters': { + ADV_EXTRA_ROUTES: {'allow_post': True, 'allow_put': True, + 'default': True, + 'convert_to': converters.convert_to_boolean, + 'is_visible': True}, + } + } +} + + +ACTION_MAP = { +} + +ACTION_STATUS = {} + +REQUIRED_EXTENSIONS = [ + bgpvpn.ALIAS +] + +OPTIONAL_EXTENSIONS = [] diff --git a/neutron_lib/tests/unit/api/definitions/test_bgpvpn_routes_control.py b/neutron_lib/tests/unit/api/definitions/test_bgpvpn_routes_control.py new file mode 100644 index 000000000..e44d1bbc2 --- /dev/null +++ b/neutron_lib/tests/unit/api/definitions/test_bgpvpn_routes_control.py @@ -0,0 +1,25 @@ +# +# Licensed 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. + +from neutron_lib.api.definitions import bgpvpn +from neutron_lib.api.definitions import bgpvpn_routes_control +from neutron_lib.tests.unit.api.definitions import base + + +class BgpvpnRoutesControlDefinitionTestCase(base.DefinitionBaseTestCase): + + extension_module = bgpvpn_routes_control + extension_resources = (bgpvpn.COLLECTION_NAME,) + extension_attributes = ('ports', 'routes', 'advertise_fixed_ips', + 'advertise_extra_routes', 'local_pref') + extension_subresources = ('port_associations', 'router_associations') diff --git a/releasenotes/notes/bgpvpn-routes-control-51cd95d6ab265cb1.yaml b/releasenotes/notes/bgpvpn-routes-control-51cd95d6ab265cb1.yaml new file mode 100644 index 000000000..b2b407c01 --- /dev/null +++ b/releasenotes/notes/bgpvpn-routes-control-51cd95d6ab265cb1.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + The ``bgpvpn-routes-control`` API extension is introduced to enrich the + base ``bgpvpn`` extension. It allows to control BGPVPN connectivity at + the granularity of a port and the advertisement into a BGPVPN of routes + corresponding to destination reachable via a given port (static routes, + BGPVPN route leaking).