Push router,peer events to BGP l3 agent extension

Signed-off-by: Manu B <manu.b@est.tech>
Change-Id: Ied48acd5c552515b1a5e16da6fd01c07ba974dd5
This commit is contained in:
Manu B 2021-07-27 09:39:46 +00:00
parent ad4489feab
commit e49047dc5d
5 changed files with 248 additions and 6 deletions

View File

@ -0,0 +1,53 @@
# Copyright (c) 2019 Red Hat, Inc.
#
# 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.objects import common_types
from oslo_versionedobjects import fields as obj_fields
from neutron.db.models import conntrack_helper as models
from neutron.objects import base
from neutron_dynamic_routing.db import bgp_db
@base.NeutronObjectRegistry.register
class BgpSpeakerRouterAssociation(base.NeutronDbObject):
# Version 1.0: Initial version
VERSION = '1.0'
db_model = bgp_db.BgpSpeakerRouterAssociation
fields = {
'id': common_types.UUIDField(),
'bgp_speaker_id': common_types.UUIDField(),
'router_id': common_types.UUIDField(),
'advertise_extra_routes': obj_fields.BooleanField(),
'status': obj_fields.StringField(),
}
primary_keys = ['id']
@base.NeutronObjectRegistry.register
class BgpSpeakerPeerAssociation(base.NeutronDbObject):
# Version 1.0: Initial version
VERSION = '1.0'
db_model = bgp_db.BgpSpeakerPeerAssociation
fields = {
'id': common_types.UUIDField(),
'bgp_speaker_id': common_types.UUIDField(),
'peer_id': common_types.UUIDField(),
'status': obj_fields.StringField(),
}
primary_keys = ['id']

View File

@ -0,0 +1,127 @@
# Copyright 2021 OpenStack Foundation
# 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 import rpc as n_rpc
from neutron_lib.agent import l3_extension
from neutron.api.rpc.callbacks import resources
from neutron.api.rpc.handlers import resources_rpc
from oslo_log import log as logging
from neutron_dynamic_routing.objects import bgp_associations as assoc_objects
from neutron_dynamic_routing.services.bgp.agent.l3 import l3_agent_bgp_plugin_api
LOG = logging.getLogger(__name__)
BGP_ROUTER_ASSOC = assoc_objects.BgpSpeakerRouterAssociation.obj_name()
BGP_PEER_ASSOC = assoc_objects.BgpSpeakerPeerAssociation.obj_name()
class BgpAgentExtension(l3_extension.L3AgentExtension):
SUPPORTED_RESOURCE_TYPES = [BGP_ROUTER_ASSOC, BGP_PEER_ASSOC]
def initialize(self, connection, driver_type):
LOG.debug("Initializing BgpL3AgentExtension")
resources.register_resource_class(
assoc_objects.BgpSpeakerRouterAssociation)
resources.register_resource_class(
assoc_objects.BgpSpeakerPeerAssociation)
self._register_rpc_consumers()
self.rpc_plugin = l3_agent_bgp_plugin_api.BgpL3ExtPluginApi(
bgp_consts.BGP_PLUGIN)
LOG.debug("Initialized BgpaasAgentExtension")
def _register_rpc_consumers(self):
LOG.debug("Reg RPC consumers BgpaasAgentExtension")
registry.register(self._handle_router_notification, BGP_ROUTER_ASSOC)
registry.register(self._handle_peer_notification, BGP_PEER_ASSOC)
self._register_router_consumers()
self._register_peer_consumers()
LOG.debug("Registered RPC consumers BgpaasAgentExtension")
def _register_router_consumers(self):
self._connection = n_rpc.Connection()
endpoints = [resources_rpc.ResourcesPushRpcCallback()]
topic = resources_rpc.resource_type_versioned_topic(BGP_ROUTER_ASSOC)
self._connection.create_consumer(topic, endpoints, fanout=True)
self._connection.consume_in_threads()
def _register_peer_consumers(self):
self._connection_peer = n_rpc.Connection()
endpoints = [resources_rpc.ResourcesPushRpcCallback()]
topic_peer = resources_rpc.resource_type_versioned_topic(
BGP_PEER_ASSOC)
self._connection_peer.create_consumer(topic_peer, endpoints,
fanout=True)
self._connection_peer.consume_in_threads()
def consume_api(self, agent_api):
self.agent_api = agent_api
def _handle_router_notification(self, context, resource_type,
router_assocs, event_type):
LOG.debug('Received router associated push event %s for resource %s,'
'with router associations %s', event_type, resource_type,
router_assocs)
for router_assoc in router_assocs:
if event_type == rpc_events.CREATED:
#TODO invoke call to create BGP speaker
pass
elif event_type == rpc_events.DELETED:
#TODO invoke call to delete BGP speaker
pass
def _handle_peer_notification(self, context, resource_type,
peer_assocs, event_type):
LOG.debug('Received peer associated push event %s for resource %s,'
'with peer associations %s', event_type, resource_type,
peer_assocs)
for peer_assoc in peer_assocs:
if event_type == rpc_events.CREATED:
#TODO invoke call to create BGP speaker
pass
elif event_type == rpc_events.DELETED:
#TODO invoke call to delete BGP speaker
pass
def add_router(self, context, data):
"""Handle a router add event.
Called on router create.
:param context: RPC context.
:param data: Router data.
"""
pass
def update_router(self, context, data):
"""Handle a router update event.
Called on router update.
:param context: RPC context.
:param data: Router data.
"""
pass
def delete_router(self, context, data):
"""Handle a router delete event.
:param context: RPC context.
:param data: Router data.
"""
pass
def ha_state_change(self, context, data):
pass

