Merge "Support advanced NVP IPsec VPN Service"
This commit is contained in:
commit
78366adca8
@ -24,6 +24,7 @@ from neutron.db.firewall import firewall_db
|
|||||||
from neutron.db import l3_db
|
from neutron.db import l3_db
|
||||||
from neutron.db.loadbalancer import loadbalancer_db
|
from neutron.db.loadbalancer import loadbalancer_db
|
||||||
from neutron.db import routedserviceinsertion_db as rsi_db
|
from neutron.db import routedserviceinsertion_db as rsi_db
|
||||||
|
from neutron.db.vpn import vpn_db
|
||||||
from neutron.extensions import firewall as fw_ext
|
from neutron.extensions import firewall as fw_ext
|
||||||
from neutron.extensions import l3
|
from neutron.extensions import l3
|
||||||
from neutron.extensions import routedserviceinsertion as rsi
|
from neutron.extensions import routedserviceinsertion as rsi
|
||||||
@ -79,7 +80,8 @@ class NsxAdvancedPlugin(sr_db.ServiceRouter_mixin,
|
|||||||
base.NsxPluginV2,
|
base.NsxPluginV2,
|
||||||
rsi_db.RoutedServiceInsertionDbMixin,
|
rsi_db.RoutedServiceInsertionDbMixin,
|
||||||
firewall_db.Firewall_db_mixin,
|
firewall_db.Firewall_db_mixin,
|
||||||
loadbalancer_db.LoadBalancerPluginDb
|
loadbalancer_db.LoadBalancerPluginDb,
|
||||||
|
vpn_db.VPNPluginDb
|
||||||
):
|
):
|
||||||
|
|
||||||
supported_extension_aliases = (
|
supported_extension_aliases = (
|
||||||
@ -87,7 +89,8 @@ class NsxAdvancedPlugin(sr_db.ServiceRouter_mixin,
|
|||||||
"service-router",
|
"service-router",
|
||||||
"routed-service-insertion",
|
"routed-service-insertion",
|
||||||
"fwaas",
|
"fwaas",
|
||||||
"lbaas"
|
"lbaas",
|
||||||
|
"vpnaas"
|
||||||
])
|
])
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -893,7 +896,7 @@ class NsxAdvancedPlugin(sr_db.ServiceRouter_mixin,
|
|||||||
self._process_create_resource_router_id(
|
self._process_create_resource_router_id(
|
||||||
context, res, firewall_db.Firewall)
|
context, res, firewall_db.Firewall)
|
||||||
# Since there is only one firewall per edge,
|
# Since there is only one firewall per edge,
|
||||||
#here would be bulk configureation operation on firewall
|
# here would be bulk configuration operation on firewall
|
||||||
self._vcns_update_firewall(context, fw, router_id)
|
self._vcns_update_firewall(context, fw, router_id)
|
||||||
self._firewall_set_status(
|
self._firewall_set_status(
|
||||||
context, fw['id'], service_constants.ACTIVE, fw)
|
context, fw['id'], service_constants.ACTIVE, fw)
|
||||||
@ -1570,6 +1573,153 @@ class NsxAdvancedPlugin(sr_db.ServiceRouter_mixin,
|
|||||||
context, loadbalancer_db.Pool,
|
context, loadbalancer_db.Pool,
|
||||||
pool_id, service_constants.ACTIVE)
|
pool_id, service_constants.ACTIVE)
|
||||||
|
|
||||||
|
def _vcns_update_ipsec_config(
|
||||||
|
self, context, vpnservice_id, removed_ipsec_conn_id=None):
|
||||||
|
sites = []
|
||||||
|
vpn_service = self._get_vpnservice(context, vpnservice_id)
|
||||||
|
edge_id = self._get_edge_id_by_vcns_edge_binding(
|
||||||
|
context, vpn_service.router_id)
|
||||||
|
if not vpn_service.router.gw_port:
|
||||||
|
msg = _("Failed to update ipsec vpn configuration on edge, since "
|
||||||
|
"the router: %s does not have a gateway yet!"
|
||||||
|
) % vpn_service.router_id
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exceptions.VcnsBadRequest(resource='router', msg=msg)
|
||||||
|
|
||||||
|
external_ip = vpn_service.router.gw_port['fixed_ips'][0]['ip_address']
|
||||||
|
subnet = self._make_subnet_dict(vpn_service.subnet)
|
||||||
|
for ipsec_site_conn in vpn_service.ipsec_site_connections:
|
||||||
|
if ipsec_site_conn.id != removed_ipsec_conn_id:
|
||||||
|
site = self._make_ipsec_site_connection_dict(ipsec_site_conn)
|
||||||
|
ikepolicy = self._make_ikepolicy_dict(
|
||||||
|
ipsec_site_conn.ikepolicy)
|
||||||
|
ipsecpolicy = self._make_ipsecpolicy_dict(
|
||||||
|
ipsec_site_conn.ipsecpolicy)
|
||||||
|
sites.append({'site': site,
|
||||||
|
'ikepolicy': ikepolicy,
|
||||||
|
'ipsecpolicy': ipsecpolicy,
|
||||||
|
'subnet': subnet,
|
||||||
|
'external_ip': external_ip})
|
||||||
|
try:
|
||||||
|
self.vcns_driver.update_ipsec_config(
|
||||||
|
edge_id, sites, enabled=vpn_service.admin_state_up)
|
||||||
|
except exceptions.VcnsBadRequest:
|
||||||
|
LOG.exception(_("Bad or unsupported Input request!"))
|
||||||
|
raise
|
||||||
|
except exceptions.VcnsApiException:
|
||||||
|
msg = (_("Failed to update ipsec VPN configuration "
|
||||||
|
"with vpnservice: %(vpnservice_id)s on vShield Edge: "
|
||||||
|
"%(edge_id)s") % {'vpnservice_id': vpnservice_id,
|
||||||
|
'edge_id': edge_id})
|
||||||
|
LOG.exception(msg)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def create_vpnservice(self, context, vpnservice):
|
||||||
|
LOG.debug(_("create_vpnservice() called"))
|
||||||
|
router_id = vpnservice['vpnservice'].get('router_id')
|
||||||
|
if not self._is_advanced_service_router(context, router_id):
|
||||||
|
msg = _("router_id:%s is not an advanced router!") % router_id
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise exceptions.VcnsBadRequest(resource='router', msg=msg)
|
||||||
|
|
||||||
|
if self.get_vpnservices(context, filters={'router_id': [router_id]}):
|
||||||
|
msg = _("a vpnservice is already associated with the router: %s"
|
||||||
|
) % router_id
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise nsx_exc.ServiceOverQuota(
|
||||||
|
overs='vpnservice', err_msg=msg)
|
||||||
|
|
||||||
|
service = super(NvpAdvancedPlugin, self).create_vpnservice(
|
||||||
|
context, vpnservice)
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.VPNService,
|
||||||
|
service['id'], service_constants.ACTIVE, service)
|
||||||
|
return service
|
||||||
|
|
||||||
|
def update_vpnservice(self, context, vpnservice_id, vpnservice):
|
||||||
|
vpnservice['vpnservice']['status'] = service_constants.PENDING_UPDATE
|
||||||
|
service = super(NvpAdvancedPlugin, self).update_vpnservice(
|
||||||
|
context, vpnservice_id, vpnservice)
|
||||||
|
# Only admin_state_up attribute is configurable on Edge.
|
||||||
|
if vpnservice['vpnservice'].get('admin_state_up') is None:
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.VPNService,
|
||||||
|
service['id'], service_constants.ACTIVE, service)
|
||||||
|
return service
|
||||||
|
# Test whether there is one ipsec site connection attached to
|
||||||
|
# the vpnservice. If not, just return without updating ipsec
|
||||||
|
# config on edge side.
|
||||||
|
vpn_service_db = self._get_vpnservice(context, vpnservice_id)
|
||||||
|
if not vpn_service_db.ipsec_site_connections:
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.VPNService,
|
||||||
|
service['id'], service_constants.ACTIVE, service)
|
||||||
|
return service
|
||||||
|
try:
|
||||||
|
self._vcns_update_ipsec_config(context, service['id'])
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.VPNService,
|
||||||
|
service['id'], service_constants.ERROR, service)
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.VPNService,
|
||||||
|
service['id'], service_constants.ACTIVE, service)
|
||||||
|
return service
|
||||||
|
|
||||||
|
def create_ipsec_site_connection(self, context, ipsec_site_connection):
|
||||||
|
ipsec_site_conn = super(
|
||||||
|
NvpAdvancedPlugin, self).create_ipsec_site_connection(
|
||||||
|
context, ipsec_site_connection)
|
||||||
|
try:
|
||||||
|
self._vcns_update_ipsec_config(
|
||||||
|
context, ipsec_site_conn['vpnservice_id'])
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
super(NvpAdvancedPlugin, self).delete_ipsec_site_connection(
|
||||||
|
context, ipsec_site_conn['id'])
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.IPsecSiteConnection,
|
||||||
|
ipsec_site_conn['id'], service_constants.ACTIVE, ipsec_site_conn)
|
||||||
|
return ipsec_site_conn
|
||||||
|
|
||||||
|
def update_ipsec_site_connection(self, context, ipsec_site_connection_id,
|
||||||
|
ipsec_site_connection):
|
||||||
|
ipsec_site_connection['ipsec_site_connection']['status'] = (
|
||||||
|
service_constants.PENDING_UPDATE)
|
||||||
|
ipsec_site_conn = super(
|
||||||
|
NvpAdvancedPlugin, self).update_ipsec_site_connection(
|
||||||
|
context, ipsec_site_connection_id, ipsec_site_connection)
|
||||||
|
try:
|
||||||
|
self._vcns_update_ipsec_config(
|
||||||
|
context, ipsec_site_conn['vpnservice_id'])
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.IPsecSiteConnection, ipsec_site_conn['id'],
|
||||||
|
service_constants.ERROR, ipsec_site_conn)
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.IPsecSiteConnection,
|
||||||
|
ipsec_site_conn['id'], service_constants.ACTIVE, ipsec_site_conn)
|
||||||
|
return ipsec_site_conn
|
||||||
|
|
||||||
|
def delete_ipsec_site_connection(self, context, ipsec_site_conn_id):
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.IPsecSiteConnection,
|
||||||
|
ipsec_site_conn_id, service_constants.PENDING_DELETE)
|
||||||
|
vpnservice_id = self.get_ipsec_site_connection(
|
||||||
|
context, ipsec_site_conn_id)['vpnservice_id']
|
||||||
|
try:
|
||||||
|
self._vcns_update_ipsec_config(
|
||||||
|
context, vpnservice_id, ipsec_site_conn_id)
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
self._resource_set_status(
|
||||||
|
context, vpn_db.IPsecSiteConnection, ipsec_site_conn_id,
|
||||||
|
service_constants.ERROR)
|
||||||
|
super(NvpAdvancedPlugin, self).delete_ipsec_site_connection(
|
||||||
|
context, ipsec_site_conn_id)
|
||||||
|
|
||||||
|
|
||||||
class VcnsCallbacks(object):
|
class VcnsCallbacks(object):
|
||||||
"""Edge callback implementation Callback functions for
|
"""Edge callback implementation Callback functions for
|
||||||
|
149
neutron/plugins/vmware/vshield/edge_ipsecvpn_driver.py
Normal file
149
neutron/plugins/vmware/vshield/edge_ipsecvpn_driver.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
# Copyright 2014 VMware, 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.openstack.common import log as logging
|
||||||
|
from neutron.plugins.vmware.vshield.common import (
|
||||||
|
exceptions as vcns_exc)
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
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',)
|
||||||
|
|
||||||
|
|
||||||
|
class EdgeIPsecVpnDriver():
|
||||||
|
|
||||||
|
"""Driver APIs for Edge IPsec VPN bulk configuration."""
|
||||||
|
|
||||||
|
def _check_ikepolicy_ipsecpolicy_allowed(self, ikepolicy, ipsecpolicy):
|
||||||
|
"""Check whether ikepolicy and ipsecpolicy are allowed on vshield edge.
|
||||||
|
|
||||||
|
Some IPsec VPN configurations and features are configured by default or
|
||||||
|
not supported on vshield edge.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Check validation of IKEPolicy.
|
||||||
|
if ikepolicy['ike_version'] != 'v1':
|
||||||
|
msg = _("Unsupported ike_version: %s! Only 'v1' ike version is "
|
||||||
|
"supported on vshield Edge!"
|
||||||
|
) % ikepolicy['ike_version']
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise vcns_exc.VcnsBadRequest(resource='ikepolicy',
|
||||||
|
msg=msg)
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
if (ikepolicy['auth_algorithm'] != ipsecpolicy['auth_algorithm'] or
|
||||||
|
ikepolicy['encryption_algorithm'] != ipsecpolicy[
|
||||||
|
'encryption_algorithm'] or
|
||||||
|
ikepolicy['pfs'] != ipsecpolicy['pfs']):
|
||||||
|
msg = _("IKEPolicy and IPsecPolicy should have consistent "
|
||||||
|
"auth_algorithm, encryption_algorithm and pfs for VSE!")
|
||||||
|
LOG.warning(msg)
|
||||||
|
|
||||||
|
# Check whether encryption_algorithm is allowed.
|
||||||
|
encryption_algorithm = ENCRYPTION_ALGORITHM_MAP.get(
|
||||||
|
ipsecpolicy.get('encryption_algorithm'), None)
|
||||||
|
if not encryption_algorithm:
|
||||||
|
msg = _("Unsupported encryption_algorithm: %s! '3des', "
|
||||||
|
"'aes-128' and 'aes-256' are supported on VSE right now."
|
||||||
|
) % ipsecpolicy['encryption_algorithm']
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise vcns_exc.VcnsBadRequest(resource='ipsecpolicy',
|
||||||
|
msg=msg)
|
||||||
|
|
||||||
|
# Check whether pfs is allowed.
|
||||||
|
if not PFS_MAP.get(ipsecpolicy['pfs']):
|
||||||
|
msg = _("Unsupported pfs: %s! 'group2' and 'group5' "
|
||||||
|
"are supported on VSE right now.") % ipsecpolicy['pfs']
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise vcns_exc.VcnsBadRequest(resource='ipsecpolicy',
|
||||||
|
msg=msg)
|
||||||
|
|
||||||
|
# Check whether transform protocol is allowed.
|
||||||
|
if ipsecpolicy['transform_protocol'] not in TRANSFORM_PROTOCOL_ALLOWED:
|
||||||
|
msg = _("Unsupported transform protocol: %s! 'esp' is supported "
|
||||||
|
"by default on VSE right now."
|
||||||
|
) % ipsecpolicy['transform_protocol']
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise vcns_exc.VcnsBadRequest(resource='ipsecpolicy',
|
||||||
|
msg=msg)
|
||||||
|
|
||||||
|
# Check whether encapsulation mode is allowed.
|
||||||
|
if ipsecpolicy['encapsulation_mode'] not in ENCAPSULATION_MODE_ALLOWED:
|
||||||
|
msg = _("Unsupported encapsulation mode: %s! 'tunnel' is "
|
||||||
|
"supported by default on VSE right now."
|
||||||
|
) % ipsecpolicy['encapsulation_mode']
|
||||||
|
LOG.warning(msg)
|
||||||
|
raise vcns_exc.VcnsBadRequest(resource='ipsecpolicy',
|
||||||
|
msg=msg)
|
||||||
|
|
||||||
|
def _convert_ipsec_site(self, site, enablePfs=True):
|
||||||
|
self._check_ikepolicy_ipsecpolicy_allowed(
|
||||||
|
site['ikepolicy'], site['ipsecpolicy'])
|
||||||
|
return {
|
||||||
|
'enabled': site['site'].get('admin_state_up'),
|
||||||
|
'enablePfs': enablePfs,
|
||||||
|
'dhGroup': PFS_MAP.get(site['ipsecpolicy']['pfs']),
|
||||||
|
'name': site['site'].get('name'),
|
||||||
|
'description': site['site'].get('description'),
|
||||||
|
'localId': site['external_ip'],
|
||||||
|
'localIp': site['external_ip'],
|
||||||
|
'peerId': site['site'].get('peer_id'),
|
||||||
|
'peerIp': site['site'].get('peer_address'),
|
||||||
|
'localSubnets': {
|
||||||
|
'subnets': [site['subnet'].get('cidr')]},
|
||||||
|
'peerSubnets': {
|
||||||
|
'subnets': site['site'].get('peer_cidrs')},
|
||||||
|
'authenticationMode': site['site'].get('auth_mode'),
|
||||||
|
'psk': site['site'].get('psk'),
|
||||||
|
'encryptionAlgorithm': ENCRYPTION_ALGORITHM_MAP.get(
|
||||||
|
site['ipsecpolicy'].get('encryption_algorithm'))}
|
||||||
|
|
||||||
|
def update_ipsec_config(self, edge_id, sites, enabled=True):
|
||||||
|
ipsec_config = {'featureType': "ipsec_4.0",
|
||||||
|
'enabled': enabled}
|
||||||
|
vse_sites = [self._convert_ipsec_site(site) for site in sites]
|
||||||
|
ipsec_config['sites'] = {'sites': vse_sites}
|
||||||
|
try:
|
||||||
|
self.vcns.update_ipsec_config(edge_id, ipsec_config)
|
||||||
|
except vcns_exc.VcnsApiException:
|
||||||
|
LOG.exception(_("Failed to update ipsec vpn configuration "
|
||||||
|
"with edge_id: %s"), edge_id)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def delete_ipsec_config(self, edge_id):
|
||||||
|
try:
|
||||||
|
self.vcns.delete_ipsec_config(edge_id)
|
||||||
|
except vcns_exc.ResourceNotFound:
|
||||||
|
LOG.warning(_("IPsec config not found on edge: %s"), edge_id)
|
||||||
|
except vcns_exc.VcnsApiException:
|
||||||
|
LOG.exception(_("Failed to delete ipsec vpn configuration "
|
||||||
|
"with edge_id: %s"), edge_id)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def get_ipsec_config(self, edge_id):
|
||||||
|
return self.vcns.get_ipsec_config(edge_id)
|
@ -39,6 +39,9 @@ POOL_RESOURCE = "pools"
|
|||||||
MONITOR_RESOURCE = "monitors"
|
MONITOR_RESOURCE = "monitors"
|
||||||
APP_PROFILE_RESOURCE = "applicationprofiles"
|
APP_PROFILE_RESOURCE = "applicationprofiles"
|
||||||
|
|
||||||
|
# IPsec VPNaaS Constants
|
||||||
|
IPSEC_VPN_SERVICE = 'ipsec/config'
|
||||||
|
|
||||||
|
|
||||||
class Vcns(object):
|
class Vcns(object):
|
||||||
|
|
||||||
@ -264,6 +267,18 @@ class Vcns(object):
|
|||||||
app_profileid)
|
app_profileid)
|
||||||
return self.do_request(HTTP_DELETE, uri)
|
return self.do_request(HTTP_DELETE, uri)
|
||||||
|
|
||||||
|
def update_ipsec_config(self, edge_id, ipsec_config):
|
||||||
|
uri = self._build_uri_path(edge_id, IPSEC_VPN_SERVICE)
|
||||||
|
return self.do_request(HTTP_PUT, uri, ipsec_config)
|
||||||
|
|
||||||
|
def delete_ipsec_config(self, edge_id):
|
||||||
|
uri = self._build_uri_path(edge_id, IPSEC_VPN_SERVICE)
|
||||||
|
return self.do_request(HTTP_DELETE, uri)
|
||||||
|
|
||||||
|
def get_ipsec_config(self, edge_id):
|
||||||
|
uri = self._build_uri_path(edge_id, IPSEC_VPN_SERVICE)
|
||||||
|
return self.do_request(HTTP_GET, uri)
|
||||||
|
|
||||||
def _build_uri_path(self, edge_id,
|
def _build_uri_path(self, edge_id,
|
||||||
service,
|
service,
|
||||||
resource=None,
|
resource=None,
|
||||||
|
@ -22,6 +22,7 @@ from neutron.openstack.common import log as logging
|
|||||||
from neutron.plugins.vmware.common import config # noqa
|
from neutron.plugins.vmware.common import config # noqa
|
||||||
from neutron.plugins.vmware.vshield import edge_appliance_driver
|
from neutron.plugins.vmware.vshield import edge_appliance_driver
|
||||||
from neutron.plugins.vmware.vshield import edge_firewall_driver
|
from neutron.plugins.vmware.vshield import edge_firewall_driver
|
||||||
|
from neutron.plugins.vmware.vshield import edge_ipsecvpn_driver
|
||||||
from neutron.plugins.vmware.vshield import edge_loadbalancer_driver
|
from neutron.plugins.vmware.vshield import edge_loadbalancer_driver
|
||||||
from neutron.plugins.vmware.vshield.tasks import tasks
|
from neutron.plugins.vmware.vshield.tasks import tasks
|
||||||
from neutron.plugins.vmware.vshield import vcns
|
from neutron.plugins.vmware.vshield import vcns
|
||||||
@ -31,7 +32,8 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver,
|
class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver,
|
||||||
edge_firewall_driver.EdgeFirewallDriver,
|
edge_firewall_driver.EdgeFirewallDriver,
|
||||||
edge_loadbalancer_driver.EdgeLbDriver):
|
edge_loadbalancer_driver.EdgeLbDriver,
|
||||||
|
edge_ipsecvpn_driver.EdgeIPsecVpnDriver):
|
||||||
|
|
||||||
def __init__(self, callbacks):
|
def __init__(self, callbacks):
|
||||||
super(VcnsDriver, self).__init__()
|
super(VcnsDriver, self).__init__()
|
||||||
|
@ -32,6 +32,7 @@ from neutron.db.vpn import vpn_db
|
|||||||
from neutron import extensions
|
from neutron import extensions
|
||||||
from neutron.extensions import vpnaas
|
from neutron.extensions import vpnaas
|
||||||
from neutron import manager
|
from neutron import manager
|
||||||
|
from neutron.openstack.common import uuidutils
|
||||||
from neutron.plugins.common import constants
|
from neutron.plugins.common import constants
|
||||||
from neutron.scheduler import l3_agent_scheduler
|
from neutron.scheduler import l3_agent_scheduler
|
||||||
from neutron.services.vpn import plugin as vpn_plugin
|
from neutron.services.vpn import plugin as vpn_plugin
|
||||||
@ -55,34 +56,13 @@ class TestVpnCorePlugin(test_l3_plugin.TestL3NatIntPlugin,
|
|||||||
self.router_scheduler = l3_agent_scheduler.ChanceScheduler()
|
self.router_scheduler = l3_agent_scheduler.ChanceScheduler()
|
||||||
|
|
||||||
|
|
||||||
class VPNPluginDbTestCase(test_l3_plugin.L3NatTestCaseMixin,
|
class VPNTestMixin(object):
|
||||||
test_db_plugin.NeutronDbPluginV2TestCase):
|
|
||||||
resource_prefix_map = dict(
|
resource_prefix_map = dict(
|
||||||
(k.replace('_', '-'),
|
(k.replace('_', '-'),
|
||||||
constants.COMMON_PREFIXES[constants.VPN])
|
constants.COMMON_PREFIXES[constants.VPN])
|
||||||
for k in vpnaas.RESOURCE_ATTRIBUTE_MAP
|
for k in vpnaas.RESOURCE_ATTRIBUTE_MAP
|
||||||
)
|
)
|
||||||
|
|
||||||
def setUp(self, core_plugin=None, vpnaas_plugin=DB_VPN_PLUGIN_KLASS):
|
|
||||||
service_plugins = {'vpnaas_plugin': vpnaas_plugin}
|
|
||||||
plugin_str = ('neutron.tests.unit.db.vpn.'
|
|
||||||
'test_db_vpnaas.TestVpnCorePlugin')
|
|
||||||
|
|
||||||
super(VPNPluginDbTestCase, self).setUp(
|
|
||||||
plugin_str,
|
|
||||||
service_plugins=service_plugins
|
|
||||||
)
|
|
||||||
self._subnet_id = "0c798ed8-33ba-11e2-8b28-000c291c4d14"
|
|
||||||
self.core_plugin = TestVpnCorePlugin
|
|
||||||
self.plugin = vpn_plugin.VPNPlugin()
|
|
||||||
ext_mgr = PluginAwareExtensionManager(
|
|
||||||
extensions_path,
|
|
||||||
{constants.CORE: self.core_plugin,
|
|
||||||
constants.VPN: self.plugin}
|
|
||||||
)
|
|
||||||
app = config.load_paste_app('extensions_test_app')
|
|
||||||
self.ext_api = ExtensionMiddleware(app, ext_mgr=ext_mgr)
|
|
||||||
|
|
||||||
def _create_ikepolicy(self, fmt,
|
def _create_ikepolicy(self, fmt,
|
||||||
name='ikepolicy1',
|
name='ikepolicy1',
|
||||||
auth_algorithm='sha1',
|
auth_algorithm='sha1',
|
||||||
@ -410,6 +390,53 @@ class VPNPluginDbTestCase(test_l3_plugin.L3NatTestCaseMixin,
|
|||||||
'ipsec_site_connection']['id']
|
'ipsec_site_connection']['id']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _check_ipsec_site_connection(self, ipsec_site_connection, keys, dpd):
|
||||||
|
self.assertEqual(
|
||||||
|
keys,
|
||||||
|
dict((k, v) for k, v
|
||||||
|
in ipsec_site_connection.items()
|
||||||
|
if k in keys))
|
||||||
|
self.assertEqual(
|
||||||
|
dpd,
|
||||||
|
dict((k, v) for k, v
|
||||||
|
in ipsec_site_connection['dpd'].items()
|
||||||
|
if k in dpd))
|
||||||
|
|
||||||
|
def _set_active(self, model, resource_id):
|
||||||
|
service_plugin = manager.NeutronManager.get_service_plugins()[
|
||||||
|
constants.VPN]
|
||||||
|
adminContext = context.get_admin_context()
|
||||||
|
with adminContext.session.begin(subtransactions=True):
|
||||||
|
resource_db = service_plugin._get_resource(
|
||||||
|
adminContext,
|
||||||
|
model,
|
||||||
|
resource_id)
|
||||||
|
resource_db.status = constants.ACTIVE
|
||||||
|
|
||||||
|
|
||||||
|
class VPNPluginDbTestCase(VPNTestMixin,
|
||||||
|
test_l3_plugin.L3NatTestCaseMixin,
|
||||||
|
test_db_plugin.NeutronDbPluginV2TestCase):
|
||||||
|
def setUp(self, core_plugin=None, vpnaas_plugin=DB_VPN_PLUGIN_KLASS):
|
||||||
|
service_plugins = {'vpnaas_plugin': vpnaas_plugin}
|
||||||
|
plugin_str = ('neutron.tests.unit.db.vpn.'
|
||||||
|
'test_db_vpnaas.TestVpnCorePlugin')
|
||||||
|
|
||||||
|
super(VPNPluginDbTestCase, self).setUp(
|
||||||
|
plugin_str,
|
||||||
|
service_plugins=service_plugins
|
||||||
|
)
|
||||||
|
self._subnet_id = uuidutils.generate_uuid()
|
||||||
|
self.core_plugin = TestVpnCorePlugin
|
||||||
|
self.plugin = vpn_plugin.VPNPlugin()
|
||||||
|
ext_mgr = PluginAwareExtensionManager(
|
||||||
|
extensions_path,
|
||||||
|
{constants.CORE: self.core_plugin,
|
||||||
|
constants.VPN: self.plugin}
|
||||||
|
)
|
||||||
|
app = config.load_paste_app('extensions_test_app')
|
||||||
|
self.ext_api = ExtensionMiddleware(app, ext_mgr=ext_mgr)
|
||||||
|
|
||||||
|
|
||||||
class TestVpnaas(VPNPluginDbTestCase):
|
class TestVpnaas(VPNPluginDbTestCase):
|
||||||
|
|
||||||
@ -890,17 +917,6 @@ class TestVpnaas(VPNPluginDbTestCase):
|
|||||||
self._delete('routers', router['router']['id'],
|
self._delete('routers', router['router']['id'],
|
||||||
expected_code=webob.exc.HTTPConflict.code)
|
expected_code=webob.exc.HTTPConflict.code)
|
||||||
|
|
||||||
def _set_active(self, model, resource_id):
|
|
||||||
service_plugin = manager.NeutronManager.get_service_plugins()[
|
|
||||||
constants.VPN]
|
|
||||||
adminContext = context.get_admin_context()
|
|
||||||
with adminContext.session.begin(subtransactions=True):
|
|
||||||
resource_db = service_plugin._get_resource(
|
|
||||||
adminContext,
|
|
||||||
model,
|
|
||||||
resource_id)
|
|
||||||
resource_db.status = constants.ACTIVE
|
|
||||||
|
|
||||||
def test_update_vpnservice(self):
|
def test_update_vpnservice(self):
|
||||||
"""Test case to update a vpnservice."""
|
"""Test case to update a vpnservice."""
|
||||||
name = 'new_vpnservice1'
|
name = 'new_vpnservice1'
|
||||||
@ -1198,18 +1214,6 @@ class TestVpnaas(VPNPluginDbTestCase):
|
|||||||
setup_overrides=ipv6_setup_params,
|
setup_overrides=ipv6_setup_params,
|
||||||
expected_status_int=400)
|
expected_status_int=400)
|
||||||
|
|
||||||
def _check_ipsec_site_connection(self, ipsec_site_connection, keys, dpd):
|
|
||||||
self.assertEqual(
|
|
||||||
keys,
|
|
||||||
dict((k, v) for k, v
|
|
||||||
in ipsec_site_connection.items()
|
|
||||||
if k in keys))
|
|
||||||
self.assertEqual(
|
|
||||||
dpd,
|
|
||||||
dict((k, v) for k, v
|
|
||||||
in ipsec_site_connection['dpd'].items()
|
|
||||||
if k in dpd))
|
|
||||||
|
|
||||||
def test_delete_ipsec_site_connection(self):
|
def test_delete_ipsec_site_connection(self):
|
||||||
"""Test case to delete a ipsec_site_connection."""
|
"""Test case to delete a ipsec_site_connection."""
|
||||||
with self.ipsec_site_connection(
|
with self.ipsec_site_connection(
|
||||||
|
@ -455,11 +455,6 @@ class L3NatTest(test_l3_plugin.L3BaseForIntTests, NsxPluginV2TestCase):
|
|||||||
plugin_instance.__class__.__name__)
|
plugin_instance.__class__.__name__)
|
||||||
self._plugin_class = plugin_instance.__class__
|
self._plugin_class = plugin_instance.__class__
|
||||||
|
|
||||||
|
|
||||||
class TestL3NatTestCase(L3NatTest,
|
|
||||||
test_l3_plugin.L3NatDBIntTestCase,
|
|
||||||
NsxPluginV2TestCase):
|
|
||||||
|
|
||||||
def _create_l3_ext_network(self, vlan_id=None):
|
def _create_l3_ext_network(self, vlan_id=None):
|
||||||
name = 'l3_ext_net'
|
name = 'l3_ext_net'
|
||||||
net_type = NetworkTypes.L3_EXT
|
net_type = NetworkTypes.L3_EXT
|
||||||
@ -474,6 +469,11 @@ class TestL3NatTestCase(L3NatTest,
|
|||||||
pnet.PHYSICAL_NETWORK,
|
pnet.PHYSICAL_NETWORK,
|
||||||
pnet.SEGMENTATION_ID))
|
pnet.SEGMENTATION_ID))
|
||||||
|
|
||||||
|
|
||||||
|
class TestL3NatTestCase(L3NatTest,
|
||||||
|
test_l3_plugin.L3NatDBIntTestCase,
|
||||||
|
NsxPluginV2TestCase):
|
||||||
|
|
||||||
def _test_create_l3_ext_network(self, vlan_id=None):
|
def _test_create_l3_ext_network(self, vlan_id=None):
|
||||||
name = 'l3_ext_net'
|
name = 'l3_ext_net'
|
||||||
net_type = NetworkTypes.L3_EXT
|
net_type = NetworkTypes.L3_EXT
|
||||||
|
@ -44,6 +44,11 @@ class FakeVcns(object):
|
|||||||
"firewallRules": []
|
"firewallRules": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.fake_ipsecvpn_dict = {}
|
||||||
|
self.temp_ipsecvpn = {
|
||||||
|
'featureType': "ipsec_4.0",
|
||||||
|
'enabled': True,
|
||||||
|
'sites': {'sites': []}}
|
||||||
self._fake_virtualservers_dict = {}
|
self._fake_virtualservers_dict = {}
|
||||||
self._fake_pools_dict = {}
|
self._fake_pools_dict = {}
|
||||||
self._fake_monitors_dict = {}
|
self._fake_monitors_dict = {}
|
||||||
@ -364,9 +369,6 @@ class FakeVcns(object):
|
|||||||
break
|
break
|
||||||
return self.return_helper(header, response)
|
return self.return_helper(header, response)
|
||||||
|
|
||||||
#
|
|
||||||
#Fake Edge LBAAS call
|
|
||||||
#
|
|
||||||
def create_vip(self, edge_id, vip_new):
|
def create_vip(self, edge_id, vip_new):
|
||||||
if not self._fake_virtualservers_dict.get(edge_id):
|
if not self._fake_virtualservers_dict.get(edge_id):
|
||||||
self._fake_virtualservers_dict[edge_id] = {}
|
self._fake_virtualservers_dict[edge_id] = {}
|
||||||
@ -525,6 +527,27 @@ class FakeVcns(object):
|
|||||||
response['config'] = self._fake_loadbalancer_config[edge_id]
|
response['config'] = self._fake_loadbalancer_config[edge_id]
|
||||||
return self.return_helper(header, response)
|
return self.return_helper(header, response)
|
||||||
|
|
||||||
|
def update_ipsec_config(self, edge_id, ipsec_config):
|
||||||
|
self.fake_ipsecvpn_dict[edge_id] = ipsec_config
|
||||||
|
header = {'status': 204}
|
||||||
|
response = ""
|
||||||
|
return self.return_helper(header, response)
|
||||||
|
|
||||||
|
def delete_ipsec_config(self, edge_id):
|
||||||
|
header = {'status': 404}
|
||||||
|
if edge_id in self.fake_ipsecvpn_dict:
|
||||||
|
header = {'status': 204}
|
||||||
|
del self.fake_ipsecvpn_dict[edge_id]
|
||||||
|
response = ""
|
||||||
|
return self.return_helper(header, response)
|
||||||
|
|
||||||
|
def get_ipsec_config(self, edge_id):
|
||||||
|
if edge_id not in self.fake_ipsecvpn_dict:
|
||||||
|
self.fake_ipsecvpn_dict[edge_id] = self.temp_ipsecvpn
|
||||||
|
header = {'status': 204}
|
||||||
|
response = self.fake_ipsecvpn_dict[edge_id]
|
||||||
|
return self.return_helper(header, response)
|
||||||
|
|
||||||
def enable_service_loadbalancer(self, edge_id, config):
|
def enable_service_loadbalancer(self, edge_id, config):
|
||||||
header = {'status': 204}
|
header = {'status': 204}
|
||||||
response = ""
|
response = ""
|
||||||
|
372
neutron/tests/unit/vmware/vshield/test_vpnaas_plugin.py
Normal file
372
neutron/tests/unit/vmware/vshield/test_vpnaas_plugin.py
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
# Copyright 2014 VMware, 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.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import webob.exc
|
||||||
|
|
||||||
|
from neutron.api.v2 import attributes
|
||||||
|
from neutron.db.vpn import vpn_db
|
||||||
|
from neutron.extensions import vpnaas
|
||||||
|
from neutron import manager
|
||||||
|
from neutron.openstack.common import uuidutils
|
||||||
|
from neutron.tests.unit.db.vpn import test_db_vpnaas
|
||||||
|
from neutron.tests.unit.vmware.vshield import test_edge_router
|
||||||
|
|
||||||
|
_uuid = uuidutils.generate_uuid
|
||||||
|
|
||||||
|
|
||||||
|
class VPNTestExtensionManager(
|
||||||
|
test_edge_router.ServiceRouterTestExtensionManager):
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
|
# If l3 resources have been loaded and updated by main API
|
||||||
|
# router, update the map in the l3 extension so it will load
|
||||||
|
# the same attributes as the API router
|
||||||
|
resources = super(VPNTestExtensionManager, self).get_resources()
|
||||||
|
vpn_attr_map = copy.deepcopy(vpnaas.RESOURCE_ATTRIBUTE_MAP)
|
||||||
|
for res in vpnaas.RESOURCE_ATTRIBUTE_MAP.keys():
|
||||||
|
attr_info = attributes.RESOURCE_ATTRIBUTE_MAP.get(res)
|
||||||
|
if attr_info:
|
||||||
|
vpnaas.RESOURCE_ATTRIBUTE_MAP[res] = attr_info
|
||||||
|
vpn_resources = vpnaas.Vpnaas.get_resources()
|
||||||
|
# restore the original resources once the controllers are created
|
||||||
|
vpnaas.RESOURCE_ATTRIBUTE_MAP = vpn_attr_map
|
||||||
|
resources.extend(vpn_resources)
|
||||||
|
return resources
|
||||||
|
|
||||||
|
|
||||||
|
class TestVpnPlugin(test_db_vpnaas.VPNTestMixin,
|
||||||
|
test_edge_router.ServiceRouterTest):
|
||||||
|
|
||||||
|
def vcns_vpn_patch(self):
|
||||||
|
instance = self.vcns_instance
|
||||||
|
instance.return_value.update_ipsec_config.side_effect = (
|
||||||
|
self.fc2.update_ipsec_config)
|
||||||
|
instance.return_value.get_ipsec_config.side_effect = (
|
||||||
|
self.fc2.get_ipsec_config)
|
||||||
|
instance.return_value.delete_ipsec_config.side_effect = (
|
||||||
|
self.fc2.delete_ipsec_config)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# Save the global RESOURCE_ATTRIBUTE_MAP
|
||||||
|
self.saved_attr_map = {}
|
||||||
|
for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.items():
|
||||||
|
self.saved_attr_map[resource] = attrs.copy()
|
||||||
|
|
||||||
|
super(TestVpnPlugin, self).setUp(ext_mgr=VPNTestExtensionManager())
|
||||||
|
self.vcns_vpn_patch()
|
||||||
|
self.plugin = manager.NeutronManager.get_plugin()
|
||||||
|
self.router_id = None
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestVpnPlugin, self).tearDown()
|
||||||
|
# Restore the global RESOURCE_ATTRIBUTE_MAP
|
||||||
|
attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
|
||||||
|
self.ext_api = None
|
||||||
|
self.plugin = None
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def router(self, vlan_id=None):
|
||||||
|
with self._create_l3_ext_network(vlan_id) as net:
|
||||||
|
with self.subnet(cidr='100.0.0.0/24', network=net) as s:
|
||||||
|
data = {'router': {'tenant_id': self._tenant_id}}
|
||||||
|
data['router']['service_router'] = True
|
||||||
|
router_req = self.new_create_request('routers', data, self.fmt)
|
||||||
|
try:
|
||||||
|
res = router_req.get_response(self.ext_api)
|
||||||
|
router = self.deserialize(self.fmt, res)
|
||||||
|
self._add_external_gateway_to_router(
|
||||||
|
router['router']['id'],
|
||||||
|
s['subnet']['network_id'])
|
||||||
|
router = self._show('routers', router['router']['id'])
|
||||||
|
yield router
|
||||||
|
finally:
|
||||||
|
self._delete('routers', router['router']['id'])
|
||||||
|
|
||||||
|
def test_create_vpnservice(self, **extras):
|
||||||
|
"""Test case to create a vpnservice."""
|
||||||
|
description = 'my-vpn-service'
|
||||||
|
expected = {'name': 'vpnservice1',
|
||||||
|
'description': 'my-vpn-service',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'tenant_id': self._tenant_id, }
|
||||||
|
|
||||||
|
expected.update(extras)
|
||||||
|
with self.subnet(cidr='10.2.0.0/24') as subnet:
|
||||||
|
with self.router() as router:
|
||||||
|
expected['router_id'] = router['router']['id']
|
||||||
|
expected['subnet_id'] = subnet['subnet']['id']
|
||||||
|
name = expected['name']
|
||||||
|
with self.vpnservice(name=name,
|
||||||
|
subnet=subnet,
|
||||||
|
router=router,
|
||||||
|
description=description,
|
||||||
|
**extras) as vpnservice:
|
||||||
|
self.assertEqual(dict((k, v) for k, v in
|
||||||
|
vpnservice['vpnservice'].items()
|
||||||
|
if k in expected),
|
||||||
|
expected)
|
||||||
|
|
||||||
|
def test_create_vpnservices_with_same_router(self, **extras):
|
||||||
|
"""Test case to create two vpnservices with same router."""
|
||||||
|
with self.subnet(cidr='10.2.0.0/24') as subnet:
|
||||||
|
with self.router() as router:
|
||||||
|
with self.vpnservice(name='vpnservice1',
|
||||||
|
subnet=subnet,
|
||||||
|
router=router):
|
||||||
|
res = self._create_vpnservice(
|
||||||
|
'json', 'vpnservice2', True,
|
||||||
|
router_id=(router['router']['id']),
|
||||||
|
subnet_id=(subnet['subnet']['id']))
|
||||||
|
self.assertEqual(
|
||||||
|
res.status_int, webob.exc.HTTPConflict.code)
|
||||||
|
|
||||||
|
def test_update_vpnservice(self):
|
||||||
|
"""Test case to update a vpnservice."""
|
||||||
|
name = 'new_vpnservice1'
|
||||||
|
expected = [('name', name)]
|
||||||
|
with contextlib.nested(
|
||||||
|
self.subnet(cidr='10.2.0.0/24'),
|
||||||
|
self.router()) as (subnet, router):
|
||||||
|
with self.vpnservice(name=name,
|
||||||
|
subnet=subnet,
|
||||||
|
router=router) as vpnservice:
|
||||||
|
expected.append(('subnet_id',
|
||||||
|
vpnservice['vpnservice']['subnet_id']))
|
||||||
|
expected.append(('router_id',
|
||||||
|
vpnservice['vpnservice']['router_id']))
|
||||||
|
data = {'vpnservice': {'name': name,
|
||||||
|
'admin_state_up': False}}
|
||||||
|
expected.append(('admin_state_up', False))
|
||||||
|
self._set_active(vpn_db.VPNService,
|
||||||
|
vpnservice['vpnservice']['id'])
|
||||||
|
req = self.new_update_request(
|
||||||
|
'vpnservices',
|
||||||
|
data,
|
||||||
|
vpnservice['vpnservice']['id'])
|
||||||
|
res = self.deserialize(self.fmt,
|
||||||
|
req.get_response(self.ext_api))
|
||||||
|
for k, v in expected:
|
||||||
|
self.assertEqual(res['vpnservice'][k], v)
|
||||||
|
|
||||||
|
def _test_create_ipsec_site_connection(self, key_overrides=None,
|
||||||
|
ike_key_overrides=None,
|
||||||
|
ipsec_key_overrides=None,
|
||||||
|
setup_overrides=None,
|
||||||
|
expected_status_int=200):
|
||||||
|
"""Create ipsec_site_connection and check results."""
|
||||||
|
params = {'ikename': 'ikepolicy1',
|
||||||
|
'ipsecname': 'ipsecpolicy1',
|
||||||
|
'vpnsname': 'vpnservice1',
|
||||||
|
'subnet_cidr': '10.2.0.0/24',
|
||||||
|
'subnet_version': 4}
|
||||||
|
if setup_overrides:
|
||||||
|
params.update(setup_overrides)
|
||||||
|
expected = {'name': 'connection1',
|
||||||
|
'description': 'my-ipsec-connection',
|
||||||
|
'peer_address': '192.168.1.10',
|
||||||
|
'peer_id': '192.168.1.10',
|
||||||
|
'peer_cidrs': ['192.168.2.0/24', '192.168.3.0/24'],
|
||||||
|
'initiator': 'bi-directional',
|
||||||
|
'mtu': 1500,
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'psk': 'abcd',
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'admin_state_up': True}
|
||||||
|
if key_overrides:
|
||||||
|
expected.update(key_overrides)
|
||||||
|
|
||||||
|
ike_expected = {'name': params['ikename'],
|
||||||
|
'auth_algorithm': 'sha1',
|
||||||
|
'encryption_algorithm': 'aes-128',
|
||||||
|
'ike_version': 'v1',
|
||||||
|
'pfs': 'group5'}
|
||||||
|
if ike_key_overrides:
|
||||||
|
ike_expected.update(ike_key_overrides)
|
||||||
|
|
||||||
|
ipsec_expected = {'name': params['ipsecname'],
|
||||||
|
'auth_algorithm': 'sha1',
|
||||||
|
'encryption_algorithm': 'aes-128',
|
||||||
|
'pfs': 'group5'}
|
||||||
|
if ipsec_key_overrides:
|
||||||
|
ipsec_expected.update(ipsec_key_overrides)
|
||||||
|
|
||||||
|
dpd = {'action': 'hold',
|
||||||
|
'interval': 40,
|
||||||
|
'timeout': 120}
|
||||||
|
with contextlib.nested(
|
||||||
|
self.ikepolicy(self.fmt, ike_expected['name'],
|
||||||
|
ike_expected['auth_algorithm'],
|
||||||
|
ike_expected['encryption_algorithm'],
|
||||||
|
ike_version=ike_expected['ike_version'],
|
||||||
|
pfs=ike_expected['pfs']),
|
||||||
|
self.ipsecpolicy(self.fmt, ipsec_expected['name'],
|
||||||
|
ipsec_expected['auth_algorithm'],
|
||||||
|
ipsec_expected['encryption_algorithm'],
|
||||||
|
pfs=ipsec_expected['pfs']),
|
||||||
|
self.subnet(cidr=params['subnet_cidr'],
|
||||||
|
ip_version=params['subnet_version']),
|
||||||
|
self.router()) as (
|
||||||
|
ikepolicy, ipsecpolicy, subnet, router):
|
||||||
|
with self.vpnservice(name=params['vpnsname'], subnet=subnet,
|
||||||
|
router=router) as vpnservice1:
|
||||||
|
expected['ikepolicy_id'] = ikepolicy['ikepolicy']['id']
|
||||||
|
expected['ipsecpolicy_id'] = (
|
||||||
|
ipsecpolicy['ipsecpolicy']['id']
|
||||||
|
)
|
||||||
|
expected['vpnservice_id'] = (
|
||||||
|
vpnservice1['vpnservice']['id']
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
with self.ipsec_site_connection(
|
||||||
|
self.fmt,
|
||||||
|
expected['name'],
|
||||||
|
expected['peer_address'],
|
||||||
|
expected['peer_id'],
|
||||||
|
expected['peer_cidrs'],
|
||||||
|
expected['mtu'],
|
||||||
|
expected['psk'],
|
||||||
|
expected['initiator'],
|
||||||
|
dpd['action'],
|
||||||
|
dpd['interval'],
|
||||||
|
dpd['timeout'],
|
||||||
|
vpnservice1,
|
||||||
|
ikepolicy,
|
||||||
|
ipsecpolicy,
|
||||||
|
expected['admin_state_up'],
|
||||||
|
description=expected['description']
|
||||||
|
) as ipsec_site_connection:
|
||||||
|
if expected_status_int != 200:
|
||||||
|
self.fail("Expected failure on create")
|
||||||
|
self._check_ipsec_site_connection(
|
||||||
|
ipsec_site_connection['ipsec_site_connection'],
|
||||||
|
expected,
|
||||||
|
dpd)
|
||||||
|
except webob.exc.HTTPClientError as ce:
|
||||||
|
self.assertEqual(ce.code, expected_status_int)
|
||||||
|
|
||||||
|
def test_create_ipsec_site_connection(self, **extras):
|
||||||
|
"""Test case to create an ipsec_site_connection."""
|
||||||
|
self._test_create_ipsec_site_connection(key_overrides=extras)
|
||||||
|
|
||||||
|
def test_create_ipsec_site_connection_invalid_ikepolicy(self):
|
||||||
|
self._test_create_ipsec_site_connection(
|
||||||
|
ike_key_overrides={'ike_version': 'v2'},
|
||||||
|
expected_status_int=400)
|
||||||
|
|
||||||
|
def test_create_ipsec_site_connection_invalid_ipsecpolicy(self):
|
||||||
|
self._test_create_ipsec_site_connection(
|
||||||
|
ipsec_key_overrides={'encryption_algorithm': 'aes-192'},
|
||||||
|
expected_status_int=400)
|
||||||
|
self._test_create_ipsec_site_connection(
|
||||||
|
ipsec_key_overrides={'pfs': 'group14'},
|
||||||
|
expected_status_int=400)
|
||||||
|
|
||||||
|
def _test_update_ipsec_site_connection(self,
|
||||||
|
update={'name': 'new name'},
|
||||||
|
overrides=None,
|
||||||
|
expected_status_int=200):
|
||||||
|
"""Creates and then updates ipsec_site_connection."""
|
||||||
|
expected = {'name': 'new_ipsec_site_connection',
|
||||||
|
'ikename': 'ikepolicy1',
|
||||||
|
'ipsecname': 'ipsecpolicy1',
|
||||||
|
'vpnsname': 'vpnservice1',
|
||||||
|
'description': 'my-ipsec-connection',
|
||||||
|
'peer_address': '192.168.1.10',
|
||||||
|
'peer_id': '192.168.1.10',
|
||||||
|
'peer_cidrs': ['192.168.2.0/24', '192.168.3.0/24'],
|
||||||
|
'initiator': 'bi-directional',
|
||||||
|
'mtu': 1500,
|
||||||
|
'tenant_id': self._tenant_id,
|
||||||
|
'psk': 'abcd',
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'action': 'hold',
|
||||||
|
'interval': 40,
|
||||||
|
'timeout': 120,
|
||||||
|
'subnet_cidr': '10.2.0.0/24',
|
||||||
|
'subnet_version': 4,
|
||||||
|
'make_active': True}
|
||||||
|
if overrides:
|
||||||
|
expected.update(overrides)
|
||||||
|
|
||||||
|
with contextlib.nested(
|
||||||
|
self.ikepolicy(name=expected['ikename']),
|
||||||
|
self.ipsecpolicy(name=expected['ipsecname']),
|
||||||
|
self.subnet(cidr=expected['subnet_cidr'],
|
||||||
|
ip_version=expected['subnet_version']),
|
||||||
|
self.router()
|
||||||
|
) as (ikepolicy, ipsecpolicy, subnet, router):
|
||||||
|
with self.vpnservice(name=expected['vpnsname'], subnet=subnet,
|
||||||
|
router=router) as vpnservice1:
|
||||||
|
expected['vpnservice_id'] = vpnservice1['vpnservice']['id']
|
||||||
|
expected['ikepolicy_id'] = ikepolicy['ikepolicy']['id']
|
||||||
|
expected['ipsecpolicy_id'] = ipsecpolicy['ipsecpolicy']['id']
|
||||||
|
with self.ipsec_site_connection(
|
||||||
|
self.fmt,
|
||||||
|
expected['name'],
|
||||||
|
expected['peer_address'],
|
||||||
|
expected['peer_id'],
|
||||||
|
expected['peer_cidrs'],
|
||||||
|
expected['mtu'],
|
||||||
|
expected['psk'],
|
||||||
|
expected['initiator'],
|
||||||
|
expected['action'],
|
||||||
|
expected['interval'],
|
||||||
|
expected['timeout'],
|
||||||
|
vpnservice1,
|
||||||
|
ikepolicy,
|
||||||
|
ipsecpolicy,
|
||||||
|
expected['admin_state_up'],
|
||||||
|
description=expected['description']
|
||||||
|
) as ipsec_site_connection:
|
||||||
|
data = {'ipsec_site_connection': update}
|
||||||
|
if expected.get('make_active'):
|
||||||
|
self._set_active(
|
||||||
|
vpn_db.IPsecSiteConnection,
|
||||||
|
(ipsec_site_connection['ipsec_site_connection']
|
||||||
|
['id']))
|
||||||
|
req = self.new_update_request(
|
||||||
|
'ipsec-site-connections',
|
||||||
|
data,
|
||||||
|
ipsec_site_connection['ipsec_site_connection']['id'])
|
||||||
|
res = req.get_response(self.ext_api)
|
||||||
|
self.assertEqual(expected_status_int, res.status_int)
|
||||||
|
if expected_status_int == 200:
|
||||||
|
res_dict = self.deserialize(self.fmt, res)
|
||||||
|
for k, v in update.items():
|
||||||
|
self.assertEqual(
|
||||||
|
res_dict['ipsec_site_connection'][k], v)
|
||||||
|
|
||||||
|
def test_update_ipsec_site_connection(self):
|
||||||
|
"""Test case for valid updates to IPSec site connection."""
|
||||||
|
dpd = {'action': 'hold',
|
||||||
|
'interval': 40,
|
||||||
|
'timeout': 120}
|
||||||
|
self._test_update_ipsec_site_connection(update={'dpd': dpd})
|
||||||
|
self._test_update_ipsec_site_connection(update={'mtu': 2000})
|
||||||
|
|
||||||
|
def test_delete_ipsec_site_connection(self):
|
||||||
|
"""Test case to delete a ipsec_site_connection."""
|
||||||
|
with self.ipsec_site_connection(
|
||||||
|
no_delete=True) as ipsec_site_connection:
|
||||||
|
req = self.new_delete_request(
|
||||||
|
'ipsec-site-connections',
|
||||||
|
ipsec_site_connection['ipsec_site_connection']['id']
|
||||||
|
)
|
||||||
|
res = req.get_response(self.ext_api)
|
||||||
|
self.assertEqual(res.status_int, 204)
|
Loading…
Reference in New Issue
Block a user