Merge "[NSX-v3+p] Support switching session persistence type"

This commit is contained in:
Zuul 2019-06-24 09:19:16 +00:00 committed by Gerrit Code Review
commit 31ad4b72ea
9 changed files with 229 additions and 102 deletions

View File

@ -20,7 +20,7 @@ from vmware_nsx.services.lbaas import lb_const
@log_helpers.log_method_call
def validate_session_persistence(pool, listener, completor, old_pool=None):
def validate_session_persistence(pool, listener, completor):
sp = pool.get('session_persistence')
if not listener or not sp:
# safety first!
@ -35,23 +35,21 @@ def validate_session_persistence(pool, listener, completor, old_pool=None):
'lst_id': listener['id'],
'proto': listener['protocol']})
raise n_exc.BadRequest(resource='lbaas-pool', msg=msg)
# Cannot switch (yet) on update from source IP to cookie based, and
# vice versa
def session_persistence_type_changed(pool, old_pool):
cookie_pers_types = (lb_const.LB_SESSION_PERSISTENCE_HTTP_COOKIE,
lb_const.LB_SESSION_PERSISTENCE_APP_COOKIE)
sp = pool.get('session_persistence')
if not sp:
return False
if old_pool:
oldsp = old_pool.get('session_persistence')
if not oldsp:
return
return False
if ((sp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP and
oldsp['type'] in cookie_pers_types) or
(sp['type'] in cookie_pers_types and
oldsp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP)):
completor(success=False)
msg = (_("Cannot update session persistence type to "
"%(sp_type)s for pool on listener %(lst_id)s "
"from %(old_sp_type)s") %
{'sp_type': sp['type'],
'lst_id': listener['id'],
'old_sp_type': oldsp['type']})
raise n_exc.BadRequest(resource='lbaas-pool', msg=msg)
return True
return False

View File

@ -191,7 +191,8 @@ def delete_persistence_profile(nsxpolicy, lb_persistence_profile_path):
pp_client.delete(persistence_profile_id)
def setup_session_persistence(nsxpolicy, pool, pool_tags, listener, vs_data):
def setup_session_persistence(nsxpolicy, pool, pool_tags, switch_type,
listener, vs_data):
sp = pool.get('session_persistence')
pers_type = None
cookie_name = None
@ -203,6 +204,7 @@ def setup_session_persistence(nsxpolicy, pool, pool_tags, listener, vs_data):
elif sp['type'] == lb_const.LB_SESSION_PERSISTENCE_HTTP_COOKIE:
pp_client = lb_client.lb_cookie_persistence_profile
pers_type = nsxlib_lb.PersistenceProfileTypes.COOKIE
pers_id_suffix = 'cookie'
cookie_name = sp.get('cookie_name')
if not cookie_name:
cookie_name = lb_const.SESSION_PERSISTENCE_DEFAULT_COOKIE_NAME
@ -210,12 +212,14 @@ def setup_session_persistence(nsxpolicy, pool, pool_tags, listener, vs_data):
elif sp['type'] == lb_const.LB_SESSION_PERSISTENCE_APP_COOKIE:
pp_client = lb_client.lb_cookie_persistence_profile
pers_type = nsxlib_lb.PersistenceProfileTypes.COOKIE
pers_id_suffix = 'cookie'
# In this case cookie name is mandatory
cookie_name = sp['cookie_name']
cookie_mode = "REWRITE"
else:
pp_client = lb_client.lb_source_ip_persistence_profile
pers_type = nsxlib_lb.PersistenceProfileTypes.SOURCE_IP
pers_id_suffix = 'sourceip'
if pers_type:
# There is a profile to create or update
pp_kwargs = {
@ -230,7 +234,7 @@ def setup_session_persistence(nsxpolicy, pool, pool_tags, listener, vs_data):
profile_path = vs_data.get('lb_persistence_profile_path', '')
persistence_profile_id = p_utils.path_to_id(profile_path)
if persistence_profile_id:
if persistence_profile_id and not switch_type:
# NOTE: removal of the persistence profile must be executed
# after the virtual server has been updated
if pers_type:
@ -248,7 +252,7 @@ def setup_session_persistence(nsxpolicy, pool, pool_tags, listener, vs_data):
nsxpolicy, profile_path))
elif pers_type:
# Create persistence profile
pp_id = pool['id']
pp_id = "%s_%s" % (pool['id'], pers_id_suffix)
pp_kwargs['persistence_profile_id'] = pp_id
pp_client.create_or_overwrite(**pp_kwargs)
LOG.debug("Created persistence profile %(profile_id)s for "
@ -256,5 +260,10 @@ def setup_session_persistence(nsxpolicy, pool, pool_tags, listener, vs_data):
{'profile_id': pp_id,
'listener_id': listener['id'],
'pool_id': pool['id']})
if switch_type:
# There is aso a persistence profile to remove!
return (pp_id, functools.partial(delete_persistence_profile,
nsxpolicy, profile_path))
return pp_id, None
return None, None

