Use bgp api-def from neutron-lib
As neutron-dynamic-routing is a Neutron stadium project the api-def and the api-ref should be in neutron-lib. Change-Id: Idccc69f025a0d1ec0453d13a7d81b94e3a15149d Depends-On: https://review.opendev.org/c/openstack/neutron-lib/+/788322
This commit is contained in:
parent
7245c228c2
commit
c021b106d9
@ -25,467 +25,5 @@
|
||||
API
|
||||
===
|
||||
|
||||
Introduction
|
||||
------------
|
||||
Neutron dynamic routing project adds the support for dynamic routing protocols
|
||||
in neutron. Using the ReST interface, a cloud administrator can define routing
|
||||
peers and advertise neutron routes outside the OpenStack domain.
|
||||
|
||||
.. note::
|
||||
|
||||
Currently, only the support for BGP dynamic routing protocol is available.
|
||||
|
||||
Data Model
|
||||
----------
|
||||
New data models are defined for supporting routing protocols. Below models are defined for
|
||||
different protocols.
|
||||
|
||||
BGP
|
||||
~~~
|
||||
|
||||
BGP Speaker
|
||||
+++++++++++
|
||||
* ``id``
|
||||
The uuid of BGP Speaker.
|
||||
* ``name``
|
||||
The name of BGP Speaker.
|
||||
* ``local_as``
|
||||
The local AS value, ranges from 1 to 65535.
|
||||
* ``ip_version``
|
||||
The ip address version for BGP Speaker. 4 by default.
|
||||
* ``peers``
|
||||
The remote peer connection which supports BGP.
|
||||
* ``networks``
|
||||
The tenant networks connected to the BGP Speaker.
|
||||
* ``advertise_floating_ip_host_routes``
|
||||
Whether to enable or disable the advertisement of floating ip host routes by
|
||||
the BGP Speaker. True by default.
|
||||
* ``advertise_tenant_networks``
|
||||
Whether to enable or disable the advertisement of tenant network routes by
|
||||
the BGP Speaker. True by default.
|
||||
|
||||
BGP Peer
|
||||
++++++++
|
||||
* ``id``
|
||||
The uuid of BGP peer.
|
||||
* ``name``
|
||||
The name of BGP peer.
|
||||
* ``peer_ip``
|
||||
The IP address of BGP peer.
|
||||
* ``remote_as``
|
||||
The remote AS value, ranges from 1 to 65535.
|
||||
* ``auth_type``
|
||||
The authentication algorithm. Supported algorithms: none and md5, none by
|
||||
default.
|
||||
* ``password``
|
||||
The authentication password for the specified authentication type.
|
||||
|
||||
|
||||
ReST Interface
|
||||
--------------
|
||||
Different ReST interface are exposed for realizing different dynamic protocol
|
||||
functionality.
|
||||
|
||||
.. note::
|
||||
|
||||
Only an administrator have the access to the exposed API's.
|
||||
|
||||
|
||||
BGP
|
||||
~~~
|
||||
|
||||
BGP Speaker
|
||||
+++++++++++
|
||||
|
||||
Create
|
||||
''''''
|
||||
Issue a ``POST`` request to ``/v2.0/bgp-speakers`` with following JSON-encoded
|
||||
data to create a BGP Speaker: ::
|
||||
|
||||
{
|
||||
"bgp_speaker":{
|
||||
"ip_version":4,
|
||||
"local_as":"1000",
|
||||
"name":"bgp-speaker"
|
||||
}
|
||||
}
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_speaker":{
|
||||
"peers":[
|
||||
],
|
||||
"name":"bgp-speaker",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"local_as":1000,
|
||||
"advertise_tenant_networks":true,
|
||||
"networks":[
|
||||
],
|
||||
"ip_version":4,
|
||||
"advertise_floating_ip_host_routes":true,
|
||||
"id":"5e08db80-db77-4b5c-a56d-dbca0b284f2c"
|
||||
}
|
||||
}
|
||||
|
||||
Return code: 201
|
||||
|
||||
List
|
||||
''''
|
||||
Issue a ``GET`` request to ``/v2.0/bgp-speakers`` to retrieve this list of available
|
||||
BGP Speakers. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_speakers":[
|
||||
{
|
||||
"peers":[
|
||||
],
|
||||
"name":"bgp-speaker-1",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"local_as":1001,
|
||||
"advertise_tenant_networks":true,
|
||||
"networks":[
|
||||
],
|
||||
"ip_version":4,
|
||||
"advertise_floating_ip_host_routes":true,
|
||||
"id":"5e08db80-db77-4b5c-a56d-dbca0b284f2c"
|
||||
},
|
||||
{
|
||||
"peers":[
|
||||
],
|
||||
"name":"bgp-speaker",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"local_as":1000,
|
||||
"advertise_tenant_networks":true,
|
||||
"networks":[
|
||||
],
|
||||
"ip_version":4,
|
||||
"advertise_floating_ip_host_routes":true,
|
||||
"id":"b759b2a1-27f4-4a6b-bb61-f2c9a22c9902"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
Show
|
||||
''''
|
||||
Issue a ``GET`` request to ``/v2.0/bgp-speakers/<bgp-speaker-id>`` to retrieve the
|
||||
detail about a specific BGP Speaker. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_speaker":{
|
||||
"peers":[
|
||||
],
|
||||
"name":"bgp-speaker",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"local_as":1000,
|
||||
"advertise_tenant_networks":true,
|
||||
"networks":[
|
||||
],
|
||||
"ip_version":4,
|
||||
"advertise_floating_ip_host_routes":true,
|
||||
"id":"b759b2a1-27f4-4a6b-bb61-f2c9a22c9902"
|
||||
}
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
Update
|
||||
''''''
|
||||
Issue ``PUT`` request to ``/v2.0/bgp-speakers/<bgp-speaker-id>`` to update a
|
||||
specific BGP Speaker. Following attributes can be updated.
|
||||
|
||||
* ``name``
|
||||
The name of BGP Speaker.
|
||||
* ``advertise_floating_ip_host_routes``
|
||||
Whether to enable or disable the advertisement of floating ip host routes by
|
||||
the BGP Speaker. True by default.
|
||||
* ``advertise_tenant_networks``
|
||||
Whether to enable or disable the advertisement of tenant network routes by
|
||||
the BGP Speaker. True by default.
|
||||
|
||||
Delete
|
||||
''''''
|
||||
Issue ``DELETE`` request to ``/v2.0/bgp-speakers/<bgp-speaker-id>`` to delete
|
||||
a specific BGP Speaker. ::
|
||||
|
||||
No response body
|
||||
|
||||
Return code: 204
|
||||
|
||||
BGP Peer
|
||||
++++++++
|
||||
|
||||
Create
|
||||
''''''
|
||||
Issue a ``POST`` request to ``/v2.0/bgp-peers`` with following JSON-encoded data
|
||||
to create a BGP peer: ::
|
||||
|
||||
{
|
||||
"bgp_peer":{
|
||||
"auth_type":"none",
|
||||
"remote_as":"1001",
|
||||
"name":"bgp-peer",
|
||||
"peer_ip":"10.0.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_peer":{
|
||||
"auth_type":"none",
|
||||
"remote_as":"1001",
|
||||
"name":"bgp-peer",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"peer_ip":"10.0.0.3",
|
||||
"id":"a7193581-a31c-4ea5-8218-b3052758461f"
|
||||
}
|
||||
}
|
||||
|
||||
Return code: 201
|
||||
|
||||
List
|
||||
''''
|
||||
Issue a ``GET`` request to ``/v2.0/bgp-peers`` to retrieve the list of available
|
||||
BGP peers. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_peers":[
|
||||
{
|
||||
"auth_type":"none",
|
||||
"remote_as":1001,
|
||||
"name":"bgp-peer",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"peer_ip":"10.0.0.3",
|
||||
"id":"a7193581-a31c-4ea5-8218-b3052758461f"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
Show
|
||||
''''
|
||||
Issue a ``GET`` request to ``/v2.0/bgp-peers/<bgp-peer-id>`` to retrieve the detail about a
|
||||
specific BGP peer. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_peer":{
|
||||
"auth_type":"none",
|
||||
"remote_as":1001,
|
||||
"name":"bgp-peer",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"peer_ip":"10.0.0.3",
|
||||
"id":"a7193581-a31c-4ea5-8218-b3052758461f"
|
||||
}
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
Update
|
||||
''''''
|
||||
Issue ``PUT`` request to ``/v2.0/bgp-peers/<bgp-peer-id>`` to update
|
||||
a specific BGP peer. Following attributes can be updated.
|
||||
|
||||
* ``name``
|
||||
The name of BGP peer.
|
||||
* ``password``
|
||||
The authentication password.
|
||||
|
||||
|
||||
Delete
|
||||
''''''
|
||||
Issue ``DELETE`` request to ``/v2.0/bgp-peers/<bgp-peer-id>`` to delete
|
||||
a specific BGP peer. ::
|
||||
|
||||
No response body
|
||||
|
||||
Return code: 204
|
||||
|
||||
|
||||
BGP Speaker and Peer binding
|
||||
++++++++++++++++++++++++++++
|
||||
|
||||
Add BGP Peer to a BGP Speaker
|
||||
'''''''''''''''''''''''''''''
|
||||
Issue a ``PUT`` request to ``/v2.0/bgp-speakers/<bgp-speaker-id>/add-bgp-peer``
|
||||
to bind the BGP peer to the specified BGP Seaker with following JSON-encoded data: ::
|
||||
|
||||
{
|
||||
"bgp_peer_id":"a7193581-a31c-4ea5-8218-b3052758461f"
|
||||
}
|
||||
|
||||
Response body: ::
|
||||
|
||||
{
|
||||
"bgp_peer_id":"a7193581-a31c-4ea5-8218-b3052758461f"
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
Remove BGP Peer from a BGP Speaker
|
||||
''''''''''''''''''''''''''''''''''
|
||||
Issue a ``DELETE`` request with following data to ``/v2.0/bgp-speakers/<bgp-speaker-id>/remove-bgp-peer``
|
||||
to unbind the BGP peer: ::
|
||||
|
||||
{
|
||||
"bgp_peer_id":"a7193581-a31c-4ea5-8218-b3052758461f"
|
||||
}
|
||||
|
||||
No response body
|
||||
|
||||
Return code: 200
|
||||
|
||||
|
||||
BGP Speaker and Network binding
|
||||
+++++++++++++++++++++++++++++++
|
||||
|
||||
Add Network to a BGP Speaker
|
||||
''''''''''''''''''''''''''''
|
||||
Issue a ``PUT`` request with following data to ``/v2.0/bgp-speakers/<bgp-speaker-id>/add_gateway_network``
|
||||
to add a network to the specified BGP speaker: ::
|
||||
|
||||
{
|
||||
"network_id":"f2269b61-6755-4174-8f64-5e318617b204"
|
||||
}
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"network_id":"f2269b61-6755-4174-8f64-5e318617b204"
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
Delete Network from a BGP Speaker
|
||||
'''''''''''''''''''''''''''''''''
|
||||
Issue a ``DELETE`` request with following data to ``/v2.0/bgp-speakers/<bgp-speaker-id>/remove_gateway_network``
|
||||
to delete a network from a specified BGP speaker. ::
|
||||
|
||||
No response body
|
||||
|
||||
Return code: 200
|
||||
|
||||
BGP Speaker Advertised Routes
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
List routes advertised by a BGP Speaker
|
||||
'''''''''''''''''''''''''''''''''''''''
|
||||
Issue ``GET`` request to ```/v2.0/bgp-speakers/<bgp-speaker-id>/get_advertised_routes``
|
||||
to list all routes advertised by the specified BGP Speaker. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"advertised_routes":[
|
||||
{
|
||||
"cidr":"192.168.10.0/24",
|
||||
"nexthop":"10.0.0.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
BGP Speaker and Dynamic Routing Agent interaction
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Add BGP Speaker to a Dynamic Routing Agent
|
||||
''''''''''''''''''''''''''''''''''''''''''
|
||||
Issue a ``POST`` request to ``/v2.0/agents/<bgp-agent-id>/bgp-drinstances`` to
|
||||
add a BGP Speaker to the specified dynamic routing agent. The following is
|
||||
the request body: ::
|
||||
|
||||
{
|
||||
"bgp_speaker_id": "5639072c-49eb-480a-9f11-953386589bc8"
|
||||
}
|
||||
|
||||
No response body
|
||||
|
||||
Return code: 201
|
||||
|
||||
List BGP speakers hosted by a Dynamic Routing Agent
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Issue a ``GET`` request to ``/v2.0/agents/<bgp-dragent-id>/bgp-drinstances`` to
|
||||
list all BGP Seakers hosted on the specified dynamic routing agent. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"bgp_speakers":[
|
||||
{
|
||||
"peers":[
|
||||
],
|
||||
"name":"bgp-speaker",
|
||||
"tenant_id":"34a6e17a48cf414ebc890367bf42266b",
|
||||
"local_as":1000,
|
||||
"advertise_tenant_networks":true,
|
||||
"networks":[
|
||||
],
|
||||
"ip_version":4,
|
||||
"advertise_floating_ip_host_routes":true,
|
||||
"id":"b759b2a1-27f4-4a6b-bb61-f2c9a22c9902"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
List Dynamic Routing Agents hosting a specific BGP Speaker
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Issue a ``GET`` request to ``/v2.0/bgp-speakers/<bgp-speaker-id>/bgp-dragents``
|
||||
to list all BGP dynamic agents which are hosting the specified BGP Speaker. ::
|
||||
|
||||
Response body:
|
||||
|
||||
{
|
||||
"agents":[
|
||||
{
|
||||
"binary":"neutron-bgp-dragent",
|
||||
"description":null,
|
||||
"admin_state_up":true,
|
||||
"heartbeat_timestamp":"2016-05-17 03:05:12",
|
||||
"availability_zone":null,
|
||||
"alive":true,
|
||||
"topic":"bgp_dragent",
|
||||
"host":"yangyubj-virtual-machine",
|
||||
"agent_type":"BGP dynamic routing agent",
|
||||
"resource_versions":{
|
||||
},
|
||||
"created_at":"2016-05-09 07:38:00",
|
||||
"started_at":"2016-05-11 09:06:13",
|
||||
"id":"af216618-29d3-4ee7-acab-725bdc90e614",
|
||||
"configurations":{
|
||||
"advertise_routes":0,
|
||||
"bgp_peers":0,
|
||||
"bgp_speakers":1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Return code: 200
|
||||
|
||||
|
||||
Delete BGP Speaker from a Dynamic Routing Agent
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Issue a ``DELETE`` request to ``/v2.0/agents/<bgp-agent-id>/bgp-drinstances/<bgp-speaker-id>``
|
||||
to delete the BGP Speaker hosted by the specified dynamic routing agent. ::
|
||||
|
||||
No response body
|
||||
|
||||
Return code: 204
|
||||
|
||||
Reference
|
||||
---------
|
||||
None
|
||||
The reference of the OpenStack neutron-dynamic-routing API is found at
|
||||
https://docs.openstack.org/api-ref/network/#bgp-dynamic-routing.
|
||||
|
@ -13,11 +13,10 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from neutron_lib.api.definitions import bgp as bgp_ext
|
||||
from neutron_lib.plugins import directory
|
||||
import oslo_messaging
|
||||
|
||||
from neutron_dynamic_routing.extensions import bgp as bgp_ext
|
||||
|
||||
|
||||
class BgpSpeakerRpcCallback(object):
|
||||
"""BgpDrAgent RPC callback in plugin implementations.
|
||||
@ -37,7 +36,7 @@ class BgpSpeakerRpcCallback(object):
|
||||
@property
|
||||
def plugin(self):
|
||||
if not hasattr(self, '_plugin'):
|
||||
self._plugin = directory.get_plugin(bgp_ext.BGP_EXT_ALIAS)
|
||||
self._plugin = directory.get_plugin(bgp_ext.ALIAS)
|
||||
return self._plugin
|
||||
|
||||
def get_bgp_speaker_info(self, context, bgp_speaker_id):
|
||||
|
@ -26,6 +26,7 @@ from neutron.objects import subnet as subnet_obj
|
||||
from neutron.objects import subnetpool as subnetpool_obj
|
||||
from neutron.plugins.ml2 import models as ml2_models
|
||||
|
||||
from neutron_lib.api.definitions import bgp as bgp_ext
|
||||
from neutron_lib.api import validators
|
||||
from neutron_lib import constants as lib_consts
|
||||
from neutron_lib.db import api as db_api
|
||||
@ -43,7 +44,7 @@ from sqlalchemy.orm import aliased
|
||||
from sqlalchemy.orm import exc as sa_exc
|
||||
|
||||
from neutron_dynamic_routing._i18n import _
|
||||
from neutron_dynamic_routing.extensions import bgp as bgp_ext
|
||||
from neutron_dynamic_routing.extensions import bgp
|
||||
|
||||
|
||||
DEVICE_OWNER_ROUTER_GW = lib_consts.DEVICE_OWNER_ROUTER_GW
|
||||
@ -208,7 +209,7 @@ class BgpDbMixin(object):
|
||||
bgp_speaker_id,
|
||||
network_id)
|
||||
except oslo_db_exc.DBDuplicateEntry:
|
||||
raise bgp_ext.BgpSpeakerNetworkBindingError(
|
||||
raise bgp.BgpSpeakerNetworkBindingError(
|
||||
network_id=network_id,
|
||||
bgp_speaker_id=bgp_speaker_id)
|
||||
return {'network_id': network_id}
|
||||
@ -231,7 +232,7 @@ class BgpDbMixin(object):
|
||||
auth_type = ri.get('auth_type')
|
||||
password = ri.get('password')
|
||||
if auth_type == 'md5' and not password:
|
||||
raise bgp_ext.InvalidBgpPeerMd5Authentication()
|
||||
raise bgp.InvalidBgpPeerMd5Authentication()
|
||||
|
||||
with db_api.CONTEXT_WRITER.using(context):
|
||||
res_keys = ['tenant_id', 'name', 'remote_as', 'peer_ip',
|
||||
@ -276,7 +277,7 @@ class BgpDbMixin(object):
|
||||
bgp_peer_db = self._get_bgp_peer(context, bgp_peer_id)
|
||||
if ((bp.get('password') is not None) and
|
||||
(bgp_peer_db['auth_type'] == 'none')):
|
||||
raise bgp_ext.BgpPeerNotAuthenticated(bgp_peer_id=bgp_peer_id)
|
||||
raise bgp.BgpPeerNotAuthenticated(bgp_peer_id=bgp_peer_id)
|
||||
bgp_peer_db.update(bp)
|
||||
|
||||
bgp_peer_dict = self._make_bgp_peer_dict(bgp_peer_db)
|
||||
@ -287,7 +288,7 @@ class BgpDbMixin(object):
|
||||
return model_query.get_by_id(context, BgpSpeaker,
|
||||
bgp_speaker_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpSpeakerNotFound(id=bgp_speaker_id)
|
||||
raise bgp.BgpSpeakerNotFound(id=bgp_speaker_id)
|
||||
|
||||
def _get_bgp_speaker_ids_by_router(self, context, router_id):
|
||||
with db_api.CONTEXT_READER.using(context):
|
||||
@ -340,13 +341,13 @@ class BgpDbMixin(object):
|
||||
bgp_speaker = model_query.get_by_id(context, BgpSpeaker,
|
||||
bgp_speaker_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpSpeakerNotFound(id=bgp_speaker_id)
|
||||
raise bgp.BgpSpeakerNotFound(id=bgp_speaker_id)
|
||||
|
||||
try:
|
||||
bgp_peer = model_query.get_by_id(context, BgpPeer,
|
||||
bgp_peer_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpPeerNotFound(id=bgp_peer_id)
|
||||
raise bgp.BgpPeerNotFound(id=bgp_peer_id)
|
||||
|
||||
peers = self._get_bgp_peers_by_bgp_speaker_binding(context,
|
||||
bgp_speaker_id)
|
||||
@ -358,7 +359,7 @@ class BgpDbMixin(object):
|
||||
def _validate_peer_ips(self, bgp_speaker_id, current_peers, new_peer):
|
||||
for peer in current_peers:
|
||||
if peer.peer_ip == new_peer.peer_ip:
|
||||
raise bgp_ext.DuplicateBgpPeerIpException(
|
||||
raise bgp.DuplicateBgpPeerIpException(
|
||||
bgp_peer_id=new_peer.id,
|
||||
peer_ip=new_peer.peer_ip,
|
||||
bgp_speaker_id=bgp_speaker_id)
|
||||
@ -372,7 +373,7 @@ class BgpDbMixin(object):
|
||||
bgp_speaker_id,
|
||||
bgp_peer_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpSpeakerPeerNotAssociated(
|
||||
raise bgp.BgpSpeakerPeerNotAssociated(
|
||||
bgp_peer_id=bgp_peer_id,
|
||||
bgp_speaker_id=bgp_speaker_id)
|
||||
context.session.delete(binding)
|
||||
@ -386,7 +387,7 @@ class BgpDbMixin(object):
|
||||
bgp_speaker = model_query.get_by_id(context, BgpSpeaker,
|
||||
bgp_speaker_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpSpeakerNotFound(id=bgp_speaker_id)
|
||||
raise bgp.BgpSpeakerNotFound(id=bgp_speaker_id)
|
||||
|
||||
try:
|
||||
network = model_query.get_by_id(context, models_v2.Network,
|
||||
@ -410,7 +411,7 @@ class BgpDbMixin(object):
|
||||
bgp_speaker_id,
|
||||
network_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpSpeakerNetworkNotAssociated(
|
||||
raise bgp.BgpSpeakerNetworkNotAssociated(
|
||||
network_id=network_id,
|
||||
bgp_speaker_id=bgp_speaker_id)
|
||||
context.session.delete(binding)
|
||||
@ -433,7 +434,7 @@ class BgpDbMixin(object):
|
||||
try:
|
||||
return model_query.get_by_id(context, BgpPeer, bgp_peer_id)
|
||||
except sa_exc.NoResultFound:
|
||||
raise bgp_ext.BgpPeerNotFound(id=bgp_peer_id)
|
||||
raise bgp.BgpPeerNotFound(id=bgp_peer_id)
|
||||
|
||||
def _get_bgp_speaker_peer_binding(self, context,
|
||||
bgp_speaker_id, bgp_peer_id):
|
||||
|
@ -14,107 +14,13 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from neutron_lib.api import converters as n_conv
|
||||
from neutron_lib.api import extensions
|
||||
from neutron_lib.db import constants as db_const
|
||||
from neutron_lib.api.definitions import bgp as bgp_api_def
|
||||
from neutron_lib.api import extensions as api_ext
|
||||
from neutron_lib import exceptions as n_exc
|
||||
|
||||
from neutron.api.v2 import resource_helper as rh
|
||||
|
||||
from neutron_dynamic_routing._i18n import _
|
||||
from neutron_dynamic_routing.services.bgp.common import constants as bgp_consts
|
||||
|
||||
BGP_EXT_ALIAS = 'bgp'
|
||||
BGP_SPEAKER_RESOURCE_NAME = 'bgp-speaker'
|
||||
BGP_SPEAKER_BODY_KEY_NAME = 'bgp_speaker'
|
||||
BGP_PEER_BODY_KEY_NAME = 'bgp_peer'
|
||||
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
BGP_SPEAKER_RESOURCE_NAME + 's': {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True, 'primary_key': True},
|
||||
'name': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string': db_const.NAME_FIELD_SIZE},
|
||||
'is_visible': True, 'default': ''},
|
||||
'local_as': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:range': (bgp_consts.MIN_ASNUM,
|
||||
bgp_consts.MAX_ASNUM)},
|
||||
'is_visible': True, 'default': None,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': False},
|
||||
'ip_version': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:values': [4, 6]},
|
||||
'is_visible': True, 'default': None,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': False},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': False,
|
||||
'validate': {
|
||||
'type:string': db_const.PROJECT_ID_FIELD_SIZE},
|
||||
'is_visible': True},
|
||||
'peers': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid_list': None},
|
||||
'is_visible': True, 'default': [],
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': True},
|
||||
'networks': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid_list': None},
|
||||
'is_visible': True, 'default': [],
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': True},
|
||||
'advertise_floating_ip_host_routes': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'convert_to': n_conv.convert_to_boolean,
|
||||
'validate': {'type:boolean': None},
|
||||
'is_visible': True, 'default': True,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': True},
|
||||
'advertise_tenant_networks': {
|
||||
'allow_post': True,
|
||||
'allow_put': True,
|
||||
'convert_to': n_conv.convert_to_boolean,
|
||||
'validate': {'type:boolean': None},
|
||||
'is_visible': True, 'default': True,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': True},
|
||||
},
|
||||
'bgp-peers': {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True, 'primary_key': True},
|
||||
'name': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string': db_const.NAME_FIELD_SIZE},
|
||||
'is_visible': True, 'default': ''},
|
||||
'peer_ip': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {'type:ip_address': None},
|
||||
'is_visible': True},
|
||||
'remote_as': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:range': (bgp_consts.MIN_ASNUM,
|
||||
bgp_consts.MAX_ASNUM)},
|
||||
'is_visible': True, 'default': None,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': False},
|
||||
'auth_type': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {'type:values':
|
||||
bgp_consts.SUPPORTED_AUTH_TYPES},
|
||||
'is_visible': True},
|
||||
'password': {'allow_post': True, 'allow_put': True,
|
||||
'required_by_policy': True,
|
||||
'validate': {'type:string_or_none': None},
|
||||
'is_visible': False,
|
||||
'default': None},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': False,
|
||||
'validate': {
|
||||
'type:string': db_const.PROJECT_ID_FIELD_SIZE},
|
||||
'is_visible': True}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Dynamic Routing Exceptions
|
||||
@ -164,48 +70,16 @@ class NetworkNotBoundForIpVersion(NetworkNotBound):
|
||||
"BgpSpeaker.")
|
||||
|
||||
|
||||
class Bgp(extensions.ExtensionDescriptor):
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "Neutron BGP Dynamic Routing Extension"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return BGP_EXT_ALIAS
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return("Discover and advertise routes for Neutron prefixes "
|
||||
"dynamically via BGP")
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2016-05-10T15:37:00-00:00"
|
||||
class Bgp(api_ext.APIExtensionDescriptor):
|
||||
api_definition = bgp_api_def
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
plural_mappings = rh.build_plural_mappings(
|
||||
{}, RESOURCE_ATTRIBUTE_MAP)
|
||||
action_map = {BGP_SPEAKER_RESOURCE_NAME:
|
||||
{'add_bgp_peer': 'PUT',
|
||||
'remove_bgp_peer': 'PUT',
|
||||
'add_gateway_network': 'PUT',
|
||||
'remove_gateway_network': 'PUT',
|
||||
'get_advertised_routes': 'GET'}}
|
||||
{}, bgp_api_def.RESOURCE_ATTRIBUTE_MAP)
|
||||
exts = rh.build_resource_info(plural_mappings,
|
||||
RESOURCE_ATTRIBUTE_MAP,
|
||||
BGP_EXT_ALIAS,
|
||||
action_map=action_map)
|
||||
bgp_api_def.RESOURCE_ATTRIBUTE_MAP,
|
||||
bgp_api_def.ALIAS,
|
||||
action_map=bgp_api_def.ACTION_MAP)
|
||||
|
||||
return exts
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return RESOURCE_ATTRIBUTE_MAP
|
||||
else:
|
||||
return {}
|
||||
|
||||
def update_attributes_map(self, attributes):
|
||||
super(Bgp, self).update_attributes_map(
|
||||
attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)
|
||||
|
@ -10,63 +10,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api.definitions import bgp_4byte_asn as api_def
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
|
||||
from neutron_dynamic_routing.extensions import bgp as bgp_ext
|
||||
from neutron_dynamic_routing.services.bgp.common import constants as bgp_consts
|
||||
|
||||
|
||||
BGP_4BYTE_ASN_EXT_ALIAS = 'bgp_4byte_asn'
|
||||
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
'bgp-speakers': {
|
||||
'local_as': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:range': (bgp_consts.MIN_ASNUM,
|
||||
bgp_consts.MAX_4BYTE_ASNUM)},
|
||||
'is_visible': True, 'default': None,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': False}
|
||||
},
|
||||
'bgp-peers': {
|
||||
'remote_as': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:range': (bgp_consts.MIN_ASNUM,
|
||||
bgp_consts.MAX_4BYTE_ASNUM)},
|
||||
'is_visible': True, 'default': None,
|
||||
'required_by_policy': False,
|
||||
'enforce_policy': False}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Bgp_4byte_asn(api_extensions.ExtensionDescriptor):
|
||||
class Bgp_4byte_asn(api_extensions.APIExtensionDescriptor):
|
||||
"""Extension class supporting bgp 4-byte AS numbers.
|
||||
"""
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "BGP 4-byte AS numbers"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return BGP_4BYTE_ASN_EXT_ALIAS
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Support bgp 4-byte AS numbers"
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2017-09-07T00:00:00-00:00"
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
return []
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return RESOURCE_ATTRIBUTE_MAP
|
||||
else:
|
||||
return {}
|
||||
|
||||
def get_required_extensions(self):
|
||||
return [bgp_ext.BGP_EXT_ALIAS]
|
||||
api_definition = api_def
|
||||
|
@ -18,6 +18,8 @@ import abc
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import resource
|
||||
from neutron import wsgi
|
||||
from neutron_lib.api.definitions import bgp as bgp_ext
|
||||
from neutron_lib.api.definitions import bgp_dragentscheduler as api_def
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
from neutron_lib.api import faults
|
||||
from neutron_lib import exceptions as n_exc
|
||||
@ -27,17 +29,10 @@ from oslo_log import log as logging
|
||||
import webob
|
||||
|
||||
from neutron_dynamic_routing._i18n import _, _LE
|
||||
from neutron_dynamic_routing.extensions import bgp as bgp_ext
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
BGP_DRAGENT_SCHEDULER_EXT_ALIAS = 'bgp_dragent_scheduler'
|
||||
BGP_DRINSTANCE = 'bgp-drinstance'
|
||||
BGP_DRINSTANCES = BGP_DRINSTANCE + 's'
|
||||
BGP_DRAGENT = 'bgp-dragent'
|
||||
BGP_DRAGENTS = BGP_DRAGENT + 's'
|
||||
|
||||
|
||||
class DrAgentInvalid(agent_exc.AgentNotFound):
|
||||
message = _("BgpDrAgent %(id)s is invalid or has been disabled.")
|
||||
@ -61,7 +56,7 @@ class BgpSpeakerRescheduleError(n_exc.Conflict):
|
||||
class BgpDrSchedulerController(wsgi.Controller):
|
||||
"""Schedule BgpSpeaker for a BgpDrAgent"""
|
||||
def get_plugin(self):
|
||||
plugin = directory.get_plugin(bgp_ext.BGP_EXT_ALIAS)
|
||||
plugin = directory.get_plugin(bgp_ext.ALIAS)
|
||||
if not plugin:
|
||||
LOG.error(_LE('No plugin for BGP routing registered'))
|
||||
msg = _('The resource could not be found.')
|
||||
@ -88,7 +83,7 @@ class BgpDrSchedulerController(wsgi.Controller):
|
||||
|
||||
class BgpDrAgentController(wsgi.Controller):
|
||||
def get_plugin(self):
|
||||
plugin = directory.get_plugin(bgp_ext.BGP_EXT_ALIAS)
|
||||
plugin = directory.get_plugin(bgp_ext.ALIAS)
|
||||
if not plugin:
|
||||
LOG.error(_LE('No plugin for BGP routing registered'))
|
||||
msg = _('The resource could not be found.')
|
||||
@ -96,29 +91,16 @@ class BgpDrAgentController(wsgi.Controller):
|
||||
return plugin
|
||||
|
||||
def index(self, request, **kwargs):
|
||||
plugin = directory.get_plugin(bgp_ext.BGP_EXT_ALIAS)
|
||||
plugin = directory.get_plugin(bgp_ext.ALIAS)
|
||||
return plugin.list_dragent_hosting_bgp_speaker(
|
||||
request.context, kwargs['bgp_speaker_id'])
|
||||
|
||||
|
||||
class Bgp_dragentscheduler(api_extensions.ExtensionDescriptor):
|
||||
class Bgp_dragentscheduler(api_extensions.APIExtensionDescriptor):
|
||||
"""Extension class supporting Dynamic Routing scheduler.
|
||||
"""
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "BGP Dynamic Routing Agent Scheduler"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return BGP_DRAGENT_SCHEDULER_EXT_ALIAS
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Schedules BgpSpeakers on BgpDrAgent"
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2015-07-30T10:00:00-00:00"
|
||||
api_definition = api_def
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
@ -129,20 +111,17 @@ class Bgp_dragentscheduler(api_extensions.ExtensionDescriptor):
|
||||
|
||||
controller = resource.Resource(BgpDrSchedulerController(),
|
||||
faults.FAULT_MAP)
|
||||
exts.append(extensions.ResourceExtension(BGP_DRINSTANCES,
|
||||
exts.append(extensions.ResourceExtension(api_def.BGP_DRINSTANCES,
|
||||
controller, parent))
|
||||
|
||||
parent = dict(member_name="bgp_speaker",
|
||||
collection_name="bgp-speakers")
|
||||
controller = resource.Resource(BgpDrAgentController(),
|
||||
faults.FAULT_MAP)
|
||||
exts.append(extensions.ResourceExtension(BGP_DRAGENTS,
|
||||
exts.append(extensions.ResourceExtension(api_def.BGP_DRAGENTS,
|
||||
controller, parent))
|
||||
return exts
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
return {}
|
||||
|
||||
|
||||
class BgpDrSchedulerPluginBase(object, metaclass=abc.ABCMeta):
|
||||
"""REST API to operate BGP dynamic routing agent scheduler.
|
||||
@ -153,7 +132,7 @@ class BgpDrSchedulerPluginBase(object, metaclass=abc.ABCMeta):
|
||||
return "Neutron BGP dynamic routing scheduler Plugin"
|
||||
|
||||
def get_plugin_type(self):
|
||||
return bgp_ext.BGP_EXT_ALIAS
|
||||
return bgp_ext.ALIAS
|
||||
|
||||
@abc.abstractmethod
|
||||
def add_bgp_speaker_to_dragent(self, context, agent_id, speaker_id):
|
||||
|
@ -14,6 +14,9 @@
|
||||
|
||||
from netaddr import IPAddress
|
||||
|
||||
from neutron_lib.api.definitions import bgp as bgp_ext
|
||||
from neutron_lib.api.definitions import bgp_4byte_asn
|
||||
from neutron_lib.api.definitions import bgp_dragentscheduler as dras_ext
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib.callbacks import events
|
||||
from neutron_lib.callbacks import registry
|
||||
@ -31,12 +34,9 @@ from neutron_dynamic_routing.api.rpc.callbacks import resources as dr_resources
|
||||
from neutron_dynamic_routing.api.rpc.handlers import bgp_speaker_rpc as bs_rpc
|
||||
from neutron_dynamic_routing.db import bgp_db
|
||||
from neutron_dynamic_routing.db import bgp_dragentscheduler_db
|
||||
from neutron_dynamic_routing.extensions import bgp as bgp_ext
|
||||
from neutron_dynamic_routing.extensions import bgp_4byte_asn
|
||||
from neutron_dynamic_routing.extensions import bgp_dragentscheduler as dras_ext
|
||||
from neutron_dynamic_routing.services.bgp.common import constants as bgp_consts
|
||||
|
||||
PLUGIN_NAME = bgp_ext.BGP_EXT_ALIAS + '_svc_plugin'
|
||||
PLUGIN_NAME = bgp_ext.ALIAS + '_svc_plugin'
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -44,9 +44,9 @@ class BgpPlugin(service_base.ServicePluginBase,
|
||||
bgp_db.BgpDbMixin,
|
||||
bgp_dragentscheduler_db.BgpDrAgentSchedulerDbMixin):
|
||||
|
||||
supported_extension_aliases = [bgp_ext.BGP_EXT_ALIAS,
|
||||
dras_ext.BGP_DRAGENT_SCHEDULER_EXT_ALIAS,
|
||||
bgp_4byte_asn.BGP_4BYTE_ASN_EXT_ALIAS]
|
||||
supported_extension_aliases = [bgp_ext.ALIAS,
|
||||
dras_ext.ALIAS,
|
||||
bgp_4byte_asn.ALIAS]
|
||||
|
||||
def __init__(self):
|
||||
super(BgpPlugin, self).__init__()
|
||||
@ -57,7 +57,7 @@ class BgpPlugin(service_base.ServicePluginBase,
|
||||
self.add_periodic_dragent_status_check()
|
||||
|
||||
def get_plugin_type(self):
|
||||
return bgp_ext.BGP_EXT_ALIAS
|
||||
return bgp_ext.ALIAS
|
||||
|
||||
def get_plugin_description(self):
|
||||
"""returns string description of the plugin."""
|
||||
|
@ -16,10 +16,10 @@
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests import base
|
||||
from neutron_lib.api.definitions import bgp as bgp_ext
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron_dynamic_routing.api.rpc.handlers import bgp_speaker_rpc
|
||||
from neutron_dynamic_routing.extensions import bgp as bgp_ext
|
||||
|
||||
|
||||
class TestBgpSpeakerRpcCallback(base.BaseTestCase):
|
||||
@ -27,7 +27,7 @@ class TestBgpSpeakerRpcCallback(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestBgpSpeakerRpcCallback, self).setUp()
|
||||
self.plugin = mock.Mock()
|
||||
directory.add_plugin(bgp_ext.BGP_EXT_ALIAS, self.plugin)
|
||||
directory.add_plugin(bgp_ext.ALIAS, self.plugin)
|
||||
self.callback = bgp_speaker_rpc.BgpSpeakerRpcCallback()
|
||||
|
||||
def test_get_bgp_speaker_info(self):
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api.definitions import bgp
|
||||
from neutron_lib import context
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
@ -23,7 +24,6 @@ from neutron.tests.unit.extensions import test_agent
|
||||
|
||||
from neutron_dynamic_routing.db import bgp_db
|
||||
from neutron_dynamic_routing.db import bgp_dragentscheduler_db as bgp_dras_db
|
||||
from neutron_dynamic_routing.extensions import bgp
|
||||
from neutron_dynamic_routing.extensions import bgp_dragentscheduler as bgp_dras_ext # noqa
|
||||
from neutron_dynamic_routing.tests.common import helpers
|
||||
from neutron_dynamic_routing.tests.unit.db import test_bgp_db
|
||||
@ -190,12 +190,12 @@ class BgpDrPluginSchedulerTests(test_db_base_plugin.NeutronDbPluginV2TestCase,
|
||||
plugin = ('neutron_dynamic_routing.tests.unit.db.'
|
||||
'test_bgp_dragentscheduler_db.TestBgpDrSchedulerPlugin')
|
||||
if not service_plugins:
|
||||
service_plugins = {bgp.BGP_EXT_ALIAS:
|
||||
service_plugins = {bgp.ALIAS:
|
||||
'neutron_dynamic_routing.services.bgp.'
|
||||
'bgp_plugin.BgpPlugin'}
|
||||
|
||||
ext_mgr = ext_mgr or BgpDrSchedulerTestExtensionManager()
|
||||
super(BgpDrPluginSchedulerTests, self).setUp(
|
||||
plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
|
||||
self.bgp_plugin = directory.get_plugin(bgp.BGP_EXT_ALIAS)
|
||||
self.bgp_plugin = directory.get_plugin(bgp.ALIAS)
|
||||
self.context = context.get_admin_context()
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- The API definitions of ``neutron-dynamic-routing``, ``bgp``,
|
||||
``bgp_4byte_asn`` and ``bgp_dragent_scheduler``, are now available
|
||||
in ``neutron_lib.api.definitions``.
|
Loading…
Reference in New Issue
Block a user