TVD+BGP: adapt the nsx bgp plugin to be used in TVD

The BGP plugin and driver used for NSX-v should be used for TVD as well.
This plugin suports only NSX-V under the TVD plugin.

Change-Id: I95be40fe0f58f0ff2b06590400d708ee95294b82
This commit is contained in:
Adit Sarfaty 2017-12-24 11:30:13 +02:00
parent fcac238cb0
commit 2c21c61709
3 changed files with 232 additions and 64 deletions

View File

@ -20,27 +20,46 @@ from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources from neutron_lib.callbacks import resources
from neutron_lib import context as n_context from neutron_lib import context as n_context
from neutron_lib import exceptions as n_exc
from neutron_lib.plugins import directory
from neutron_lib.services import base as service_base from neutron_lib.services import base as service_base
from oslo_log import log as logging from oslo_log import log as logging
from vmware_nsx.common import locking from vmware_nsx.common import locking
from vmware_nsx.common import nsxv_constants from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import db as nsx_db
from vmware_nsx.db import nsxv_db from vmware_nsx.db import nsxv_db
from vmware_nsx.extensions import edge_service_gateway_bgp_peer as ext_esg from vmware_nsx.extensions import edge_service_gateway_bgp_peer as ext_esg
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.services.dynamic_routing.nsx_v import driver as nsxv_driver from vmware_nsx.services.dynamic_routing.nsx_v import driver as nsxv_driver
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
PLUGIN_NAME = bgp_ext.BGP_EXT_ALIAS + '_nsx_svc_plugin' PLUGIN_NAME = bgp_ext.BGP_EXT_ALIAS + '_nsx_svc_plugin'
class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin): class NSXBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
"""BGP service plugin for NSX-V as well as TVD plugins.
Currently only the nsx-v is supported. other plugins will be refused.
"""
supported_extension_aliases = [bgp_ext.BGP_EXT_ALIAS, supported_extension_aliases = [bgp_ext.BGP_EXT_ALIAS,
ext_esg.ESG_BGP_PEER_EXT_ALIAS] ext_esg.ESG_BGP_PEER_EXT_ALIAS]
def __init__(self): def __init__(self):
super(NSXvBgpPlugin, self).__init__() super(NSXBgpPlugin, self).__init__()
self.nsxv_driver = nsxv_driver.NSXvBgpDriver(self) self._core_plugin = directory.get_plugin()
# initialize the supported drivers (currently only NSX-v)
self.drivers = {}
try:
self.drivers[projectpluginmap.NsxPlugins.NSX_V] = (
nsxv_driver.NSXvBgpDriver(self))
except Exception:
# No driver found
LOG.warning("NSXBgpPlugin failed to initialize the NSX-V driver")
self.drivers[projectpluginmap.NsxPlugins.NSX_V] = None
self._register_callbacks() self._register_callbacks()
def get_plugin_name(self): def get_plugin_name(self):
@ -74,33 +93,78 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
nsxv_constants.SERVICE_EDGE, nsxv_constants.SERVICE_EDGE,
events.BEFORE_DELETE) events.BEFORE_DELETE)
def _get_driver_by_project(self, context, project):
# Check if the current project id has a matching driver
# Currently only NSX-V is supported
if self._core_plugin.is_tvd_plugin():
mapping = nsx_db.get_project_plugin_mapping(
context.session, project)
if mapping:
plugin_type = mapping['plugin']
else:
msg = (_("Couldn't find the plugin project %s is "
"using") % project)
raise n_exc.InvalidInput(error_message=msg)
# make sure the core plugin is supported
if not self._core_plugin.get_plugin_by_type(plugin_type):
msg = (_("Plugin %(plugin)s for project %(project)s is not "
"supported by the core plugin") % {
'project': project,
'plugin': plugin_type})
raise n_exc.InvalidInput(error_message=msg)
else:
plugin_type = self._core_plugin.plugin_type()
if not self.drivers.get(plugin_type):
msg = (_("Project %(project)s with plugin %(plugin)s has no "
"support for dynamic routing") % {
'project': project,
'plugin': plugin_type})
raise n_exc.InvalidInput(error_message=msg)
return self.drivers[plugin_type]
def _get_driver_by_speaker(self, context, bgp_speaker_id):
try:
speaker = self.get_bgp_speaker(context, bgp_speaker_id)
except Exception:
msg = _("BGP speaker %s could not be found") % bgp_speaker_id
raise n_exc.BadRequest(resource=bgp_ext.BGP_SPEAKER_RESOURCE_NAME,
msg=msg)
return self._get_driver_by_project(context, speaker['tenant_id'])
def create_bgp_speaker(self, context, bgp_speaker): def create_bgp_speaker(self, context, bgp_speaker):
self.nsxv_driver.create_bgp_speaker(context, bgp_speaker) driver = self._get_driver_by_project(
return super(NSXvBgpPlugin, self).create_bgp_speaker(context, context, bgp_speaker['bgp_speaker']['tenant_id'])
driver.create_bgp_speaker(context, bgp_speaker)
return super(NSXBgpPlugin, self).create_bgp_speaker(context,
bgp_speaker) bgp_speaker)
def update_bgp_speaker(self, context, bgp_speaker_id, bgp_speaker): def update_bgp_speaker(self, context, bgp_speaker_id, bgp_speaker):
driver = self._get_driver_by_speaker(context, bgp_speaker_id)
with locking.LockManager.get_lock(str(bgp_speaker_id)): with locking.LockManager.get_lock(str(bgp_speaker_id)):
self.nsxv_driver.update_bgp_speaker(context, bgp_speaker_id, driver.update_bgp_speaker(context, bgp_speaker_id, bgp_speaker)
bgp_speaker)
# TBD(roeyc): rolling back changes on edges base class call failed. # TBD(roeyc): rolling back changes on edges base class call failed.
return super(NSXvBgpPlugin, self).update_bgp_speaker( return super(NSXBgpPlugin, self).update_bgp_speaker(
context, bgp_speaker_id, bgp_speaker) context, bgp_speaker_id, bgp_speaker)
def delete_bgp_speaker(self, context, bgp_speaker_id): def delete_bgp_speaker(self, context, bgp_speaker_id):
driver = self._get_driver_by_speaker(context, bgp_speaker_id)
with locking.LockManager.get_lock(str(bgp_speaker_id)): with locking.LockManager.get_lock(str(bgp_speaker_id)):
self.nsxv_driver.delete_bgp_speaker(context, bgp_speaker_id) driver.delete_bgp_speaker(context, bgp_speaker_id)
super(NSXvBgpPlugin, self).delete_bgp_speaker(context, super(NSXBgpPlugin, self).delete_bgp_speaker(context,
bgp_speaker_id) bgp_speaker_id)
def _add_esg_peer_info(self, context, peer): def _add_esg_peer_info(self, context, peer):
# TODO(asarfaty): only if nsxv driver, or do it in the driver itself
binding = nsxv_db.get_nsxv_bgp_peer_edge_binding(context.session, binding = nsxv_db.get_nsxv_bgp_peer_edge_binding(context.session,
peer['id']) peer['id'])
if binding: if binding:
peer['esg_id'] = binding['edge_id'] peer['esg_id'] = binding['edge_id']
def get_bgp_peer(self, context, bgp_peer_id, fields=None): def get_bgp_peer(self, context, bgp_peer_id, fields=None):
peer = super(NSXvBgpPlugin, self).get_bgp_peer(context, peer = super(NSXBgpPlugin, self).get_bgp_peer(context,
bgp_peer_id, fields) bgp_peer_id, fields)
if not fields or 'esg_id' in fields: if not fields or 'esg_id' in fields:
self._add_esg_peer_info(context, peer) self._add_esg_peer_info(context, peer)
@ -108,16 +172,26 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
def get_bgp_peers_by_bgp_speaker(self, context, def get_bgp_peers_by_bgp_speaker(self, context,
bgp_speaker_id, fields=None): bgp_speaker_id, fields=None):
ret = super(NSXvBgpPlugin, self).get_bgp_peers_by_bgp_speaker( ret = super(NSXBgpPlugin, self).get_bgp_peers_by_bgp_speaker(
context, bgp_speaker_id, fields=fields) context, bgp_speaker_id, fields=fields)
if fields is None or 'esg_id' in fields: if fields is None or 'esg_id' in fields:
for peer in ret: for peer in ret:
self._add_esg_peer_info(context, peer) self._add_esg_peer_info(context, peer)
return ret return ret
def _get_driver_by_peer(self, context, bgp_peer_id):
try:
peer = self.get_bgp_peer(context, bgp_peer_id)
except Exception:
raise bgp_ext.BgpPeerNotFound(id=bgp_peer_id)
return self._get_driver_by_project(context, peer['tenant_id'])
def create_bgp_peer(self, context, bgp_peer): def create_bgp_peer(self, context, bgp_peer):
self.nsxv_driver.create_bgp_peer(context, bgp_peer) driver = self._get_driver_by_project(
peer = super(NSXvBgpPlugin, self).create_bgp_peer(context, bgp_peer) context, bgp_peer['bgp_peer']['tenant_id'])
driver.create_bgp_peer(context, bgp_peer)
peer = super(NSXBgpPlugin, self).create_bgp_peer(context, bgp_peer)
# TODO(asarfaty): only if nsxv driver, or do it in the driver itself
esg_id = bgp_peer['bgp_peer'].get('esg_id') esg_id = bgp_peer['bgp_peer'].get('esg_id')
if esg_id: if esg_id:
nsxv_db.add_nsxv_bgp_peer_edge_binding(context.session, peer['id'], nsxv_db.add_nsxv_bgp_peer_edge_binding(context.session, peer['id'],
@ -126,14 +200,16 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
return peer return peer
def update_bgp_peer(self, context, bgp_peer_id, bgp_peer): def update_bgp_peer(self, context, bgp_peer_id, bgp_peer):
super(NSXvBgpPlugin, self).update_bgp_peer(context, driver = self._get_driver_by_peer(context, bgp_peer_id)
super(NSXBgpPlugin, self).update_bgp_peer(context,
bgp_peer_id, bgp_peer) bgp_peer_id, bgp_peer)
self.nsxv_driver.update_bgp_peer(context, bgp_peer_id, bgp_peer) driver.update_bgp_peer(context, bgp_peer_id, bgp_peer)
return self.get_bgp_peer(context, bgp_peer_id) return self.get_bgp_peer(context, bgp_peer_id)
def delete_bgp_peer(self, context, bgp_peer_id): def delete_bgp_peer(self, context, bgp_peer_id):
driver = self._get_driver_by_peer(context, bgp_peer_id)
bgp_peer_info = {'bgp_peer_id': bgp_peer_id} bgp_peer_info = {'bgp_peer_id': bgp_peer_id}
bgp_speaker_ids = self.nsxv_driver._get_bgp_speakers_by_bgp_peer( bgp_speaker_ids = driver._get_bgp_speakers_by_bgp_peer(
context, bgp_peer_id) context, bgp_peer_id)
for speaker_id in bgp_speaker_ids: for speaker_id in bgp_speaker_ids:
try: try:
@ -141,42 +217,74 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
except bgp_ext.BgpSpeakerPeerNotAssociated: except bgp_ext.BgpSpeakerPeerNotAssociated:
LOG.debug("Couldn't find bgp speaker %s peer binding while " LOG.debug("Couldn't find bgp speaker %s peer binding while "
"deleting bgp peer %s", speaker_id, bgp_peer_id) "deleting bgp peer %s", speaker_id, bgp_peer_id)
super(NSXvBgpPlugin, self).delete_bgp_peer(context, bgp_peer_id) super(NSXBgpPlugin, self).delete_bgp_peer(context, bgp_peer_id)
def add_bgp_peer(self, context, bgp_speaker_id, bgp_peer_info): def add_bgp_peer(self, context, bgp_speaker_id, bgp_peer_info):
# speaker & peer must belong to the same driver
if not bgp_peer_info.get('bgp_peer_id'):
msg = _("bgp_peer_id must be specified")
raise n_exc.BadRequest(resource='bgp-peer', msg=msg)
peer_driver = self._get_driver_by_peer(
context, bgp_peer_info['bgp_peer_id'])
speaker_driver = self._get_driver_by_speaker(context, bgp_speaker_id)
if peer_driver != speaker_driver:
msg = _("Peer and Speaker must belong to the same plugin")
raise n_exc.InvalidInput(error_message=msg)
with locking.LockManager.get_lock(str(bgp_speaker_id)): with locking.LockManager.get_lock(str(bgp_speaker_id)):
self.nsxv_driver.add_bgp_peer(context, speaker_driver.add_bgp_peer(context,
bgp_speaker_id, bgp_peer_info) bgp_speaker_id, bgp_peer_info)
return super(NSXvBgpPlugin, self).add_bgp_peer(context, return super(NSXBgpPlugin, self).add_bgp_peer(context,
bgp_speaker_id, bgp_speaker_id,
bgp_peer_info) bgp_peer_info)
def remove_bgp_peer(self, context, bgp_speaker_id, bgp_peer_info): def remove_bgp_peer(self, context, bgp_speaker_id, bgp_peer_info):
driver = self._get_driver_by_speaker(context, bgp_speaker_id)
with locking.LockManager.get_lock(str(bgp_speaker_id)): with locking.LockManager.get_lock(str(bgp_speaker_id)):
ret = super(NSXvBgpPlugin, self).remove_bgp_peer( ret = super(NSXBgpPlugin, self).remove_bgp_peer(
context, bgp_speaker_id, bgp_peer_info) context, bgp_speaker_id, bgp_peer_info)
self.nsxv_driver.remove_bgp_peer(context, driver.remove_bgp_peer(context, bgp_speaker_id, bgp_peer_info)
bgp_speaker_id, bgp_peer_info)
return ret return ret
def _validate_network_plugin(
self, context, network_info,
plugin_type=projectpluginmap.NsxPlugins.NSX_V):
"""Make sure the network belongs to the NSX0-V plugin"""
if not network_info.get('network_id'):
msg = _("network_id must be specified")
raise n_exc.BadRequest(resource=bgp_ext.BGP_SPEAKER_RESOURCE_NAME,
msg=msg)
net_id = network_info['network_id']
p = self._core_plugin._get_plugin_from_net_id(context, net_id)
if p.plugin_type() != plugin_type:
msg = (_('Network should belong to the %s plugin as the bgp '
'speaker') % plugin_type)
raise n_exc.InvalidInput(error_message=msg)
def add_gateway_network(self, context, bgp_speaker_id, network_info): def add_gateway_network(self, context, bgp_speaker_id, network_info):
driver = self._get_driver_by_speaker(context, bgp_speaker_id)
if self._core_plugin.is_tvd_plugin():
# The plugin of the network and speaker must be the same
self._validate_network_plugin(context, network_info)
with locking.LockManager.get_lock(str(bgp_speaker_id)): with locking.LockManager.get_lock(str(bgp_speaker_id)):
self.nsxv_driver.add_gateway_network(context, driver.add_gateway_network(context,
bgp_speaker_id, bgp_speaker_id,
network_info) network_info)
return super(NSXvBgpPlugin, self).add_gateway_network( return super(NSXBgpPlugin, self).add_gateway_network(
context, bgp_speaker_id, network_info) context, bgp_speaker_id, network_info)
def remove_gateway_network(self, context, bgp_speaker_id, network_info): def remove_gateway_network(self, context, bgp_speaker_id, network_info):
driver = self._get_driver_by_speaker(context, bgp_speaker_id)
with locking.LockManager.get_lock(str(bgp_speaker_id)): with locking.LockManager.get_lock(str(bgp_speaker_id)):
super(NSXvBgpPlugin, self).remove_gateway_network( super(NSXBgpPlugin, self).remove_gateway_network(
context, bgp_speaker_id, network_info) context, bgp_speaker_id, network_info)
self.nsxv_driver.remove_gateway_network(context, driver.remove_gateway_network(context,
bgp_speaker_id, bgp_speaker_id,
network_info) network_info)
def get_advertised_routes(self, context, bgp_speaker_id): def get_advertised_routes(self, context, bgp_speaker_id):
return self.nsxv_driver.get_advertised_routes(context, bgp_speaker_id) driver = self._get_driver_by_speaker(context, bgp_speaker_id)
return driver.get_advertised_routes(context, bgp_speaker_id)
def router_interface_callback(self, resource, event, trigger, **kwargs): def router_interface_callback(self, resource, event, trigger, **kwargs):
if not kwargs['network_id']: if not kwargs['network_id']:
@ -195,14 +303,16 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
speaker_id = speaker.id speaker_id = speaker.id
with locking.LockManager.get_lock(str(speaker_id)): with locking.LockManager.get_lock(str(speaker_id)):
speaker = self.get_bgp_speaker(context, speaker_id) speaker = self.get_bgp_speaker(context, speaker_id)
driver = self._get_driver_by_project(
context, speaker['tenant_id'])
if network_id not in speaker['networks']: if network_id not in speaker['networks']:
continue continue
if event == events.AFTER_CREATE: if event == events.AFTER_CREATE:
self.nsxv_driver.advertise_subnet(context, speaker_id, driver.advertise_subnet(context, speaker_id,
router_id, subnets[0]) router_id, subnets[0])
if event == events.AFTER_DELETE: if event == events.AFTER_DELETE:
subnet_id = port['fixed_ips'][0]['subnet_id'] subnet_id = port['fixed_ips'][0]['subnet_id']
self.nsxv_driver.withdraw_subnet(context, speaker_id, driver.withdraw_subnet(context, speaker_id,
router_id, subnet_id) router_id, subnet_id)
def router_gateway_callback(self, resource, event, trigger, **kwargs): def router_gateway_callback(self, resource, event, trigger, **kwargs):
@ -214,20 +324,22 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
for speaker in speakers: for speaker in speakers:
speaker_id = speaker.id speaker_id = speaker.id
driver = self._get_driver_by_project(
context, speaker['tenant_id'])
with locking.LockManager.get_lock(str(speaker_id)): with locking.LockManager.get_lock(str(speaker_id)):
speaker = self.get_bgp_speaker(context, speaker_id) speaker = self.get_bgp_speaker(context, speaker_id)
if network_id not in speaker['networks']: if network_id not in speaker['networks']:
continue continue
if event == events.AFTER_DELETE: if event == events.AFTER_DELETE:
gw_ips = kwargs['gateway_ips'] gw_ips = kwargs['gateway_ips']
self.nsxv_driver.disable_bgp_on_router(context, driver.disable_bgp_on_router(context,
speaker, speaker,
router_id, router_id,
gw_ips[0]) gw_ips[0])
if event == events.AFTER_UPDATE: if event == events.AFTER_UPDATE:
updated_port = kwargs['updated_port'] updated_port = kwargs['updated_port']
router = kwargs['router'] router = kwargs['router']
self.nsxv_driver.process_router_gw_port_update( driver.process_router_gw_port_update(
context, speaker, router, updated_port) context, speaker, router, updated_port)
def _before_service_edge_delete_callback(self, resource, event, def _before_service_edge_delete_callback(self, resource, event,
@ -239,11 +351,13 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
edge_id = kwargs.get('edge_id') edge_id = kwargs.get('edge_id')
speakers = self._bgp_speakers_for_gateway_network(context, ext_net_id) speakers = self._bgp_speakers_for_gateway_network(context, ext_net_id)
for speaker in speakers: for speaker in speakers:
driver = self._get_driver_by_project(
context, speaker['tenant_id'])
with locking.LockManager.get_lock(speaker.id): with locking.LockManager.get_lock(speaker.id):
speaker = self.get_bgp_speaker(context, speaker.id) speaker = self.get_bgp_speaker(context, speaker.id)
if ext_net_id not in speaker['networks']: if ext_net_id not in speaker['networks']:
continue continue
self.nsxv_driver.disable_bgp_on_router(context, speaker, driver.disable_bgp_on_router(context, speaker,
router['id'], router['id'],
gw_ip, edge_id) gw_ip, edge_id)
@ -254,9 +368,15 @@ class NSXvBgpPlugin(service_base.ServicePluginBase, bgp_db.BgpDbMixin):
ext_net_id = router.gw_port and router.gw_port['network_id'] ext_net_id = router.gw_port and router.gw_port['network_id']
speakers = self._bgp_speakers_for_gateway_network(context, ext_net_id) speakers = self._bgp_speakers_for_gateway_network(context, ext_net_id)
for speaker in speakers: for speaker in speakers:
driver = self._get_driver_by_project(
context, speaker['tenant_id'])
with locking.LockManager.get_lock(speaker.id): with locking.LockManager.get_lock(speaker.id):
speaker = self.get_bgp_speaker(context, speaker.id) speaker = self.get_bgp_speaker(context, speaker.id)
if ext_net_id not in speaker['networks']: if ext_net_id not in speaker['networks']:
continue continue
self.nsxv_driver.enable_bgp_on_router(context, speaker, driver.enable_bgp_on_router(context, speaker, router['id'])
router['id'])
class NSXvBgpPlugin(NSXBgpPlugin):
"""Defined for backwards compatibility only"""
pass

View File

@ -31,6 +31,7 @@ from vmware_nsx.common import locking
from vmware_nsx.common import nsxv_constants from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import nsxv_db from vmware_nsx.db import nsxv_db
from vmware_nsx.extensions import edge_service_gateway_bgp_peer as ext_esg_peer from vmware_nsx.extensions import edge_service_gateway_bgp_peer as ext_esg_peer
from vmware_nsx.extensions import projectpluginmap
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -87,6 +88,12 @@ class NSXvBgpDriver(object):
super(NSXvBgpDriver, self).__init__() super(NSXvBgpDriver, self).__init__()
self._plugin = plugin self._plugin = plugin
self._core_plugin = directory.get_plugin() self._core_plugin = directory.get_plugin()
if self._core_plugin.is_tvd_plugin():
self._core_plugin = self._core_plugin.get_plugin_by_type(
projectpluginmap.NsxPlugins.NSX_V)
if not self._core_plugin:
err_msg = _("NSXv BGP cannot work without the NSX-V core plugin")
raise n_exc.InvalidInput(error_message=err_msg)
self._nsxv = self._core_plugin.nsx_v self._nsxv = self._core_plugin.nsx_v
self._edge_manager = self._core_plugin.edge_manager self._edge_manager = self._core_plugin.edge_manager
@ -99,7 +106,7 @@ class NSXvBgpDriver(object):
if not edge_binding: if not edge_binding:
return None, None return None, None
# Idicates which routes should be advertised - connected or static. # Indicates which routes should be advertised - connected or static.
advertise_static_routes = False advertise_static_routes = False
if edge_binding['edge_type'] != nsxv_constants.SERVICE_EDGE: if edge_binding['edge_type'] != nsxv_constants.SERVICE_EDGE:
# Distributed router # Distributed router

View File

@ -43,13 +43,15 @@ class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
service_plugins = {ext_bgp.BGP_EXT_ALIAS: BGP_PLUGIN} service_plugins = {ext_bgp.BGP_EXT_ALIAS: BGP_PLUGIN}
super(TestNSXvBgpPlugin, self).setUp(service_plugins=service_plugins) super(TestNSXvBgpPlugin, self).setUp(service_plugins=service_plugins)
self.bgp_plugin = bgp_plugin.NSXvBgpPlugin() self.bgp_plugin = bgp_plugin.NSXvBgpPlugin()
self.bgp_plugin.nsxv_driver._validate_gateway_network = mock.Mock() self.nsxv_driver = self.bgp_plugin.drivers['nsx-v']
self.bgp_plugin.nsxv_driver._validate_bgp_configuration_on_peer_esg = ( self.nsxv_driver._validate_gateway_network = mock.Mock()
self.nsxv_driver._validate_bgp_configuration_on_peer_esg = (
mock.Mock()) mock.Mock())
self.plugin = directory.get_plugin() self.plugin = directory.get_plugin()
self.l3plugin = self.plugin self.l3plugin = self.plugin
self.plugin.init_is_complete = True self.plugin.init_is_complete = True
self.context = context.get_admin_context() self.context = context.get_admin_context()
self.project_id = 'dummy_project'
@contextlib.contextmanager @contextlib.contextmanager
def gw_network(self, external=True, **kwargs): def gw_network(self, external=True, **kwargs):
@ -85,18 +87,46 @@ class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
'esg_id': esg_id, 'esg_id': esg_id,
'auth_type': 'none', 'auth_type': 'none',
'password': '', 'password': '',
'tenant_id': ''} 'tenant_id': self.project_id}
bgp_peer = self.bgp_plugin.create_bgp_peer(self.context, bgp_peer = self.bgp_plugin.create_bgp_peer(self.context,
{'bgp_peer': data}) {'bgp_peer': data})
yield bgp_peer yield bgp_peer
self.bgp_plugin.delete_bgp_peer(self.context, bgp_peer['id']) self.bgp_plugin.delete_bgp_peer(self.context, bgp_peer['id'])
@contextlib.contextmanager
def bgp_speaker(self, ip_version, local_as, name='my-speaker',
advertise_fip_host_routes=True,
advertise_tenant_networks=True,
networks=None, peers=None):
data = {'ip_version': ip_version,
test_bgp_db.ADVERTISE_FIPS_KEY: advertise_fip_host_routes,
'advertise_tenant_networks': advertise_tenant_networks,
'local_as': local_as, 'name': name,
'tenant_id': self.project_id}
bgp_speaker = self.bgp_plugin.create_bgp_speaker(self.context,
{'bgp_speaker': data})
bgp_speaker_id = bgp_speaker['id']
if networks:
for network_id in networks:
self.bgp_plugin.add_gateway_network(
self.context,
bgp_speaker_id,
{'network_id': network_id})
if peers:
for peer_id in peers:
self.bgp_plugin.add_bgp_peer(self.context, bgp_speaker_id,
{'bgp_peer_id': peer_id})
yield self.bgp_plugin.get_bgp_speaker(self.context, bgp_speaker_id)
def test_create_v6_bgp_speaker(self): def test_create_v6_bgp_speaker(self):
fake_bgp_speaker = { fake_bgp_speaker = {
"bgp_speaker": { "bgp_speaker": {
"ip_version": 6, "ip_version": 6,
"local_as": "1000", "local_as": "1000",
"name": "bgp-speaker" "name": "bgp-speaker",
"tenant_id": self.project_id
} }
} }
self.assertRaises(n_exc.InvalidInput, self.assertRaises(n_exc.InvalidInput,
@ -109,7 +139,8 @@ class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
"auth_type": "none", "auth_type": "none",
"remote_as": "1000", "remote_as": "1000",
"name": "bgp-peer", "name": "bgp-peer",
"peer_ip": "fc00::/7" "peer_ip": "fc00::/7",
"tenant_id": self.project_id
} }
} }
self.assertRaises(n_exc.InvalidInput, self.assertRaises(n_exc.InvalidInput,
@ -128,13 +159,14 @@ class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
def test_create_bgp_peer_md5_auth_no_password(self): def test_create_bgp_peer_md5_auth_no_password(self):
bgp_peer = {'bgp_peer': bgp_peer = {'bgp_peer':
{'auth_type': 'md5', 'password': None, {'auth_type': 'md5', 'password': None,
'peer_ip': '10.0.0.3'}} 'peer_ip': '10.0.0.3',
'tenant_id': self.project_id}}
self.assertRaises(ext_bgp.InvalidBgpPeerMd5Authentication, self.assertRaises(ext_bgp.InvalidBgpPeerMd5Authentication,
self.bgp_plugin.create_bgp_peer, self.bgp_plugin.create_bgp_peer,
self.context, bgp_peer) self.context, bgp_peer)
def test_add_non_external_gateway_network(self): def test_add_non_external_gateway_network(self):
self.bgp_plugin.nsxv_driver._validate_gateway_network = ( self.nsxv_driver._validate_gateway_network = (
bgp_driver.NSXvBgpDriver( bgp_driver.NSXvBgpDriver(
self.bgp_plugin)._validate_gateway_network) self.bgp_plugin)._validate_gateway_network)
with self.gw_network(external=False) as net,\ with self.gw_network(external=False) as net,\
@ -170,15 +202,14 @@ class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
with self.router(external_gateway_info=gw_info1) as rtr1,\ with self.router(external_gateway_info=gw_info1) as rtr1,\
self.router(external_gateway_info=gw_info2) as rtr2,\ self.router(external_gateway_info=gw_info2) as rtr2,\
mock.patch.object( mock.patch.object(
self.bgp_plugin.nsxv_driver, self.nsxv_driver, '_get_router_edge_info',
'_get_router_edge_info',
return_value=('edge-1', False)),\ return_value=('edge-1', False)),\
mock.patch.object( mock.patch.object(
self.plugin.edge_manager, self.plugin.edge_manager,
'get_routers_on_same_edge', 'get_routers_on_same_edge',
return_value=[rtr1['id'], rtr2['id']]),\ return_value=[rtr1['id'], rtr2['id']]),\
mock.patch.object( mock.patch.object(
self.bgp_plugin.nsxv_driver, self.nsxv_driver,
'_update_edge_bgp_identifier') as up_bgp: '_update_edge_bgp_identifier') as up_bgp:
gw_clear = {u'router': {u'external_gateway_info': {}}} gw_clear = {u'router': {u'external_gateway_info': {}}}
self.plugin.update_router(self.context, self.plugin.update_router(self.context,
@ -246,3 +277,13 @@ class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
def test__get_routes_by_router_with_fip(self): def test__get_routes_by_router_with_fip(self):
# base class tests uses no-snat router with floating ips # base class tests uses no-snat router with floating ips
self.skipTest('No SNAT with floating ips not supported') self.skipTest('No SNAT with floating ips not supported')
def test_add_bgp_peer_with_bad_id(self):
with self.subnetpool_with_address_scope(
4, prefixes=['8.0.0.0/8']) as sp:
with self.bgp_speaker(sp['ip_version'], 1234) as speaker:
self.assertRaises(ext_bgp.BgpPeerNotFound,
self.bgp_plugin.add_bgp_peer,
self.context,
speaker['id'],
{'bgp_peer_id': 'aaa'})