View File

@ -135,8 +135,7 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
return app_client
def _validate_default_pool(self, listener, completor,
old_listener=None):
def _validate_default_pool(self, listener, completor):
def_pool_id = listener.get('default_pool_id')
if def_pool_id:
vs_client = self.core_plugin.nsxpolicy.load_balancer.virtual_server
@ -149,14 +148,8 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
'listener') % listener['default_pool_id'])
raise n_exc.BadRequest(resource='lbaas-pool', msg=msg)
# Perform additional validation for session persistence before
# creating resources in the backend
old_pool = None
if old_listener:
old_pool = old_listener.get('default_pool')
lb_common.validate_session_persistence(
listener.get('default_pool'), listener, completor,
old_pool=old_pool)
listener.get('default_pool'), listener, completor)
@log_helpers.log_method_call
def create(self, context, listener, completor,
@ -183,12 +176,14 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
completor(success=True)
def _get_pool_tags(self, context, pool):
def _get_pool_tags(self, context, pool, listener_tenant_id):
return lb_utils.get_tags(self.core_plugin, pool['id'],
lb_const.LB_POOL_TYPE, pool['tenant_id'],
lb_const.LB_POOL_TYPE,
pool.get('tenant_id', listener_tenant_id),
context.project_name)
def _update_default_pool(self, context, listener, completor):
def _update_default_pool(self, context, listener,
completor, old_listener=None):
if not listener.get('default_pool_id'):
return
nsxlib_lb = self.core_plugin.nsxpolicy.load_balancer
@ -196,13 +191,18 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
vs_data = vs_client.get(listener['id'])
pool_id = listener['default_pool_id']
pool = listener['default_pool']
old_pool = None
if old_listener:
old_pool = old_listener.get('default_pool')
try:
switch_type = lb_common.session_persistence_type_changed(
pool, old_pool)
(persistence_profile_id,
post_process_func) = lb_utils.setup_session_persistence(
self.core_plugin.nsxpolicy,
pool,
self._get_pool_tags(context, pool),
listener, vs_data)
self._get_pool_tags(context, pool, listener.get('tenant_id')),
switch_type, listener, vs_data)
except nsxlib_exc.ManagerError:
with excutils.save_and_reraise_exception():
completor(success=False)
@ -236,8 +236,8 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
vs_name = None
tags = None
self._validate_default_pool(new_listener, completor,
old_listener=old_listener)
self._validate_default_pool(new_listener, completor)
if new_listener['name'] != old_listener['name']:
vs_name = utils.get_name_and_uuid(
new_listener['name'] or 'listener',
@ -262,7 +262,8 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
# Update default pool and session persistence
if (old_listener.get('default_pool_id') !=
new_listener.get('default_pool_id')):
self._update_default_pool(context, new_listener, completor)
self._update_default_pool(context, new_listener,
completor, old_listener)
completor(success=True)
@log_helpers.log_method_call

View File

@ -56,7 +56,8 @@ class EdgePoolManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
self.core_plugin.nsxpolicy,
vs_data.get('lb_persistence_profile_path', ''))
def _process_vs_update(self, context, pool, pool_id, listener, completor):
def _process_vs_update(self, context, pool, pool_id, switch_type,
listener, completor):
vs_client = self.core_plugin.nsxpolicy.load_balancer.virtual_server
try:
# Process pool persistence profile and
@ -67,7 +68,7 @@ class EdgePoolManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
post_process_func) = lb_utils.setup_session_persistence(
self.core_plugin.nsxpolicy, pool,
self._get_pool_tags(context, pool),
listener, vs_data)
switch_type, listener, vs_data)
else:
post_process_func = functools.partial(
self._remove_persistence, vs_data)
@ -139,8 +140,8 @@ class EdgePoolManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
# FIXME(salv-orlando): This two-step process can leave a zombie pool on
# NSX if the VS update operation fails
if listener:
self._process_vs_update(context, pool, pool['id'], listener,
completor)
self._process_vs_update(context, pool, pool['id'], False,
listener, completor)
completor(success=True)
@log_helpers.log_method_call
@ -174,17 +175,17 @@ class EdgePoolManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
listener = None
# Perform additional validation for session persistence before
# operating on resources in the backend
lb_common.validate_session_persistence(new_pool, listener, completor,
old_pool=old_pool)
lb_common.validate_session_persistence(new_pool, listener, completor)
try:
kwargs = self._get_pool_kwargs(pool_name, tags, lb_algorithm,
description)
pool_client.update(lb_pool_id=new_pool['id'], **kwargs)
if (listener and new_pool['session_persistence'] !=
old_pool['session_persistence']):
switch_type = lb_common.session_persistence_type_changed(
new_pool, old_pool)
self._process_vs_update(context, new_pool, new_pool['id'],
listener, completor)
switch_type, listener, completor)
completor(success=True)
except Exception as e:
with excutils.save_and_reraise_exception():
@ -206,7 +207,7 @@ class EdgePoolManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
if listener:
try:
self._process_vs_update(
context, pool, None, listener, completor)
context, pool, None, False, listener, completor)
except Exception as e:
LOG.error('Disassociation of listener %(lsn)s from pool '
'%(pool)s failed with error %(err)s',

View File

@ -282,7 +282,8 @@ def get_pool_tags(context, core_plugin, pool):
@log_helpers.log_method_call
def setup_session_persistence(nsxlib, pool, pool_tags, listener, vs_data):
def setup_session_persistence(nsxlib, pool, pool_tags,
switch_type, listener, vs_data):
sp = pool.get('session_persistence')
pers_type = None
cookie_name = None
@ -317,7 +318,7 @@ def setup_session_persistence(nsxlib, pool, pool_tags, listener, vs_data):
pp_client = nsxlib.load_balancer.persistence_profile
persistence_profile_id = vs_data.get('persistence_profile_id')
if persistence_profile_id:
if persistence_profile_id and not switch_type:
# NOTE: removal of the persistence profile must be executed
# after the virtual server has been updated
if pers_type:
@ -341,5 +342,10 @@ def setup_session_persistence(nsxlib, pool, pool_tags, listener, vs_data):
{'profile_id': pp_data['id'],
'listener_id': listener['id'],
'pool_id': pool['id']})
if switch_type:
# There is also a persistence profile to remove!
return (pp_data['id'],
functools.partial(delete_persistence_profile,
nsxlib, persistence_profile_id))
return pp_data['id'], None
return None, None

