NSXv: Support ipsec VPNaaS on nsxv driver

Change-Id: Id3fd4da7e4dd4cac4eb2e32024c0d8242b85a0bb
Co-Authored-By: Roey Chen <roeyc@vmware.com>
This commit is contained in:
Zhenmei 2016-03-18 04:11:22 -04:00 committed by Roey Chen
parent d0af9b5a9d
commit 53d1bd0e2f
12 changed files with 753 additions and 5 deletions

View File

@ -121,6 +121,15 @@ Add neutron-dynamic-routing repo as an external repository and configure followi
[DEFAULT]
api_extensions_path = $DEST/neutron-dynamic-routing/neutron_dynamic_routing/extensions
Neutron VPNaaS
~~~~~~~~~~~~~~
Add neutron-vpnaas repo as an external repository and configure following flags in ``local.conf``::
[[local|localrc]]
enable_plugin neutron-vpnaas https://git.openstack.org/openstack/neutron-vpnaas
NEUTRON_VPNAAS_SERVICE_PROVIDER=VPN:vmware:vmware_nsx.services.vpnaas.nsxv.ipsec_driver.NSXvIPsecVpnDriver:default
NSXv3
-----

View File

@ -10,6 +10,7 @@ ${DIR}/tox_install_project.sh neutron-lbaas neutron_lbaas $*
${DIR}/tox_install_project.sh vmware-nsxlib vmware_nsxlib $*
${DIR}/tox_install_project.sh neutron-fwaas neutron_fwaas $*
${DIR}/tox_install_project.sh neutron-dynamic-routing neutron-dynamic-routing $*
${DIR}/tox_install_project.sh neutron-vpnaas neutron-vpnaas $*
CONSTRAINTS_FILE=$1
shift

View File

@ -198,3 +198,11 @@ class NsxRouterInterfaceDoesNotMatchAddressScope(n_exc.BadRequest):
message = _("Unable to update no-NAT router %(router_id)s, "
"only subnets allocated from address-scope "
"%(address_scope_id)s can be connected.")
class NsxVpnValidationError(NsxPluginException):
message = _("Invalid VPN configuration: %(details)s")
class NsxIPsecVpnMappingNotFound(n_exc.NotFound):
message = _("Unable to find mapping for ipsec site connection: %(conn)s")

View File

@ -60,3 +60,19 @@ CSR_REQUEST = ("<csr><subject>"
RESERVED_IPS = ["169.254.128.0/17",
"169.254.1.0/24",
"169.254.64.192/26"]
# VPNaaS constants
ENCRYPTION_ALGORITHM_MAP = {
'3des': '3des',
'aes-128': 'aes',
'aes-256': 'aes256'
}
PFS_MAP = {
'group2': 'dh2',
'group5': 'dh5'
}
TRANSFORM_PROTOCOL_ALLOWED = ('esp',)
ENCAPSULATION_MODE_ALLOWED = ('tunnel',)

View File

@ -3549,6 +3549,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
fw_rules = []
router_with_firewall = True if fwaas_rules is not None else False
neutron_id = router_db['id']
edge_id = self._get_edge_id_by_rtr_id(context, router_id)
# Add FW rule to open subnets firewall flows and static routes
# relative flows
@ -3595,9 +3596,15 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
context, router_db)
fw_rules.extend(nosnat_fw_rules)
vpn_plugin = directory.get_plugin(plugin_const.VPN)
if vpn_plugin:
vpn_driver = vpn_plugin.ipsec_driver
vpn_rules = (
vpn_driver._generate_ipsecvpn_firewall_rules(edge_id))
fw_rules.extend(vpn_rules)
# Get the load balancer rules in case they are refreshed
# (relevant only for older LB that are still on the router edge)
edge_id = self._get_edge_id_by_rtr_id(context, router_id)
lb_rules = nsxv_db.get_nsxv_lbaas_loadbalancer_binding_by_edge(
context.session, edge_id)
for rule in lb_rules:

