A set of Neutron drivers for the VMware NSX.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

284 lines
12 KiB

# Copyright 2015 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 oslo_log import helpers as log_helpers
from oslo_log import log as logging
from oslo_utils import excutils
from vmware_nsx._i18n import _, _LE
from vmware_nsx.common import exceptions as nsxv_exc
from vmware_nsx.common import locking
from vmware_nsx.db import nsxv_db
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
from vmware_nsx.services.lbaas.nsx_v import lbaas_const as lb_const
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
LOG = logging.getLogger(__name__)
def listener_to_edge_app_profile(listener, edge_cert_id):
edge_app_profile = {
'insertXForwardedFor': False,
'name': listener.id,
'serverSslEnabled': False,
'sslPassthrough': False,
'template': lb_const.PROTOCOL_MAP[listener.protocol],
}
if (listener.protocol == lb_const.LB_PROTOCOL_HTTPS
or listener.protocol == lb_const.LB_PROTOCOL_TERMINATED_HTTPS):
if edge_cert_id:
edge_app_profile['clientSsl'] = {
'caCertificate': [],
'clientAuth': 'ignore',
'crlCertificate': [],
'serviceCertificate': [edge_cert_id]}
else:
edge_app_profile['sslPassthrough'] = True
if listener.default_pool:
persistence = None
if listener.pool.sessionpersistence:
persistence = {
'method':
lb_const.SESSION_PERSISTENCE_METHOD_MAP.get(
listener.pool.sessionpersistence.type)}
if (listener.pool.sessionpersistence.type in
lb_const.SESSION_PERSISTENCE_COOKIE_MAP):
persistence.update({
'cookieName': getattr(listener.pool.sessionpersistence,
'cookie_name',
'default_cookie_name'),
'cookieMode': lb_const.SESSION_PERSISTENCE_COOKIE_MAP[
listener.pool.sessionpersistence.type]})
edge_app_profile['persistence'] = persistence
return edge_app_profile
def listener_to_edge_vse(listener, vip_address, default_pool, app_profile_id):
if listener.connection_limit:
connection_limit = max(0, listener.connection_limit)
else:
connection_limit = 0
return {
'name': 'vip_' + listener.id,
'description': listener.description,
'ipAddress': vip_address,
'protocol': lb_const.PROTOCOL_MAP[listener.protocol],
'port': listener.protocol_port,
'connectionLimit': connection_limit,
'defaultPoolId': default_pool,
'applicationProfileId': app_profile_id}
class EdgeListenerManager(base_mgr.EdgeLoadbalancerBaseManager):
@log_helpers.log_method_call
def __init__(self, vcns_driver):
super(EdgeListenerManager, self).__init__(vcns_driver)
def _upload_certificate(self, context, edge_id, cert_id, certificate):
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
context.session, cert_id, edge_id)
if cert_binding:
return cert_binding['edge_cert_id']
request = {
'pemEncoding': certificate.get_certificate(),
'privateKey': certificate.get_private_key()}
passphrase = certificate.get_private_key_passphrase()
if passphrase:
request['passphrase'] = passphrase
cert_obj = self.vcns.upload_edge_certificate(edge_id, request)[1]
cert_list = cert_obj.get('certificates', {})
if cert_list:
edge_cert_id = cert_list[0]['objectId']
else:
error = _("Failed to upload a certificate to edge %s") % edge_id
raise nsxv_exc.NsxPluginException(err_msg=error)
nsxv_db.add_nsxv_lbaas_certificate_binding(
context.session, cert_id, edge_id, edge_cert_id)
return edge_cert_id
@log_helpers.log_method_call
def create(self, context, listener, certificate=None):
default_pool = None
lb_id = listener.loadbalancer_id
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
context.session, lb_id)
edge_id = lb_binding['edge_id']
if listener.default_pool and listener.default_pool.id:
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
context.session, lb_id, listener.id, listener.default_pool.id)
if pool_binding:
default_pool = pool_binding['edge_pool_id']
edge_cert_id = None
if certificate:
try:
edge_cert_id = self._upload_certificate(
context, edge_id, listener.default_tls_container_id,
certificate)
except Exception:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(context,
listener)
app_profile = listener_to_edge_app_profile(listener, edge_cert_id)
app_profile_id = None
try:
with locking.LockManager.get_lock(edge_id):
h = (self.vcns.create_app_profile(edge_id, app_profile))[0]
app_profile_id = lb_common.extract_resource_id(h['location'])
except vcns_exc.VcnsApiException:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(context, listener)
LOG.error(_LE('Failed to create app profile on edge: %s'),
lb_binding['edge_id'])
vse = listener_to_edge_vse(listener, lb_binding['vip_address'],
default_pool,
app_profile_id)
try:
with locking.LockManager.get_lock(edge_id):
h = self.vcns.create_vip(edge_id, vse)[0]
edge_vse_id = lb_common.extract_resource_id(h['location'])
nsxv_db.add_nsxv_lbaas_listener_binding(context.session,
lb_id,
listener.id,
app_profile_id,
edge_vse_id)
self.lbv2_driver.listener.successful_completion(context, listener)
except vcns_exc.VcnsApiException:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(context, listener)
LOG.error(_LE('Failed to create vip on Edge: %s'), edge_id)
self.vcns.delete_app_profile(edge_id, app_profile_id)
@log_helpers.log_method_call
def update(self, context, old_listener, new_listener, certificate=None):
default_pool = None
if new_listener.default_pool and new_listener.default_pool.id:
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
context.session, new_listener.default_pool.id, None, None)
if pool_binding:
default_pool = pool_binding['edge_pool_id']
lb_id = new_listener.loadbalancer_id
listener_binding = nsxv_db.get_nsxv_lbaas_listener_binding(
context.session, lb_id, new_listener.id)
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
context.session, lb_id)
edge_id = lb_binding['edge_id']
edge_cert_id = None
if certificate:
if (old_listener.default_tls_container_id !=
new_listener.default_tls_container_id):
try:
edge_cert_id = self._upload_certificate(
context, edge_id,
new_listener.default_tls_container_id,
certificate)
except Exception:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(
context, new_listener)
else:
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
context.session, new_listener.default_tls_container_id,
edge_id)
edge_cert_id = cert_binding['edge_cert_id']
app_profile_id = listener_binding['app_profile_id']
app_profile = listener_to_edge_app_profile(new_listener, edge_cert_id)
try:
with locking.LockManager.get_lock(edge_id):
self.vcns.update_app_profile(
edge_id, app_profile_id, app_profile)
vse = listener_to_edge_vse(new_listener,
lb_binding['vip_address'],
default_pool,
app_profile_id)
with locking.LockManager.get_lock(edge_id):
self.vcns.update_vip(edge_id, listener_binding['vse_id'], vse)
self.lbv2_driver.listener.successful_completion(context,
new_listener)
except vcns_exc.VcnsApiException:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(context,
new_listener)
LOG.error(_LE('Failed to update app profile on edge: %s'),
edge_id)
@log_helpers.log_method_call
def delete(self, context, listener):
lb_id = listener.loadbalancer_id
listener_binding = nsxv_db.get_nsxv_lbaas_listener_binding(
context.session, lb_id, listener.id)
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
context.session, lb_id)
if lb_binding and listener_binding:
edge_id = lb_binding['edge_id']
edge_vse_id = listener_binding['vse_id']
app_profile_id = listener_binding['app_profile_id']
try:
with locking.LockManager.get_lock(edge_id):
self.vcns.delete_vip(edge_id, edge_vse_id)
except vcns_exc.ResourceNotFound:
LOG.error(_LE('vip not found on edge: %s'), edge_id)
except vcns_exc.VcnsApiException:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(context,
listener)
LOG.error(
_LE('Failed to delete vip on edge: %s'), edge_id)
try:
with locking.LockManager.get_lock(edge_id):
self.vcns.delete_app_profile(edge_id, app_profile_id)
except vcns_exc.ResourceNotFound:
LOG.error(_LE('app profile not found on edge: %s'), edge_id)
except vcns_exc.VcnsApiException:
with excutils.save_and_reraise_exception():
self.lbv2_driver.listener.failed_completion(context,
listener)
LOG.error(
_LE('Failed to delete app profile on Edge: %s'),
edge_id)
nsxv_db.del_nsxv_lbaas_listener_binding(context.session, lb_id,
listener.id)
self.lbv2_driver.listener.successful_completion(
context, listener, delete=True)