View File

@ -123,17 +123,11 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
'listener') % listener['default_pool_id'])
raise n_exc.BadRequest(resource='lbaas-pool', msg=msg)
# Perform additional validation for session persistence before
# creating resources in the backend
old_pool = None
if old_listener:
old_pool = old_listener.get('default_pool')
lb_common.validate_session_persistence(
listener.get('default_pool'), listener, completor,
old_pool=old_pool)
listener.get('default_pool'), listener, completor)
def _update_default_pool_and_binding(self, context, listener, vs_data,
completor):
completor, old_listener=None):
vs_client = self.core_plugin.nsxlib.load_balancer.virtual_server
if listener.get('default_pool_id'):
vs_id = vs_data['id']
@ -141,13 +135,18 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
listener.get('loadbalancer', {}).get('id'))
pool_id = listener['default_pool_id']
pool = listener['default_pool']
old_pool = None
if old_listener:
old_pool = old_listener.get('default_pool')
try:
switch_type = lb_common.session_persistence_type_changed(
pool, old_pool)
(persistence_profile_id,
post_process_func) = lb_utils.setup_session_persistence(
self.core_plugin.nsxlib,
pool,
lb_utils.get_pool_tags(context, self.core_plugin, pool),
listener, vs_data)
switch_type, listener, vs_data)
except nsxlib_exc.ManagerError:
with excutils.save_and_reraise_exception():
completor(success=False)
@ -301,7 +300,8 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
new_listener.get('default_pool_id')):
self._remove_default_pool_binding(context, old_listener)
self._update_default_pool_and_binding(context, new_listener,
vs_data, completor)
vs_data, completor,
old_listener)
completor(success=True)

