Merge "NSXv3: Fix TERMINATED_HTTPS listener"
This commit is contained in:
commit
d21223ebbe
@ -124,6 +124,8 @@ NSX_V3_FW_DEFAULT_NS_GROUP = 'os_default_section_ns_group'
|
||||
NSX_V3_DEFAULT_SECTION = 'OS-Default-Section'
|
||||
NSX_V3_EXCLUDED_PORT_NSGROUP_NAME = 'neutron_excluded_port_nsgroup'
|
||||
NSX_V3_NON_VIF_PROFILE = 'nsx-default-switch-security-non-vif-profile'
|
||||
NSX_V3_SERVER_SSL_PROFILE = 'nsx-default-server-ssl-profile'
|
||||
NSX_V3_CLIENT_SSL_PROFILE = 'nsx-default-client-ssl-profile'
|
||||
|
||||
|
||||
def inject_headers():
|
||||
@ -359,6 +361,17 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
NSX_V3_NON_VIF_PROFILE)[0]
|
||||
self._no_switch_security = profile_client.build_switch_profile_ids(
|
||||
profile_client, no_switch_security_prof)[0]
|
||||
self.server_ssl_profile = None
|
||||
self.client_ssl_profile = None
|
||||
# Only create LB profiles when nsxv3 version >= 2.1.0
|
||||
if self.nsxlib.feature_supported(nsxlib_consts.FEATURE_LOAD_BALANCER):
|
||||
LOG.debug("Initializing NSX v3 Load Balancer default profiles")
|
||||
try:
|
||||
self._init_lb_profiles()
|
||||
except Exception as e:
|
||||
msg = (_("Unable to initialize NSX v3 lb profiles: "
|
||||
"Reason: %(reason)s") % {'reason': str(e)})
|
||||
raise nsx_exc.NsxPluginException(err_msg=msg)
|
||||
|
||||
def _translate_configured_names_to_uuids(self):
|
||||
# If using tags to find the objects, make sure tag scope is configured
|
||||
@ -530,6 +543,35 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
profile_id=profile[0]['id']) if profile else None
|
||||
return self._mac_learning_profile
|
||||
|
||||
def _init_lb_profiles(self):
|
||||
with locking.LockManager.get_lock('nsxv3_lb_profiles_init'):
|
||||
lb_profiles = self._get_lb_profiles()
|
||||
if not lb_profiles.get('client_ssl_profile'):
|
||||
self.nsxlib.load_balancer.client_ssl_profile.create(
|
||||
NSX_V3_CLIENT_SSL_PROFILE,
|
||||
'Neutron LB Client SSL Profile',
|
||||
tags=self.nsxlib.build_v3_api_version_tag())
|
||||
if not lb_profiles.get('server_ssl_profile'):
|
||||
self.nsxlib.load_balancer.server_ssl_profile.create(
|
||||
NSX_V3_SERVER_SSL_PROFILE,
|
||||
'Neutron LB Server SSL Profile',
|
||||
tags=self.nsxlib.build_v3_api_version_tag())
|
||||
|
||||
def _get_lb_profiles(self):
|
||||
if not self.client_ssl_profile:
|
||||
ssl_profile_client = self.nsxlib.load_balancer.client_ssl_profile
|
||||
profile = ssl_profile_client.find_by_display_name(
|
||||
NSX_V3_CLIENT_SSL_PROFILE)
|
||||
self.client_ssl_profile = profile[0]['id'] if profile else None
|
||||
if not self.server_ssl_profile:
|
||||
ssl_profile_client = self.nsxlib.load_balancer.server_ssl_profile
|
||||
profile = ssl_profile_client.find_by_display_name(
|
||||
NSX_V3_SERVER_SSL_PROFILE)
|
||||
self.server_ssl_profile = profile[0]['id'] if profile else None
|
||||
|
||||
return {'client_ssl_profile': self.client_ssl_profile,
|
||||
'server_ssl_profile': self.server_ssl_profile}
|
||||
|
||||
def _get_port_security_profile_id(self):
|
||||
return self.nsxlib.switching_profile.build_switch_profile_ids(
|
||||
self.nsxlib.switching_profile, self._psec_profile)[0]
|
||||
|
@ -98,6 +98,7 @@ LB_STATS_MAP = {'active_connections': 'current_sessions',
|
||||
'total_connections': 'total_sessions'}
|
||||
LR_ROUTER_TYPE = 'os-neutron-router-id'
|
||||
LR_PORT_TYPE = 'os-neutron-rport-id'
|
||||
LB_CERT_RESOURCE_TYPE = ['certificate_signed', 'certificate_self_signed']
|
||||
DEFAULT_LB_SIZE = 'SMALL'
|
||||
LB_FLAVOR_SIZES = ['SMALL', 'MEDIUM', 'LARGE', 'small', 'medium', 'large']
|
||||
LB_RULE_MATCH_TYPE = {
|
||||
|
@ -34,10 +34,51 @@ class EdgeListenerManager(base_mgr.Nsxv3LoadbalancerBaseManager):
|
||||
def __init__(self):
|
||||
super(EdgeListenerManager, self).__init__()
|
||||
|
||||
def _get_virtual_server_kwargs(self, context, listener, vs_name, tags,
|
||||
app_profile_id, certificate=None):
|
||||
kwargs = {'display_name': vs_name,
|
||||
'tags': tags,
|
||||
'enabled': listener.admin_state_up,
|
||||
'ip_address': listener.loadbalancer.vip_address,
|
||||
'port': listener.protocol_port,
|
||||
'application_profile_id': app_profile_id}
|
||||
if listener.connection_limit != -1:
|
||||
kwargs['max_concurrent_connections'] = \
|
||||
listener.connection_limit
|
||||
if listener.default_pool_id:
|
||||
pool_binding = nsx_db.get_nsx_lbaas_pool_binding(
|
||||
context.session, listener.loadbalancer.id,
|
||||
listener.default_pool_id)
|
||||
if pool_binding:
|
||||
kwargs['pool_id'] = pool_binding.get('lb_pool_id')
|
||||
ssl_profile_binding = self._get_ssl_profile_binding(
|
||||
tags, certificate=certificate)
|
||||
if (listener.protocol == lb_const.LB_PROTOCOL_TERMINATED_HTTPS and
|
||||
ssl_profile_binding):
|
||||
kwargs.update(ssl_profile_binding)
|
||||
return kwargs
|
||||
|
||||
def _get_ssl_profile_binding(self, tags, certificate=None):
|
||||
tm_client = self.core_plugin.nsxlib.trust_management
|
||||
nsx_cert_id = None
|
||||
ssl_profile_binding = None
|
||||
if certificate:
|
||||
nsx_cert_id = tm_client.create_cert(
|
||||
certificate.get_certificate(),
|
||||
private_key=certificate.get_private_key(),
|
||||
passphrase=certificate.get_private_key_passphrase(),
|
||||
tags=tags)
|
||||
ssl_profile_binding = {
|
||||
'client_ssl_profile_binding': {
|
||||
'ssl_profile_id': self.core_plugin.client_ssl_profile,
|
||||
'default_certificate_id': nsx_cert_id
|
||||
}
|
||||
}
|
||||
return ssl_profile_binding
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create(self, context, listener, certificate=None):
|
||||
lb_id = listener.loadbalancer_id
|
||||
vip_address = listener.loadbalancer.vip_address
|
||||
load_balancer = self.core_plugin.nsxlib.load_balancer
|
||||
app_client = load_balancer.application_profile
|
||||
vs_client = load_balancer.virtual_server
|
||||
@ -51,9 +92,12 @@ class EdgeListenerManager(base_mgr.Nsxv3LoadbalancerBaseManager):
|
||||
'tag': listener.loadbalancer.name[:utils.MAX_TAG_LEN]})
|
||||
tags.append({'scope': 'os-lbaas-lb-id',
|
||||
'tag': lb_id})
|
||||
if listener.protocol == 'HTTP' or listener.protocol == 'HTTPS':
|
||||
|
||||
if (listener.protocol == lb_const.LB_PROTOCOL_HTTP or
|
||||
listener.protocol == lb_const.LB_PROTOCOL_TERMINATED_HTTPS):
|
||||
profile_type = lb_const.LB_HTTP_PROFILE
|
||||
elif listener.protocol == 'TCP':
|
||||
elif (listener.protocol == lb_const.LB_PROTOCOL_TCP or
|
||||
listener.protocol == lb_const.LB_PROTOCOL_HTTPS):
|
||||
profile_type = lb_const.LB_TCP_PROFILE
|
||||
else:
|
||||
msg = (_('Cannot create listener %(listener)s with '
|
||||
@ -65,13 +109,9 @@ class EdgeListenerManager(base_mgr.Nsxv3LoadbalancerBaseManager):
|
||||
app_profile = app_client.create(
|
||||
display_name=vs_name, resource_type=profile_type, tags=tags)
|
||||
app_profile_id = app_profile['id']
|
||||
virtual_server = vs_client.create(
|
||||
display_name=vs_name,
|
||||
tags=tags,
|
||||
enabled=listener.admin_state_up,
|
||||
ip_address=vip_address,
|
||||
port=listener.protocol_port,
|
||||
application_profile_id=app_profile_id)
|
||||
kwargs = self._get_virtual_server_kwargs(
|
||||
context, listener, vs_name, tags, app_profile_id, certificate)
|
||||
virtual_server = vs_client.create(**kwargs)
|
||||
except nsxlib_exc.ManagerError:
|
||||
self.lbv2_driver.listener.failed_completion(context, listener)
|
||||
msg = _('Failed to create virtual server at NSX backend')
|
||||
@ -164,6 +204,23 @@ class EdgeListenerManager(base_mgr.Nsxv3LoadbalancerBaseManager):
|
||||
msg = (_('Failed to delete application profile: %(app)s') %
|
||||
{'app': app_profile_id})
|
||||
raise n_exc.BadRequest(resource='lbaas-listener', msg=msg)
|
||||
|
||||
# Delete imported NSX cert if there is any
|
||||
cert_tags = [{'scope': lb_const.LB_LISTENER_TYPE,
|
||||
'tag': listener.id}]
|
||||
results = self.core_plugin.nsxlib.search_by_tags(
|
||||
tags=cert_tags)
|
||||
# Only delete object related to certificate used by listener
|
||||
for obj in results['results']:
|
||||
if obj.get('resource_type') in lb_const.LB_CERT_RESOURCE_TYPE:
|
||||
tm_client = self.core_plugin.nsxlib.trust_management
|
||||
try:
|
||||
tm_client.delete_cert(obj['id'])
|
||||
except nsxlib_exc.ManagerError:
|
||||
LOG.error("Exception thrown when trying to delete "
|
||||
"certificate: %(cert)s",
|
||||
{'cert': obj['id']})
|
||||
|
||||
nsx_db.delete_nsx_lbaas_listener_binding(
|
||||
context.session, lb_id, listener.id)
|
||||
|
||||
|
@ -103,6 +103,8 @@ L7RULE_BINDING = {'loadbalancer_id': LB_ID,
|
||||
'lb_vs_id': LB_VS_ID,
|
||||
'lb_rule_id': LB_RULE_ID}
|
||||
|
||||
FAKE_CERT = {'id': 'cert-xyz'}
|
||||
|
||||
|
||||
class BaseTestEdgeLbaasV2(base.BaseTestCase):
|
||||
def _tested_entity(self):
|
||||
@ -127,6 +129,12 @@ class BaseTestEdgeLbaasV2(base.BaseTestCase):
|
||||
'listener1', '', None, LB_ID,
|
||||
'HTTP', protocol_port=80,
|
||||
loadbalancer=self.lb)
|
||||
self.https_listener = lb_models.Listener(
|
||||
LISTENER_ID, LB_TENANT_ID, 'listener1', '', None, LB_ID,
|
||||
'HTTPS', protocol_port=443, loadbalancer=self.lb)
|
||||
self.terminated_https_listener = lb_models.Listener(
|
||||
LISTENER_ID, LB_TENANT_ID, 'listener1', '', None, LB_ID,
|
||||
'TERMINATED_HTTPS', protocol_port=443, loadbalancer=self.lb)
|
||||
self.pool = lb_models.Pool(POOL_ID, LB_TENANT_ID, 'pool1', '',
|
||||
None, 'HTTP', 'ROUND_ROBIN',
|
||||
loadbalancer_id=LB_ID,
|
||||
@ -182,6 +190,8 @@ class BaseTestEdgeLbaasV2(base.BaseTestCase):
|
||||
'monitor').start()
|
||||
self.rule_client = mock.patch.object(load_balancer,
|
||||
'rule').start()
|
||||
self.tm_client = mock.patch.object(nsxlib,
|
||||
'trust_management').start()
|
||||
|
||||
def _unpatch_lb_plugin(self, lb_plugin, manager):
|
||||
setattr(lb_plugin, manager, self.real_manager)
|
||||
@ -256,7 +266,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
|
||||
def _tested_entity(self):
|
||||
return 'listener'
|
||||
|
||||
def test_create(self):
|
||||
def _create_listener(self, protocol='HTTP'):
|
||||
with mock.patch.object(self.app_client, 'create'
|
||||
) as mock_create_app_profile, \
|
||||
mock.patch.object(self.vs_client, 'create'
|
||||
@ -270,8 +280,11 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
|
||||
mock_create_app_profile.return_value = {'id': APP_PROFILE_ID}
|
||||
mock_create_virtual_server.return_value = {'id': LB_VS_ID}
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
listener = self.listener
|
||||
if protocol == 'HTTPS':
|
||||
listener = self.https_listener
|
||||
|
||||
self.edge_driver.listener.create(self.context, self.listener)
|
||||
self.edge_driver.listener.create(self.context, listener)
|
||||
|
||||
mock_add_virtual_server.assert_called_with(LB_SERVICE_ID,
|
||||
LB_VS_ID)
|
||||
@ -282,7 +295,44 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.listener.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.listener)
|
||||
listener)
|
||||
|
||||
def test_create_http_listener(self):
|
||||
self._create_listener()
|
||||
|
||||
def test_create_https_listener(self):
|
||||
self._create_listener(protocol='HTTPS')
|
||||
|
||||
def test_create_terminated_https(self):
|
||||
with mock.patch.object(self.tm_client, 'create_cert'
|
||||
) as mock_create_cert, \
|
||||
mock.patch.object(self.app_client, 'create'
|
||||
) as mock_create_app_profile, \
|
||||
mock.patch.object(self.vs_client, 'create'
|
||||
) as mock_create_virtual_server, \
|
||||
mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(self.service_client, 'add_virtual_server'
|
||||
) as mock_add_virtual_server, \
|
||||
mock.patch.object(nsx_db, 'add_nsx_lbaas_listener_binding'
|
||||
) as mock_add_listener_binding:
|
||||
mock_create_cert.return_value = FAKE_CERT['id']
|
||||
mock_create_app_profile.return_value = {'id': APP_PROFILE_ID}
|
||||
mock_create_virtual_server.return_value = {'id': LB_VS_ID}
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
|
||||
self.edge_driver.listener.create(self.context,
|
||||
self.terminated_https_listener)
|
||||
mock_add_virtual_server.assert_called_with(LB_SERVICE_ID,
|
||||
LB_VS_ID)
|
||||
mock_add_listener_binding.assert_called_with(
|
||||
self.context.session, LB_ID, LISTENER_ID, APP_PROFILE_ID,
|
||||
LB_VS_ID)
|
||||
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.listener.successful_completion)
|
||||
mock_successful_completion.assert_called_with(
|
||||
self.context, self.terminated_https_listener)
|
||||
|
||||
def test_update(self):
|
||||
new_listener = lb_models.Listener(LISTENER_ID, LB_TENANT_ID,
|
||||
|
Loading…
x
Reference in New Issue
Block a user