Merge "NSX-v3: VPNaaS supports only No-SNAT routers"

This commit is contained in:
Zuul 2018-02-05 11:18:00 +00:00 committed by Gerrit Code Review
commit da500f1e84
4 changed files with 53 additions and 4 deletions

View File

@ -3445,6 +3445,14 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
context.elevated(), router_id,
gw_info['network_id'], fip['subnet_id'])
# VPNaaS need to be notified on router GW changes (there is currently
# no matching upstream registration for this)
if validators.is_attr_set(gw_info):
vpn_plugin = directory.get_plugin(plugin_const.VPN)
if vpn_plugin:
vpn_driver = vpn_plugin.drivers[vpn_plugin.default_provider]
vpn_driver.validate_router_gw_info(context, router_id, gw_info)
nsx_router_id = None
routes_added = []
routes_removed = []

View File

@ -14,6 +14,7 @@
# under the License.
import netaddr
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import excutils
@ -21,6 +22,7 @@ from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib import constants
from neutron_lib import exceptions as nexception
from neutron_lib.plugins import directory
from neutron_vpnaas.services.vpn import service_drivers
@ -37,6 +39,11 @@ LOG = logging.getLogger(__name__)
IPSEC = 'ipsec'
class RouterWithSNAT(nexception.BadRequest):
message = _("Router %(router_id)s has a VPN service and cannot enable "
"SNAT")
class NSXv3IPsecVpnDriver(service_drivers.VpnDriver):
def __init__(self, service_plugin):
@ -354,6 +361,19 @@ class NSXv3IPsecVpnDriver(service_drivers.VpnDriver):
if local_ep_id:
self._nsx_vpn.local_endpoint.delete(local_ep_id)
def validate_router_gw_info(self, context, router_id, gw_info):
"""Upon router gw update - verify no-snat"""
# ckeck if this router has a vpn service
filters = {'router_id': [router_id],
'status': [constants.ACTIVE]}
services = self.vpn_plugin.get_vpnservices(
context.elevated(), filters=filters)
if services:
# do not allow enable-snat
if (gw_info and
gw_info.get('enable_snat', cfg.CONF.enable_snat_by_default)):
raise RouterWithSNAT(router_id=router_id)
def _get_session_rules(self, context, connection, vpnservice):
# TODO(asarfaty): support vpn-endpoint-groups too
peer_cidrs = connection['peer_cidrs']

View File

@ -323,6 +323,11 @@ class IPsecV3Validator(vpn_validator.VpnReferenceValidator):
"with ACTIVE_STANDBY HA mode")
raise nsx_exc.NsxVpnValidationError(details=msg)
# Verify that this is a no-snat router
if router_db.enable_snat:
msg = _("VPN is supported only for routers with disabled SNAT")
raise nsx_exc.NsxVpnValidationError(details=msg)
def validate_vpnservice(self, context, vpnservice):
"""Called upon create/update of a service"""

View File

@ -14,6 +14,7 @@
# under the License.
import mock
from neutron.db.models import l3 as l3_models
from neutron_lib import context as n_ctx
from neutron_vpnaas.tests import base
@ -156,16 +157,31 @@ class TestDriverValidation(base.BaseTestCase):
self.validator.validate_ipsec_policy(self.context, policy_info)
def test_vpn_service_validation_router(self):
router = {'high_availability_mode': 'ACITVE_ACTIVE'}
db_router = l3_models.Router()
nsx_router = {'high_availability_mode': 'ACITVE_ACTIVE'}
db_router.enable_snat = False
with mock.patch.object(self.validator.nsxlib.logical_router, 'get',
return_value=router):
return_value=nsx_router):
self.assertRaises(nsx_exc.NsxVpnValidationError,
self.validator.validate_vpnservice,
self.context, self.vpn_service)
router = {'high_availability_mode': 'ACTIVE_STANDBY'}
nsx_router = {'high_availability_mode': 'ACTIVE_STANDBY'}
db_router.enable_snat = True
with mock.patch.object(self.validator.nsxlib.logical_router, 'get',
return_value=router):
return_value=nsx_router),\
mock.patch.object(self.validator._core_plugin, '_get_router',
return_value=db_router):
self.assertRaises(nsx_exc.NsxVpnValidationError,
self.validator.validate_vpnservice,
self.context, self.vpn_service)
nsx_router = {'high_availability_mode': 'ACTIVE_STANDBY'}
db_router.enable_snat = False
with mock.patch.object(self.validator.nsxlib.logical_router, 'get',
return_value=nsx_router),\
mock.patch.object(self.validator._core_plugin, '_get_router',
return_value=db_router):
self.validator.validate_vpnservice(self.context, self.vpn_service)
def _test_conn_validation(self, conn_params=None, success=True,