View File

@ -49,7 +49,7 @@ class EdgePoolManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
kwargs['snat_translation'] = {'type': "LbSnatAutoMap"}
return kwargs
def _process_vs_update(self, context, pool, listener,
def _process_vs_update(self, context, pool, switch_type, listener,
nsx_pool_id, nsx_vs_id, completor):
LOG.debug("Processing NSX virtual server update for pool %(pool_id)s. "
"Will update VS %(nsx_vs_id)s", {'pool_id': pool['id'],
@ -64,7 +64,7 @@ class EdgePoolManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
post_process_func) = lb_utils.setup_session_persistence(
self.core_plugin.nsxlib,
pool, self._get_pool_tags(context, pool),
listener, vs_data)
switch_type, listener, vs_data)
else:
post_process_func = functools.partial(
lb_utils.delete_persistence_profile,
@ -146,7 +146,7 @@ class EdgePoolManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
vs_id = binding['lb_vs_id']
# Updae the virtual server only if it exists
if vs_id:
self._process_vs_update(context, pool, listener,
self._process_vs_update(context, pool, False, listener,
lb_pool['id'], vs_id, completor)
nsx_db.update_nsx_lbaas_pool_binding(
context.session, lb_id, pool['id'], vs_id)
@ -194,9 +194,7 @@ class EdgePoolManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
# Perform additional validation for session persistence before
# operating on resources in the backend
lb_common.validate_session_persistence(new_pool, listener, completor,
old_pool=old_pool)
lb_common.validate_session_persistence(new_pool, listener, completor)
try:
lb_pool_id = binding['lb_pool_id']
kwargs = self._get_pool_kwargs(pool_name, tags, lb_algorithm,
@ -206,9 +204,11 @@ class EdgePoolManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
# in session persistence
if (listener and new_pool['session_persistence'] !=
old_pool['session_persistence'] and binding['lb_vs_id']):
self._process_vs_update(context, new_pool, listener,
lb_pool_id, binding['lb_vs_id'],
completor)
switch_type = lb_common.session_persistence_type_changed(
new_pool, old_pool)
self._process_vs_update(context, new_pool, switch_type,
listener, lb_pool_id,
binding['lb_vs_id'], completor)
completor(success=True)
except Exception as e:
with excutils.save_and_reraise_exception():
@ -236,7 +236,7 @@ class EdgePoolManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
# If listeners is an empty list we hit this exception
listener = None
if listener:
self._process_vs_update(context, pool, listener,
self._process_vs_update(context, pool, False, listener,
None, vs_id, completor)
try:

View File

@ -650,7 +650,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
self.assertTrue(self.last_completor_called)
self.assertTrue(self.last_completor_succees)
def test_update_with_session_persistence_fail(self):
def test_update_with_session_persistence_change(self):
old_listener = lb_models.Listener(LISTENER_ID, LB_TENANT_ID,
'listener1', 'description',
self.pool_persistency.id,
@ -662,7 +662,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
old_listener)
sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'SOURCE_IP')
pool_persistency = lb_models.Pool(POOL_ID, LB_TENANT_ID,
pool_persistency = lb_models.Pool('new_pool_id', LB_TENANT_ID,
'pool1', '', None, 'HTTP',
'ROUND_ROBIN', loadbalancer_id=LB_ID,
listener=self.listener,
@ -681,13 +681,27 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
with mock.patch.object(self.core_plugin,
'get_waf_profile_path_and_mode',
return_value=(None, None)), \
mock.patch.object(self.pp_client, 'create_or_overwrite'
) as mock_create_pp, \
mock.patch.object(self.pp_generic_client, 'delete'
) as mock_delete_pp, \
mock.patch.object(self.core_plugin, 'get_floatingips'
) as mock_get_floatingips:
) as mock_get_floatingips, \
mock.patch.object(self.edge_driver.listener,
'_get_pool_tags'
) as mock_get_pool_tags:
mock_get_pool_tags.return_value = []
mock_get_floatingips.return_value = []
self.assertRaises(n_exc.BadRequest,
self.edge_driver.listener.update,
self.context, old_listener_dict,
new_listener_dict, self.completor)
self.edge_driver.listener.update(
self.context, old_listener_dict,
new_listener_dict, self.completor)
mock_create_pp.assert_called_once_with(
name='persistence_pool1_new_p...ol_id',
persistence_profile_id='new_pool_id_sourceip',
tags=mock.ANY)
# No reason to check parameters here, it's
# all mocked out
mock_delete_pp.assert_called_once()
def test_delete(self):
with mock.patch.object(self.service_client, 'get'
@ -759,11 +773,11 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
cookie_name='meh_cookie',
name=mock.ANY,
tags=mock.ANY,
persistence_profile_id=POOL_ID)
persistence_profile_id="%s_cookie" % LB_PP_ID)
mock_update_pp.assert_not_called()
mock_vs_update.assert_called_once_with(
LB_VS_ID, pool_id=LB_POOL_ID,
lb_persistence_profile_id=LB_PP_ID)
lb_persistence_profile_id="%s_cookie" % LB_PP_ID)
vs_data = {'id': LB_VS_ID}
self._test_create_with_persistency(vs_data, verify_func)
@ -878,18 +892,50 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
cookie_name='meh_cookie',
name=mock.ANY,
tags=mock.ANY,
persistence_profile_id=LB_POOL_ID)
persistence_profile_id="%s_cookie" % LB_PP_ID)
mock_update_pp.assert_not_called()
mock_delete_pp.assert_not_called()
mock_vs_update.assert_called_once_with(
LB_VS_ID, pool_id=LB_POOL_ID,
lb_persistence_profile_id=LB_PP_ID)
lb_persistence_profile_id="%s_cookie" % LB_PP_ID)
vs_data = {'id': LB_VS_ID}
self._test_update_with_persistency(vs_data, self.pool,
self.pool_persistency, verify_func,
cookie=True)
def test_update_switch_persistency_type(self):
def verify_func(mock_create_pp, mock_update_pp,
mock_delete_pp, mock_vs_update):
mock_create_pp.assert_called_once_with(
name=mock.ANY,
tags=mock.ANY,
persistence_profile_id="%s_sourceip" % LB_PP_ID)
mock_update_pp.assert_not_called()
mock_delete_pp.assert_called_once()
mock_vs_update.assert_called_once_with(
LB_VS_ID, pool_id=LB_POOL_ID,
lb_persistence_profile_id="%s_sourceip" % LB_PP_ID)
ip_sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'SOURCE_IP')
pool_ip_persistency = lb_models.Pool(
POOL_ID, LB_TENANT_ID,
'pool1', '', None, 'HTTP',
'ROUND_ROBIN', loadbalancer_id=LB_ID,
listener=self.listener,
listeners=[self.listener],
loadbalancer=self.lb,
session_persistence=ip_sess_persistence)
vs_data = {'id': LB_VS_ID,
'lb_persistence_profile_path': 'meh'}
self._test_update_with_persistency(vs_data,
self.pool_persistency,
pool_ip_persistency,
verify_func,)
def test_update_remove_persistency(self):
def verify_func(mock_create_pp, mock_update_pp,
mock_delete_pp, mock_vs_update):
@ -943,14 +989,14 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
mock_create_pp, mock_update_pp):
if cookie_name:
mock_create_pp.assert_called_once_with(
persistence_profile_id=POOL_ID,
persistence_profile_id="%s_cookie" % LB_PP_ID,
cookie_name=cookie_name,
cookie_mode=cookie_mode,
name=mock.ANY,
tags=mock.ANY)
else:
mock_create_pp.assert_called_once_with(
persistence_profile_id=POOL_ID,
persistence_profile_id="%s_sourceip" % LB_PP_ID,
name=mock.ANY,
tags=mock.ANY)
# Compare tags - kw args are the last item of a mock call tuple
@ -964,14 +1010,14 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
mock_create_pp, mock_update_pp):
if cookie_name:
mock_update_pp.assert_called_once_with(
LB_PP_ID,
"%s_cookie" % LB_PP_ID,
cookie_name=cookie_name,
cookie_mode=cookie_mode,
name=mock.ANY,
tags=mock.ANY)
else:
mock_update_pp.assert_called_once_with(
LB_PP_ID,
"%s_sourceip" % LB_PP_ID,
name=mock.ANY,
tags=mock.ANY)
# Compare tags - kw args are the last item of a mock call tuple
@ -988,7 +1034,9 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
def _test_setup_session_persistence(self, session_persistence,
vs_data, verify_func,
cookie_name=None, cookie_mode=None):
cookie_name=None,
cookie_mode=None,
switch_type=False):
with mock.patch.object(self.pp_client, 'create_or_overwrite'
) as mock_create_pp, \
mock.patch.object(self.pp_cookie_client, 'create_or_overwrite'
@ -1001,10 +1049,15 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
self.pool.session_persistence = session_persistence
pool_dict = lb_translators.lb_pool_obj_to_dict(self.pool)
pp_id, post_func = p_utils.setup_session_persistence(
self.nsxpolicy, pool_dict, [], self.listener_dict, vs_data)
self.nsxpolicy, pool_dict, [], switch_type,
self.listener_dict, vs_data)
pp_id_suffix = ""
if session_persistence:
self.assertEqual(LB_PP_ID, pp_id)
if session_persistence.type == "SOURCE_IP":
pp_id_suffix = "sourceip"
elif session_persistence.type in ["HTTP_COOKIE", "APP_COOKIE"]:
pp_id_suffix = "cookie"
self.assertEqual("%s_%s" % (LB_PP_ID, pp_id_suffix), pp_id)
else:
self.assertIsNone(pp_id)
self.assertEqual(
@ -1017,20 +1070,21 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
else mock_update_pp)
def test_setup_session_persistence_sourceip_new_profile(self):
sess_persistence = lb_models.SessionPersistence(POOL_ID, 'SOURCE_IP')
sess_persistence = lb_models.SessionPersistence(
"%s_sourceip" % LB_PP_ID, 'SOURCE_IP')
self._test_setup_session_persistence(
sess_persistence, {'id': LB_VS_ID}, self._verify_create)
def test_setup_session_persistence_httpcookie_new_profile(self):
sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'HTTP_COOKIE')
"%s_cookie" % LB_PP_ID, 'HTTP_COOKIE')
self._test_setup_session_persistence(
sess_persistence, {'id': LB_VS_ID},
self._verify_create, 'default_cookie_name', 'INSERT')
def test_setup_session_persistence_appcookie_new_profile(self):
sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'APP_COOKIE', 'whatever')
"%s_cookie" % LB_PP_ID, 'APP_COOKIE', 'whatever')
self._test_setup_session_persistence(
sess_persistence, {'id': LB_VS_ID},
self._verify_create, 'whatever', 'REWRITE')
@ -1039,30 +1093,36 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
sess_persistence = None
self._test_setup_session_persistence(
sess_persistence,
{'id': LB_VS_ID, 'lb_persistence_profile_path': LB_PP_ID},
{'id': LB_VS_ID,
'lb_persistence_profile_path': "%s_sourceip" % LB_PP_ID},
self._verify_delete)
def test_setup_session_persistence_sourceip_from_existing(self):
sess_persistence = lb_models.SessionPersistence(POOL_ID, 'SOURCE_IP')
sess_persistence = lb_models.SessionPersistence(
"%s_sourceip" % LB_PP_ID, 'SOURCE_IP')
self._test_setup_session_persistence(
sess_persistence,
{'id': LB_VS_ID, 'lb_persistence_profile_path': LB_PP_ID},
{'id': LB_VS_ID,
'lb_persistence_profile_path': "%s_sourceip" % LB_PP_ID},
self._verify_update)
def test_setup_session_persistence_httpcookie_from_existing(self):
sess_persistence = lb_models.SessionPersistence(POOL_ID, 'HTTP_COOKIE')
sess_persistence = lb_models.SessionPersistence(
"%s_cookie" % LB_PP_ID, 'HTTP_COOKIE')
self._test_setup_session_persistence(
sess_persistence,
{'id': LB_VS_ID, 'lb_persistence_profile_path': LB_PP_ID},
{'id': LB_VS_ID,
'lb_persistence_profile_path': '%s_cookie' % LB_PP_ID},
self._verify_update,
'default_cookie_name', 'INSERT')
def test_setup_session_persistence_appcookie_from_existing(self):
sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'APP_COOKIE', 'whatever')
"%s_cookie" % LB_PP_ID, 'APP_COOKIE', 'whatever')
self._test_setup_session_persistence(
sess_persistence,
{'id': LB_VS_ID, 'lb_persistence_profile_path': LB_PP_ID},
{'id': LB_VS_ID,
'lb_persistence_profile_path': '%s_cookie' % LB_PP_ID},
self._verify_update,
'whatever', 'REWRITE')

