Merge "[NSX-v3+p] Support switching session persistence type"
This commit is contained in:
commit
31ad4b72ea
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user