View File

@ -0,0 +1,45 @@
# Copyright 2021 OpenStack Foundation
# 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 import rpc as n_rpc
import oslo_messaging
class BgpL3ExtPluginApi(object):
"""Agent side of the bgp l3 agent ext RPC API.
This class implements the client side of an rpc interface.
The server side of this interface can be found in
api.rpc.handlers.bgp_speaker_rpc.BgpSpeakerRpcCallback.
API version history:
1.0 - Initial version.
"""
def __init__(self, topic):
target = oslo_messaging.Target(topic=topic, version='1.0')
self.client = n_rpc.get_client(target)
def get_bgp_speaker_info(self, context, bgp_speaker_id):
"""Make a remote process call to retrieve a BGP speaker info."""
cctxt = self.client.prepare()
return cctxt.call(context, 'get_bgp_speaker_info',
bgp_speaker_id=bgp_speaker_id)
def get_bgp_peer_info(self, context, bgp_peer_id):
"""Make a remote process call to retrieve a BGP peer info."""
cctxt = self.client.prepare()
return cctxt.call(context, 'get_bgp_peer_info',
bgp_peer_id=bgp_peer_id)

View File

@ -14,6 +14,7 @@
from netaddr import IPAddress
from neutron.api.rpc.callbacks import resources as resources_callback
from neutron_lib.api.definitions import portbindings
from neutron_lib.api.definitions import bgp_associations
from neutron_lib.callbacks import events
@ -35,6 +36,7 @@ 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.objects import bgp_associations as assoc_objects
from neutron_dynamic_routing.services.bgp.common import constants as bgp_consts
PLUGIN_NAME = bgp_ext.BGP_EXT_ALIAS + '_svc_plugin'
@ -224,9 +226,16 @@ class BgpPlugin(service_base.ServicePluginBase,
def create_bgp_speaker_router_association(self, context, bgp_speaker_id,
router_association):
return super(BgpPlugin, self).create_bgp_speaker_router_association(
context, bgp_speaker_id,
router_association)
assoc_info = super(BgpPlugin, self)\
.create_bgp_speaker_router_association(context,
bgp_speaker_id,
router_association)
router_assoc_obj = assoc_objects.BgpSpeakerRouterAssociation(
context,
**assoc_info)
self.push_api.push(context, [router_assoc_obj], rpc_events.CREATED)
return assoc_info
def delete_bgp_speaker_router_association(self, context, id,
bgp_speaker_id):
@ -252,9 +261,15 @@ class BgpPlugin(service_base.ServicePluginBase,
def create_bgp_speaker_peer_association(self, context, bgp_speaker_id,
peer_association):
return super(BgpPlugin, self).create_bgp_speaker_peer_association(
context, bgp_speaker_id,
peer_association)
assoc_info = super(BgpPlugin, self)\
.create_bgp_speaker_peer_association(context, bgp_speaker_id,
peer_association)
peer_assoc_obj = assoc_objects.BgpSpeakerPeerAssociation(
context,
**assoc_info)
self.push_api.push(context, [peer_assoc_obj], rpc_events.CREATED)
return assoc_info
def delete_bgp_speaker_peer_association(self, context, id,
bgp_speaker_id):

View File

@ -37,3 +37,5 @@ neutron.policies =
neutron-dynamic-routing = neutron_dynamic_routing.policies:list_rules
neutron.service_plugins =
bgp = neutron_dynamic_routing.services.bgp.bgp_plugin:BgpPlugin
neutron.agent.l3.extensions =
bgp-ext = neutron_dynamic_routing.services.bgp.agent.l3.bgp_extension:BgpAgentExtension