Fix Load balancer remains on PENDING_CREATE
On LB creation process, when heavy load env situation
arises, neutron client could return several errors
that is currently not under control. At this way
Octavia API is not receiving an update status and LB
keeps on PENDING_CREATE without any apparent error.
This patch cover error on request over neutron client
(subnet, list ports...) in order to update to Octavia
API with ERROR status in case this situation achieved.
Closes-Bug: #1974052
Change-Id: I04edbbd631f63b79c10916ce2391bb0cb95c1c19
(cherry picked from commit 28d378868f
)
This commit is contained in:
parent
9013681f1f
commit
1aa4be5bd1
|
@ -893,27 +893,49 @@ class OvnProviderHelper():
|
|||
def lb_create(self, loadbalancer, protocol=None):
|
||||
port = None
|
||||
subnet = {}
|
||||
neutron_client = clients.get_neutron_client()
|
||||
if loadbalancer.get(constants.VIP_PORT_ID):
|
||||
# In case we don't have vip_network_id
|
||||
port = neutron_client.show_port(
|
||||
loadbalancer[constants.VIP_PORT_ID])['port']
|
||||
for ip in port['fixed_ips']:
|
||||
if ip['ip_address'] == loadbalancer[constants.VIP_ADDRESS]:
|
||||
subnet = neutron_client.show_subnet(
|
||||
ip['subnet_id'])['subnet']
|
||||
break
|
||||
elif (loadbalancer.get(constants.VIP_NETWORK_ID) and
|
||||
loadbalancer.get(constants.VIP_ADDRESS)):
|
||||
ports = neutron_client.list_ports(
|
||||
network_id=loadbalancer[constants.VIP_NETWORK_ID])
|
||||
for p in ports['ports']:
|
||||
for ip in p['fixed_ips']:
|
||||
try:
|
||||
neutron_client = clients.get_neutron_client()
|
||||
if loadbalancer.get(constants.VIP_PORT_ID):
|
||||
# In case we don't have vip_network_id
|
||||
port = neutron_client.show_port(
|
||||
loadbalancer[constants.VIP_PORT_ID])['port']
|
||||
for ip in port['fixed_ips']:
|
||||
if ip['ip_address'] == loadbalancer[constants.VIP_ADDRESS]:
|
||||
port = p
|
||||
subnet = neutron_client.show_subnet(
|
||||
ip['subnet_id'])['subnet']
|
||||
break
|
||||
elif (loadbalancer.get(constants.VIP_NETWORK_ID) and
|
||||
loadbalancer.get(constants.VIP_ADDRESS)):
|
||||
ports = neutron_client.list_ports(
|
||||
network_id=loadbalancer[constants.VIP_NETWORK_ID])
|
||||
for p in ports['ports']:
|
||||
for ip in p['fixed_ips']:
|
||||
if ip['ip_address'] == loadbalancer[
|
||||
constants.VIP_ADDRESS]:
|
||||
port = p
|
||||
subnet = neutron_client.show_subnet(
|
||||
ip['subnet_id'])['subnet']
|
||||
break
|
||||
except Exception:
|
||||
LOG.error('Cannot get info from neutron client')
|
||||
LOG.exception(ovn_const.EXCEPTION_MSG, "creation of loadbalancer")
|
||||
# Any Exception set the status to ERROR
|
||||
if isinstance(port, dict):
|
||||
try:
|
||||
self.delete_vip_port(port.get('id'))
|
||||
LOG.warning("Deleting the VIP port %s since LB went into "
|
||||
"ERROR state", str(port.get('id')))
|
||||
except Exception:
|
||||
LOG.exception("Error deleting the VIP port %s upon "
|
||||
"loadbalancer %s creation failure",
|
||||
str(port.get('id')),
|
||||
str(loadbalancer[constants.ID]))
|
||||
status = {
|
||||
constants.LOADBALANCERS: [
|
||||
{constants.ID: loadbalancer[constants.ID],
|
||||
constants.PROVISIONING_STATUS: constants.ERROR,
|
||||
constants.OPERATING_STATUS: constants.ERROR}]}
|
||||
return status
|
||||
|
||||
# If protocol set make sure its lowercase
|
||||
protocol = protocol.lower() if protocol else []
|
||||
|
|
|
@ -632,6 +632,16 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
|
|||
def test_lb_create_on_multi_protocol_SCTP(self):
|
||||
self._test_lb_create_on_multi_protocol('SCTP')
|
||||
|
||||
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
|
||||
def test_lb_create_neutron_client_exception(self, net_cli):
|
||||
net_cli.return_value.list_ports.return_value = self.ports
|
||||
net_cli.return_value.show_subnet.side_effect = [n_exc.NotFound]
|
||||
status = self.helper.lb_create(self.lb)
|
||||
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
|
||||
constants.ERROR)
|
||||
self.assertEqual(status['loadbalancers'][0]['operating_status'],
|
||||
constants.ERROR)
|
||||
|
||||
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
|
||||
@mock.patch.object(ovn_helper.OvnProviderHelper, 'delete_vip_port')
|
||||
def test_lb_create_exception(self, del_port, net_cli):
|
||||
|
|
Loading…
Reference in New Issue