View File

View File

@ -0,0 +1,355 @@
# Copyright 2016 VMware, Inc.
# 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.
import netaddr
from neutron_lib import exceptions as n_exc
from neutron_lib.plugins import directory
from neutron_vpnaas.services.vpn import service_drivers
from oslo_log import log as logging
from vmware_nsx._i18n import _
from vmware_nsx.common import exceptions as nsxv_exc
from vmware_nsx.common import locking
from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import nsxv_db
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
from vmware_nsx.services.vpnaas.nsxv import ipsec_validator
LOG = logging.getLogger(__name__)
IPSEC = 'ipsec'
class NSXvIPsecVpnDriver(service_drivers.VpnDriver):
def __init__(self, service_plugin):
self._core_plugin = directory.get_plugin()
self._vcns = self._core_plugin.nsx_v.vcns
validator = ipsec_validator.IPsecValidator(service_plugin)
super(NSXvIPsecVpnDriver, self).__init__(service_plugin, validator)
@property
def l3_plugin(self):
return self._core_plugin
@property
def service_type(self):
return IPSEC
def _is_shared_router(self, router):
return router.get('router_type') == nsxv_constants.SHARED
def _get_router_edge_id(self, context, vpnservice_id):
vpnservice = self.service_plugin._get_vpnservice(context,
vpnservice_id)
router_id = vpnservice['router_id']
edge_binding = nsxv_db.get_nsxv_router_binding(context.session,
router_id)
if not edge_binding:
msg = _("Couldn't find edge binding for router %s") % router_id
raise nsxv_exc.NsxPluginException(err_msg=msg)
if edge_binding['edge_type'] == nsxv_constants.VDR_EDGE:
edge_manager = self._core_plugin.edge_manager
router_id = edge_manager.get_plr_by_tlr_id(context, router_id)
binding = nsxv_db.get_nsxv_router_binding(context.session,
router_id)
edge_id = binding['edge_id']
else:
# Get exclusive edge id
edge_id = edge_binding['edge_id']
return router_id, edge_id
def _convert_ipsec_conn(self, context, ipsec_site_connection):
ipsec_id = ipsec_site_connection['ipsecpolicy_id']
vpnservice_id = ipsec_site_connection['vpnservice_id']
ipsecpolicy = self.service_plugin.get_ipsecpolicy(context, ipsec_id)
vpnservice = self.service_plugin._get_vpnservice(context,
vpnservice_id)
local_cidr = vpnservice['subnet']['cidr']
router_id = vpnservice['router_id']
router = self._core_plugin.get_router(context, router_id)
local_addr = (router['external_gateway_info']['external_fixed_ips']
[0]["ip_address"])
encrypt = nsxv_constants.ENCRYPTION_ALGORITHM_MAP.get(
ipsecpolicy.get('encryption_algorithm'))
site = {
'enabled': True,
'enablePfs': True,
'dhGroup': nsxv_constants.PFS_MAP.get(ipsecpolicy.get('pfs')),
'name': ipsec_site_connection.get('name'),
'description': ipsec_site_connection.get('description'),
'localId': local_addr,
'localIp': local_addr,
'peerId': ipsec_site_connection['peer_id'],
'peerIp': ipsec_site_connection.get('peer_address'),
'localSubnets': {
'subnets': [local_cidr]},
'peerSubnets': {
'subnets': ipsec_site_connection.get('peer_cidrs')},
'authenticationMode': ipsec_site_connection.get('auth_mode'),
'psk': ipsec_site_connection.get('psk'),
'encryptionAlgorithm': encrypt
}
return site
def _generate_new_sites(self, edge_id, ipsec_site_conn):
# Fetch the previous ipsec vpn configuration
ipsecvpn_configs = self._get_ipsec_config(edge_id)
vse_sites = []
if ipsecvpn_configs[1]['enabled']:
vse_sites = ([site for site
in ipsecvpn_configs[1]['sites']['sites']])
vse_sites.append(ipsec_site_conn)
return vse_sites
def _generate_ipsecvpn_firewall_rules(self, edge_id):
ipsecvpn_configs = self._get_ipsec_config(edge_id)
ipsec_vpn_fw_rules = []
if ipsecvpn_configs[1]['enabled']:
for site in ipsecvpn_configs[1]['sites']['sites']:
peer_subnets = site['peerSubnets']['subnets']
local_subnets = site['localSubnets']['subnets']
ipsec_vpn_fw_rules.append({
'name': 'VPN ' + site['name'],
'action': 'allow',
'enabled': True,
'source_ip_address': peer_subnets,
'destination_ip_address': local_subnets})
return ipsec_vpn_fw_rules
def _update_firewall_rules(self, context, vpnservice_id):
vpnservice = self.service_plugin._get_vpnservice(context,
vpnservice_id)
router_db = (
self._core_plugin._get_router(context, vpnservice['router_id']))
self._core_plugin._update_subnets_and_dnat_firewall(context,
router_db)
def _update_status(self, context, vpn_service_id, ipsec_site_conn_id,
status, updated_pending_status=True):
status_list = []
vpn_status = {}
ipsec_site_conn = {}
vpn_status['id'] = vpn_service_id
vpn_status['updated_pending_status'] = updated_pending_status
vpn_status['status'] = status
ipsec_site_conn['status'] = status
ipsec_site_conn['updated_pending_status'] = updated_pending_status
vpn_status['ipsec_site_connections'] = {ipsec_site_conn_id:
ipsec_site_conn}
status_list.append(vpn_status)
self.service_plugin.update_status_by_agent(context, status_list)
def create_ipsec_site_connection(self, context, ipsec_site_connection):
LOG.debug('Creating ipsec site connection %(conn_info)s.',
{"conn_info": ipsec_site_connection})
self.validator.validate_ipsec_conn(context, ipsec_site_connection)
new_ipsec = self._convert_ipsec_conn(context, ipsec_site_connection)
vpnservice_id = ipsec_site_connection['vpnservice_id']
edge_id = self._get_router_edge_id(context, vpnservice_id)[1]
with locking.LockManager.get_lock(edge_id):
vse_sites = self._generate_new_sites(edge_id, new_ipsec)
ipsec_id = ipsec_site_connection["id"]
try:
LOG.debug('Updating ipsec vpn configuration %(vse_sites)s.',
{'vse_sites': vse_sites})
self._update_ipsec_config(edge_id, vse_sites, enabled=True)
except vcns_exc.VcnsApiException:
self._update_status(context, vpnservice_id, ipsec_id,
"ERROR")
msg = (_("Failed to create ipsec site connection "
"configuration with %(edge_id)s.") %
{'edge_id': edge_id})
raise nsxv_exc.NsxPluginException(err_msg=msg)
LOG.debug('Updating ipsec vpn firewall')
try:
self._update_firewall_rules(context, vpnservice_id)
except vcns_exc.VcnsApiException:
self._update_status(context, vpnservice_id, ipsec_id, "ERROR")
msg = (_("Failed to update firewall rule for ipsec vpn "
"with %(edge_id)s.") % {'edge_id': edge_id})
raise nsxv_exc.NsxPluginException(err_msg=msg)
self._update_status(context, vpnservice_id, ipsec_id, "ACTIVE")
def _get_ipsec_config(self, edge_id):
return self._vcns.get_ipsec_config(edge_id)
def delete_ipsec_site_connection(self, context, ipsec_site_conn):
LOG.debug('Deleting ipsec site connection %(site)s.',
{"site": ipsec_site_conn})
ipsec_id = ipsec_site_conn['id']
edge_id = self._get_router_edge_id(context,
ipsec_site_conn['vpnservice_id'])[1]
with locking.LockManager.get_lock(edge_id):
del_site, vse_sites = self._find_vse_site(context, edge_id,
ipsec_site_conn)
if not del_site:
LOG.error("Failed to find ipsec_site_connection "
"%(ipsec_site_conn)s with %(edge_id)s.",
{'ipsec_site_conn': ipsec_site_conn,
'edge_id': edge_id})
raise nsxv_exc.NsxIPsecVpnMappingNotFound(conn=ipsec_id)
vse_sites.remove(del_site)
enabled = True if vse_sites else False
try:
self._update_ipsec_config(edge_id, vse_sites, enabled)
except vcns_exc.VcnsApiException:
msg = (_("Failed to delete ipsec site connection "
"configuration with edge_id: %(edge_id)s.") %
{'egde_id': edge_id})
raise nsxv_exc.NsxPluginException(err_msg=msg)
try:
self._update_firewall_rules(context,
ipsec_site_conn['vpnservice_id'])
except vcns_exc.VcnsApiException:
msg = _("Failed to update firewall rule for ipsec vpn with "
"%(edge_id)s.") % {'edge_id': edge_id}
raise nsxv_exc.NsxPluginException(err_msg=msg)
def _find_vse_site(self, context, edge_id, site):
# Fetch the previous ipsec vpn configuration
ipsecvpn_configs = self._get_ipsec_config(edge_id)[1]
vpnservice = self.service_plugin._get_vpnservice(context,
site['vpnservice_id'])
local_cidr = vpnservice['subnet']['cidr']
old_site = None
vse_sites = None
if ipsecvpn_configs['enabled']:
vse_sites = ipsecvpn_configs['sites'].get('sites')
for s in vse_sites:
if ((s['peerSubnets'].get('subnets') == site['peer_cidrs'])
and
(s['localSubnets'].get('subnets')[0] == local_cidr)):
old_site = s
break
return old_site, vse_sites
def _update_site_dict(self, context, edge_id, site,
ipsec_site_connection):
# Fetch the previous ipsec vpn configuration
old_site, vse_sites = self._find_vse_site(context, edge_id, site)
if old_site:
vse_sites.remove(old_site)
if 'peer_addresses' in ipsec_site_connection:
old_site['peerIp'] = ipsec_site_connection['peer_address']
if 'peer_cidrs' in ipsec_site_connection:
old_site['peerSubnets']['subnets'] = (ipsec_site_connection
['peer_cidrs'])
vse_sites.append(old_site)
return vse_sites
def update_ipsec_site_connection(self, context, old_ipsec_conn,
ipsec_site_connection):
LOG.debug('Updating ipsec site connection %(site)s.',
{"site": ipsec_site_connection})
vpnservice_id = old_ipsec_conn['vpnservice_id']
ipsec_id = old_ipsec_conn['id']
edge_id = self._get_router_edge_id(context, vpnservice_id)[1]
with locking.LockManager.get_lock(edge_id):
vse_sites = self._update_site_dict(context, edge_id,
old_ipsec_conn,
ipsec_site_connection)
if not vse_sites:
self._update_status(context, vpnservice_id, ipsec_id,
"ERROR")
LOG.error("Failed to find ipsec_site_connection "
"%(ipsec_site_conn)s with %(edge_id)s.",
{'ipsec_site_conn': ipsec_site_connection,
'edge_id': edge_id})
raise nsxv_exc.NsxIPsecVpnMappingNotFound(conn=ipsec_id)
try:
LOG.debug('Updating ipsec vpn configuration %(vse_sites)s.',
{'vse_sites': vse_sites})
self._update_ipsec_config(edge_id, vse_sites)
except vcns_exc.VcnsApiException:
self._update_status(context, vpnservice_id, ipsec_id, "ERROR")
msg = (_("Failed to create ipsec site connection "
"configuration with %(edge_id)s.") %
{'edge_id': edge_id})
raise nsxv_exc.NsxPluginException(err_msg=msg)
if 'peer_cidrs' in ipsec_site_connection:
# Update firewall
old_ipsec_conn['peer_cidrs'] = (
ipsec_site_connection['peer_cidrs'])
try:
self._update_firewall_rules(context, vpnservice_id)
except vcns_exc.VcnsApiException:
self._update_status(context, vpnservice_id, ipsec_id,
"ERROR")
msg = (_("Failed to update firewall rule for ipsec "
"vpn with %(edge_id)s.") % {'edge_id': edge_id})
raise nsxv_exc.NsxPluginException(err_msg=msg)
def _get_gateway_ips(self, router):
"""Obtain the IPv4 and/or IPv6 GW IP for the router.
If there are multiples, (arbitrarily) use the first one.
"""
v4_ip = v6_ip = None
for fixed_ip in router.gw_port['fixed_ips']:
addr = fixed_ip['ip_address']
vers = netaddr.IPAddress(addr).version
if vers == 4:
if v4_ip is None:
v4_ip = addr
elif v6_ip is None:
v6_ip = addr
return v4_ip, v6_ip
def create_vpnservice(self, context, vpnservice):
LOG.debug('Creating VPN service %(vpn)s', {'vpn': vpnservice})
# Only support distributed and exclusive router type
router_id = vpnservice['router_id']
vpnservice_id = vpnservice['id']
router = self._core_plugin.get_router(context, router_id)
if self._is_shared_router(router):
# Rolling back change on the neutron
self.service_plugin.delete_vpnservice(context, vpnservice_id)
msg = _("Router type is not supported for VPN service, only "
"support distributed and exclusive router")
raise n_exc.InvalidInput(error_message=msg)
vpnservice = self.service_plugin._get_vpnservice(context,
vpnservice_id)
v4_ip, v6_ip = self._get_gateway_ips(vpnservice.router)
if v4_ip:
vpnservice['external_v4_ip'] = v4_ip
if v6_ip:
vpnservice['external_v6_ip'] = v6_ip
self.service_plugin.set_external_tunnel_ips(context,
vpnservice_id,
v4_ip=v4_ip, v6_ip=v6_ip)
def update_vpnservice(self, context, old_vpnservice, vpnservice):
pass
def delete_vpnservice(self, context, vpnservice):
pass
def _update_ipsec_config(self, edge_id, sites, enabled=True):
ipsec_config = {'featureType': "ipsec_4.0",
'enabled': enabled}
ipsec_config['sites'] = {'sites': sites}
try:
self._vcns.update_ipsec_config(edge_id, ipsec_config)
except vcns_exc.VcnsApiException:
msg = _("Failed to update ipsec vpn configuration with "
"edge_id: %s") % edge_id
raise nsxv_exc.NsxPluginException(err_msg=msg)

