NSXv3: Handle association fip to vip in different cases

User may associate fip to loadbalancer's vip_port when there is no
listener yet which means there is no virtual server yet on backend.
There is another case that user may create virtual server after
association of fip to vip_port. In this case, we need to use the
fip as the virtual server's vip ip_address.

This patch handles the above two cases which makes association of
floating ip to vip port gracefully.

Change-Id: Ic78d80109bbd0abf1b2b59786275cfa5b1a9d59c
This commit is contained in:
Tong Liu 2017-12-04 22:18:23 -08:00 committed by Gary Kotton
parent bb94cc7461
commit 073e7512b2
3 changed files with 31 additions and 20 deletions

View File

@ -3796,13 +3796,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
for vs in vs_list['results']:
vs_client.update_virtual_server_with_vip(vs['id'],
vip_address)
else:
msg = (_('Virtual server cannot be found with scope '
'%(scope)s and tag %(tag)s') %
{'scope': 'os-lbaas-lb-id', 'tag': device_id})
LOG.error(msg)
raise nsx_exc.NsxResourceNotFound(res_name='virtual_server',
res_id=device_id)
def _create_floating_ip_wrapper(self, context, floatingip):
if cfg.CONF.api_replay_mode:
@ -3836,8 +3829,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if device_owner == const.DEVICE_OWNER_LOADBALANCERV2:
try:
self._update_lb_vip(port_data, fip_address)
except (nsx_lib_exc.ManagerError,
nsx_exc.NsxResourceNotFound):
except nsx_lib_exc.ManagerError:
with excutils.save_and_reraise_exception():
super(NsxV3Plugin, self).delete_floatingip(
context, new_fip['id'])
@ -3869,10 +3861,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
is_lb_port = True
try:
self._update_lb_vip(port_data, fixed_ip_address)
except nsx_exc.NsxResourceNotFound:
LOG.warning("Virtual server cannot be found to "
"update VIP for fip %(fip_id)s",
{'fip_id': fip_id})
except nsx_lib_exc.ManagerError as e:
LOG.error("Exception when updating vip ip_address"
"on vip_port %(port)s: %(err)s",
{'port': port_id, 'err': e})
if router_id and not is_lb_port:
try:

View File

@ -37,8 +37,18 @@ class EdgeListenerManager(base_mgr.Nsxv3LoadbalancerBaseManager):
def _get_virtual_server_kwargs(self, context, listener, vs_name, tags,
app_profile_id, certificate=None):
# If loadbalancer vip_port already has floating ip, use floating
# IP as the virtual server VIP address. Else, use the loadbalancer
# vip_address directly on virtual server.
filters = {'port_id': [listener.loadbalancer.vip_port_id]}
floating_ips = self.core_plugin.get_floatingips(context,
filters=filters)
if floating_ips:
lb_vip_address = floating_ips[0]['floating_ip_address']
else:
lb_vip_address = listener.loadbalancer.vip_address
kwargs = {'enabled': listener.admin_state_up,
'ip_address': listener.loadbalancer.vip_address,
'ip_address': lb_vip_address,
'port': listener.protocol_port,
'application_profile_id': app_profile_id}
if vs_name:

View File

@ -265,8 +265,10 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
return 'listener'
def _create_listener(self, protocol='HTTP'):
with mock.patch.object(self.app_client, 'create'
) as mock_create_app_profile, \
with mock.patch.object(self.core_plugin, 'get_floatingips'
) as mock_get_floatingips, \
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'
@ -275,6 +277,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
) as mock_add_virtual_server, \
mock.patch.object(nsx_db, 'add_nsx_lbaas_listener_binding'
) as mock_add_listener_binding:
mock_get_floatingips.return_value = []
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
@ -302,8 +305,10 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
self._create_listener(protocol='HTTPS')
def test_create_terminated_https(self):
with mock.patch.object(self.tm_client, 'create_cert'
) as mock_create_cert, \
with mock.patch.object(self.core_plugin, 'get_floatingips'
) as mock_get_floatingips, \
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'
@ -314,6 +319,7 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
) as mock_add_virtual_server, \
mock.patch.object(nsx_db, 'add_nsx_lbaas_listener_binding'
) as mock_add_listener_binding:
mock_get_floatingips.return_value = []
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}
@ -337,8 +343,11 @@ class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
'listener1-new', 'new-description',
None, LB_ID, protocol_port=80,
loadbalancer=self.lb)
with mock.patch.object(nsx_db, 'get_nsx_lbaas_listener_binding'
) as mock_get_listener_binding:
with mock.patch.object(self.core_plugin, 'get_floatingips'
) as mock_get_floatingips, \
mock.patch.object(nsx_db, 'get_nsx_lbaas_listener_binding'
) as mock_get_listener_binding:
mock_get_floatingips.return_value = []
mock_get_listener_binding.return_value = LISTENER_BINDING
self.edge_driver.listener.update(self.context, self.listener,