View File

@ -740,7 +740,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
self.assertTrue(self.last_completor_called)
self.assertTrue(self.last_completor_succees)
def test_update_with_session_persistence_fail(self):
def test_update_with_session_persistence_change(self):
old_listener = lb_models.Listener(LISTENER_ID, LB_TENANT_ID,
'listener1', 'description',
self.pool_persistency.id,
@ -752,7 +752,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
old_listener)
sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'SOURCE_IP')
pool_persistency = lb_models.Pool(POOL_ID, LB_TENANT_ID,
pool_persistency = lb_models.Pool('new_pool_id', LB_TENANT_ID,
'pool1', '', None, 'HTTP',
'ROUND_ROBIN', loadbalancer_id=LB_ID,
listener=self.listener,
@ -773,15 +773,28 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
mock.patch.object(nsx_db, 'get_nsx_lbaas_listener_binding'
) as mock_get_listener_binding,\
mock.patch.object(nsx_db, 'get_nsx_lbaas_pool_binding'
) as mock_get_pool_binding:
) as mock_get_pool_binding, \
mock.patch.object(self.pp_client, 'create'
) as mock_create_pp, \
mock.patch.object(self.pp_client, 'delete'
) as mock_delete_pp, \
mock.patch.object(lb_utils, 'get_pool_tags'
) as mock_get_pool_tags, \
mock.patch.object(nsx_db, 'update_nsx_lbaas_pool_binding'):
mock_get_pool_tags.return_value = []
mock_get_floatingips.return_value = []
mock_get_listener_binding.return_value = LISTENER_BINDING
mock_get_pool_binding.return_value = POOL_BINDING
self.assertRaises(n_exc.BadRequest,
self.edge_driver.listener.update,
self.context, old_listener_dict,
new_listener_dict, self.completor)
self.edge_driver.listener.update(
self.context, old_listener_dict,
new_listener_dict, self.completor)
mock_create_pp.assert_called_once_with(
display_name='persistence_pool1_new_p...ol_id',
resource_type='LbSourceIpPersistenceProfile',
tags=mock.ANY)
# No reason to check parameters here, it's
# all mocked out
mock_delete_pp.assert_called_once()
def test_delete(self):
with mock.patch.object(nsx_db, 'get_nsx_lbaas_listener_binding'
@ -1155,14 +1168,38 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
{'scope': 'os-lbaas-listener-id', 'tag': 'listener-x'}])
mock_create_pp.assert_not_called()
def _verify_switch(self, res_type, cookie_name, cookie_mode,
mock_create_pp, mock_update_pp):
if cookie_name:
mock_create_pp.assert_called_once_with(
resource_type=res_type,
cookie_name=cookie_name,
cookie_mode=cookie_mode,
display_name=mock.ANY,
tags=mock.ANY)
else:
mock_create_pp.assert_called_once_with(
LB_PP_ID,
resource_type=res_type,
display_name=mock.ANY,
tags=mock.ANY)
# Compare tags - kw args are the last item of a mock call tuple
self.assertItemsEqual(mock_create_pp.mock_calls[0][-1]['tags'],
[{'scope': 'os-lbaas-lb-id', 'tag': 'xxx-xxx'},
{'scope': 'os-lbaas-lb-name', 'tag': 'lb1'},
{'scope': 'os-lbaas-listener-id', 'tag': 'listener-x'}])
def _verify_delete(self, res_type, cookie_name, cookie_mode,
mock_create_pp, mock_update_pp):
# do not check delete mock as deletion is not done in
# setup_session_persistence
mock_create_pp.assert_not_called()
mock_update_pp.assert_not_called()
def _test_setup_session_persistence(self, session_persistence,
res_type, vs_data, verify_func,
cookie_name=None, cookie_mode=None):
cookie_name=None, cookie_mode=None,
switch_type=False):
with mock.patch.object(self.pp_client, 'create'
) as mock_create_pp, \
mock.patch.object(self.pp_client, 'update', return_value=None,
@ -1172,12 +1209,16 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
self.pool.session_persistence = session_persistence
pool_dict = lb_translators.lb_pool_obj_to_dict(self.pool)
pp_id, post_func = lb_utils.setup_session_persistence(
self.nsxlib, pool_dict, [], self.listener_dict, vs_data)
self.nsxlib, pool_dict, [], switch_type, self.listener_dict,
vs_data)
if session_persistence:
self.assertEqual(LB_PP_ID, pp_id)
else:
self.assertIsNone(pp_id)
if not session_persistence or switch_type:
# Also verify post_func for delete
self.assertEqual((self.nsxlib, LB_PP_ID,),
post_func.args)
verify_func(res_type, cookie_name, cookie_mode,
@ -1239,6 +1280,17 @@ class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
self._verify_update,
'whatever', 'REWRITE')
def test_setup_session_persistence_appcookie_switch_type(self):
sess_persistence = lb_models.SessionPersistence(
POOL_ID, 'APP_COOKIE', 'whatever')
res_type = 'LbCookiePersistenceProfile'
self._test_setup_session_persistence(
sess_persistence, res_type,
{'id': LB_VS_ID, 'persistence_profile_id': LB_PP_ID},
self._verify_switch,
'whatever', 'REWRITE',
switch_type=True)
class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2):
def setUp(self):