View File

@ -0,0 +1,93 @@
# Copyright 2016 VMware, Inc.
# 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_vpnaas.db.vpn import vpn_validator
from oslo_log import log as logging
from vmware_nsx._i18n import _
from vmware_nsx.common import exceptions as nsxv_exc
from vmware_nsx.common import nsxv_constants
LOG = logging.getLogger(__name__)
class IPsecValidator(vpn_validator.VpnReferenceValidator):
"""Validator methods for Vmware VPN support"""
def __init__(self, service_plugin):
super(IPsecValidator, self).__init__()
self.vpn_plugin = service_plugin
def validate_ikepolicy_version(self, policy_info):
"""NSX Edge provides IKEv1"""
version = policy_info.get('ike_version')
if version != 'v1':
msg = _("Unsupported ike policy %s! only v1 "
"is supported right now.") % version
raise nsxv_exc.NsxIPsecVpnError(details=msg)
def validate_ikepolicy_pfs(self, policy_info):
# Check whether pfs is allowed.
if not nsxv_constants.PFS_MAP.get(policy_info['pfs']):
msg = _("Unsupported pfs: %(pfs)s! currently only "
"the following pfs are supported on VSE: %s") % {
'pfs': policy_info['pfs'],
'supported': nsxv_constants.PFS_MAP}
raise nsxv_exc.NsxVpnValidationError(details=msg)
def validate_encryption_algorithm(self, policy_info):
encryption = policy_info['encryption_algorithm']
if encryption not in nsxv_constants.ENCRYPTION_ALGORITHM_MAP:
msg = _("Unsupported encryption_algorithm: %(algo)s! please "
"select one of the followoing supported algorithms: "
"%(supported_algos)s") % {
'algo': encryption,
'supported_algos':
nsxv_constants.ENCRYPTION_ALGORITHM_MAP}
raise nsxv_exc.NsxVpnValidationError(details=msg)
def validate_ipsec_policy(self, context, policy_info):
"""Ensure IPSec policy encap mode is tunnel for current REST API."""
mode = policy_info['encapsulation_mode']
if mode not in nsxv_constants.ENCAPSULATION_MODE_ALLOWED:
msg = _("Unsupported encapsulation mode: %s! currently only"
"'tunnel' mode is supported.") % mode
raise nsxv_exc.NsxVpnValidationError(details=msg)
def validate_policies_matching_algorithms(self, ikepolicy, ipsecpolicy):
# In VSE, Phase 1 and Phase 2 share the same encryption_algorithm
# and authentication algorithms setting. At present, just record the
# discrepancy error in log and take ipsecpolicy to do configuration.
keys = ('auth_algorithm', 'encryption_algorithm', 'pfs')
for key in keys:
if ikepolicy[key] != ipsecpolicy[key]:
LOG.warning("IKEPolicy and IPsecPolicy should have consistent "
"auth_algorithm, encryption_algorithm and pfs for "
"VSE!")
break
def validate_ipsec_conn(self, context, ipsec_site_conn):
ike_policy_id = ipsec_site_conn['ikepolicy_id']
ipsec_policy_id = ipsec_site_conn['ipsecpolicy_id']
ipsecpolicy = self.vpn_plugin.get_ipsecpolicy(context,
ipsec_policy_id)
ikepolicy = self.vpn_plugin.get_ikepolicy(context,
ike_policy_id)
self.validate_ikepolicy_version(ikepolicy)
self.validate_ikepolicy_pfs(ikepolicy)
self.validate_encryption_algorithm(ikepolicy)
self.validate_ipsec_policy(context, ipsecpolicy)
self.validate_policies_matching_algorithms(ikepolicy, ipsecpolicy)

View File

@ -0,0 +1,255 @@
# Copyright 2016 VMware, Inc.
# 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.
import contextlib
import mock
from neutron_lib import context
from neutron_lib import exceptions as n_exc
from neutron_lib.plugins import directory
from neutron_vpnaas.db.vpn import vpn_models # noqa
from oslo_utils import uuidutils
from vmware_nsx.common import exceptions as nsxv_exc
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
from vmware_nsx.services.vpnaas.nsxv import ipsec_driver
from vmware_nsx.tests.unit.nsx_v import test_plugin
_uuid = uuidutils.generate_uuid
DRIVER_PATH = "vmware_nsx.services.vpnaas.nsxv.ipsec_driver.NSXvIPsecVpnDriver"
VALI_PATH = "vmware_nsx.services.vpnaas.nsxv.ipsec_validator.IPsecValidator"
FAKE_ROUTER_ID = "aaaaaa-bbbbb-ccc"
FAKE_VPNSERVICE_ID = _uuid()
FAKE_IPSEC_CONNECTION = {"vpnservice_id": FAKE_VPNSERVICE_ID,
"id": _uuid()}
FAKE_EDGE_ID = _uuid()
FAKE_IPSEC_VPN_SITE = {"peerIp": "192.168.1.1"}
FAKE_VCNSAPIEXC = {"status": "fail",
"head": "fake_head",
"response": "error"}
FAKE_NEW_CONNECTION = {"peer_cidrs": "192.168.1.0/24"}
class TestVpnaasDriver(test_plugin.NsxVPluginV2TestCase):
def setUp(self):
super(TestVpnaasDriver, self).setUp()
self.context = context.get_admin_context()
self.service_plugin = mock.Mock()
self.validator = mock.Mock()
self.driver = ipsec_driver.NSXvIPsecVpnDriver(self.service_plugin)
self.plugin = directory.get_plugin()
self.l3plugin = self.plugin
@contextlib.contextmanager
def router(self, name='vpn-test-router', tenant_id=_uuid(),
admin_state_up=True, **kwargs):
request = {'router': {'tenant_id': tenant_id,
'name': name,
'admin_state_up': admin_state_up}}
for arg in kwargs:
request['router'][arg] = kwargs[arg]
router = self.l3plugin.create_router(self.context, request)
yield router
@mock.patch('%s.validate_ipsec_conn' % VALI_PATH)
@mock.patch('%s._convert_ipsec_conn' % DRIVER_PATH)
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._generate_new_sites' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_status' % DRIVER_PATH)
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
def test_create_ipsec_site_connection(self, mock_update_fw,
mock_update_status,
mock_update_ipsec, mock_gen_new,
mock_get_id,
mock_conv_ipsec,
mock_val_conn):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_conv_ipsec.return_value = FAKE_IPSEC_VPN_SITE
mock_gen_new.return_value = FAKE_IPSEC_VPN_SITE
self.driver.create_ipsec_site_connection(self.context,
FAKE_IPSEC_CONNECTION)
mock_val_conn.assert_called_with(self.context,
FAKE_IPSEC_CONNECTION)
mock_conv_ipsec.assert_called_with(self.context,
FAKE_IPSEC_CONNECTION)
mock_get_id.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
mock_gen_new.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
FAKE_IPSEC_VPN_SITE,
enabled=True)
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
mock_update_status.assert_called_with(
self.context,
FAKE_IPSEC_CONNECTION["vpnservice_id"],
FAKE_IPSEC_CONNECTION["id"],
"ACTIVE")
@mock.patch('%s.validate_ipsec_conn' % VALI_PATH)
@mock.patch('%s._convert_ipsec_conn' % DRIVER_PATH)
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._generate_new_sites' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_status' % DRIVER_PATH)
def test_create_ipsec_site_connection_fail(self,
mock_update_status,
mock_update_ipsec,
mock_gen_new, mock_get_id,
mock_conv_ipsec,
mock_val_conn):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_conv_ipsec.return_value = FAKE_IPSEC_VPN_SITE
mock_gen_new.return_value = FAKE_IPSEC_VPN_SITE
mock_update_ipsec.side_effect = (
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
self.assertRaises(nsxv_exc.NsxPluginException,
self.driver.create_ipsec_site_connection,
self.context, FAKE_IPSEC_CONNECTION)
mock_val_conn.assert_called_with(self.context, FAKE_IPSEC_CONNECTION)
mock_conv_ipsec.assert_called_with(self.context, FAKE_IPSEC_CONNECTION)
mock_get_id.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
mock_gen_new.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
FAKE_IPSEC_VPN_SITE,
enabled=True)
mock_update_status.assert_called_with(
self.context,
FAKE_IPSEC_CONNECTION["vpnservice_id"],
FAKE_IPSEC_CONNECTION["id"],
"ERROR")
@mock.patch('%s.validate_ipsec_conn' % VALI_PATH)
@mock.patch('%s._convert_ipsec_conn' % DRIVER_PATH)
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._generate_new_sites' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_status' % DRIVER_PATH)
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
def test_update_fw_fail(self, mock_update_fw, mock_update_status,
mock_update_ipsec, mock_gen_new,
mock_get_id, mock_conv_ipsec, mock_val_conn):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_conv_ipsec.return_value = FAKE_IPSEC_VPN_SITE
mock_gen_new.return_value = FAKE_IPSEC_VPN_SITE
mock_update_fw.side_effect = (
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
self.assertRaises(nsxv_exc.NsxPluginException,
self.driver.create_ipsec_site_connection,
self.context, FAKE_IPSEC_CONNECTION)
mock_val_conn.assert_called_with(self.context, FAKE_IPSEC_CONNECTION)
mock_conv_ipsec.assert_called_with(self.context, FAKE_IPSEC_CONNECTION)
mock_get_id.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
mock_gen_new.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
FAKE_IPSEC_VPN_SITE,
enabled=True)
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
mock_update_status.assert_called_with(
self.context,
FAKE_IPSEC_CONNECTION["vpnservice_id"],
FAKE_IPSEC_CONNECTION["id"],
"ERROR")
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
def test_update_ipsec(self, mock_update_fw, mock_update_ipsec,
mock_update_sites, mock_get_id):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_update_sites.return_value = FAKE_IPSEC_VPN_SITE
self.driver.update_ipsec_site_connection(self.context,
FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_sites.assert_called_with(self.context, FAKE_EDGE_ID,
FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
def test_update_ipsec_fail_with_notfound(self, mock_update_fw,
mock_update_ipsec,
mock_update_sites, mock_get_id):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_update_sites.return_value = {}
self.assertRaises(nsxv_exc.NsxIPsecVpnMappingNotFound,
self.driver.update_ipsec_site_connection,
self.context, FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_sites.assert_called_with(self.context,
FAKE_EDGE_ID,
FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
def test_update_ipsec_fail_with_fw_fail(self, mock_update_fw,
mock_update_ipsec,
mock_update_sites, mock_get_id):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_update_fw.side_effect = (
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
self.assertRaises(nsxv_exc.NsxPluginException,
self.driver.update_ipsec_site_connection,
self.context, FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_sites.assert_called_with(self.context, FAKE_EDGE_ID,
FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
@mock.patch('%s._update_status' % DRIVER_PATH)
def test_update_ipsec_fail_with_site_fail(self, mock_update_status,
mock_update_ipsec,
mock_update_sites, mock_get_id):
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
mock_update_sites.return_value = FAKE_IPSEC_VPN_SITE
mock_update_ipsec.side_effect = (
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
self.assertRaises(nsxv_exc.NsxPluginException,
self.driver.update_ipsec_site_connection,
self.context,
FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_sites.assert_called_with(self.context, FAKE_EDGE_ID,
FAKE_IPSEC_CONNECTION,
FAKE_NEW_CONNECTION)
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
FAKE_IPSEC_VPN_SITE)
mock_update_status.assert_called_with(
self.context,
FAKE_IPSEC_CONNECTION["vpnservice_id"],
FAKE_IPSEC_CONNECTION["id"],
"ERROR")
def test_create_vpn_service_on_shared_router(self):
with self.router(router_type='shared') as router, self.subnet():
vpnservice = {'router_id': router['id'],
'id': _uuid()}
self.assertRaises(n_exc.InvalidInput,
self.driver.create_vpnservice,
self.context, vpnservice)

View File

@ -21,6 +21,7 @@ from neutron.db import servicetype_db # noqa
from neutron.quota import resource_registry
from neutron.tests import base
from neutron_lib.callbacks import registry
from neutron_lib import constants
from oslo_config import cfg
from oslo_log import _options
from oslo_log import log as logging
@ -137,10 +138,13 @@ class TestNsxvAdminUtils(AbstractTestAdminUtils,
return_value=0).start()
self._plugin = nsxv_utils.NsxVPluginWrapper()
mock_nm_get_plugin = mock.patch(
"neutron_lib.plugins.directory.get_plugin")
self.mock_nm_get_plugin = mock_nm_get_plugin.start()
self.mock_nm_get_plugin.return_value = self._plugin
def get_plugin_mock(alias=constants.CORE):
if alias in (constants.CORE, constants.L3):
return self._plugin
mock.patch("neutron_lib.plugins.directory.get_plugin",
side_effect=get_plugin_mock).start()
# Create a router to make sure we have deployed an edge
self.router = self.create_router()