Browse Source

Merge "Don't fail if VIP already exist or has been deleted before" into stable/train

tags/7.1.0
Zuul Gerrit Code Review 1 month ago
parent
commit
75fe49a61b
2 changed files with 81 additions and 10 deletions
  1. +29
    -8
      networking_ovn/octavia/ovn_driver.py
  2. +52
    -2
      networking_ovn/tests/unit/octavia/test_ovn_driver.py

+ 29
- 8
networking_ovn/octavia/ovn_driver.py View File

@@ -1014,12 +1014,8 @@ class OvnProviderHelper(object):
'loadbalancers': [{"id": loadbalancer['id'],
"provisioning_status": constants.ERROR,
"operating_status": constants.ERROR}]}
try:
# Delete VIP port from neutron.
self.delete_vip_port(port_id)
except n_exc.PortNotFoundClient:
LOG.warning("Port %s could not be found. Please "
"check Neutron logs", port_id)
# Delete VIP port from neutron.
self.delete_vip_port(port_id)
return status

def _lb_delete(self, loadbalancer, ovn_lb, status):
@@ -1755,11 +1751,36 @@ class OvnProviderHelper(object):
except KeyError:
pass
network_driver = get_network_driver()
return network_driver.neutron_client.create_port(port)
try:
return network_driver.neutron_client.create_port(port)
except n_exc.IpAddressAlreadyAllocatedClient:
# Sometimes the VIP is already created (race-conditions)
# Lets get the it from Neutron API.
ports = network_driver.neutron_client.list_ports(
network_id=vip_d['vip_network_id'],
name='%s%s' % (ovn_const.LB_VIP_PORT_PREFIX, lb_id))
if not ports['ports']:
LOG.error('Cannot create/get LoadBalancer VIP port with '
'fixed IP: %s', vip_d['vip_address'])
status = {'loadbalancers': [{
"id": lb_id,
"provisioning_status": constants.ERROR,
"operating_status": constants.ERROR}]}
self._update_status_to_octavia(status)
return
# there should only be one port returned
port = ports['ports'][0]
LOG.debug('VIP Port already exists, uuid: %s', port['id'])
return {'port': port}

def delete_vip_port(self, port_id):
network_driver = get_network_driver()
network_driver.neutron_client.delete_port(port_id)
try:
network_driver.neutron_client.delete_port(port_id)
except n_exc.PortNotFoundClient:
LOG.warning("Port %s could not be found. Please "
"check Neutron logs. Perhaps port "
"was already deleted.", port_id)

def handle_vip_fip(self, fip_info):
ovn_lb = fip_info['ovn_lb']


+ 52
- 2
networking_ovn/tests/unit/octavia/test_ovn_driver.py View File

@@ -1005,8 +1005,8 @@ class TestOvnProviderHelper(TestOvnOctaviaBase):
@mock.patch('networking_ovn.octavia.ovn_driver.get_network_driver')
@mock.patch.object(ovn_driver.OvnProviderHelper, 'delete_vip_port')
def test_lb_delete_port_not_found(self, del_port, net_dr):
net_dr.return_value.neutron_client.delete_port.return_value = None
del_port.side_effect = [n_exc.PortNotFoundClient]
net_dr.return_value.neutron_client.delete_port.side_effect = (
[n_exc.PortNotFoundClient])
status = self.helper.lb_delete(self.ovn_lb)
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
constants.DELETED)
@@ -2520,6 +2520,56 @@ class TestOvnProviderHelper(TestOvnOctaviaBase):
mock.call().neutron_client.create_port(expected_dict)]
gn.assert_has_calls(expected_call)

@mock.patch('networking_ovn.octavia.ovn_driver.get_network_driver')
def test_create_vip_port_vip_selected_already_exist(self, net_dr):
net_dr.return_value.neutron_client.create_port.side_effect = [
n_exc.IpAddressAlreadyAllocatedClient]
net_dr.return_value.neutron_client.list_ports.return_value = {
'ports': [
{'name': 'ovn-lb-vip-' + self.loadbalancer_id,
'id': self.loadbalancer_id}]}
self.vip_dict['vip_address'] = '10.1.10.1'
ret = self.helper.create_vip_port(
self.project_id,
self.loadbalancer_id,
self.vip_dict)
expected = {
'port': {
'name': '%s%s' % (ovn_const.LB_VIP_PORT_PREFIX,
self.loadbalancer_id),
'id': self.loadbalancer_id}}
self.assertDictEqual(expected, ret)
expected_call = [
mock.call().neutron_client.list_ports(
network_id='%s' % self.vip_dict['vip_network_id'],
name='%s%s' % (ovn_const.LB_VIP_PORT_PREFIX,
self.loadbalancer_id))]
net_dr.assert_has_calls(expected_call)

@mock.patch('networking_ovn.octavia.ovn_driver.get_network_driver')
def test_create_vip_port_vip_selected_other_allocation_exist(self, net_dr):
net_dr.return_value.neutron_client.create_port.side_effect = [
n_exc.IpAddressAlreadyAllocatedClient]
net_dr.return_value.neutron_client.list_ports.return_value = {
'ports': []}
self.vip_dict['vip_address'] = '10.1.10.1'
ret = self.helper.create_vip_port(
self.project_id,
self.loadbalancer_id,
self.vip_dict)
self.assertIsNone(ret)
expected_call = [
mock.call().neutron_client.list_ports(
network_id='%s' % self.vip_dict['vip_network_id'],
name='%s%s' % (ovn_const.LB_VIP_PORT_PREFIX,
self.loadbalancer_id))]
net_dr.assert_has_calls(expected_call)
self.helper._update_status_to_octavia.assert_called_once_with(
{'loadbalancers':
[{'id': self.loadbalancer_id,
'provisioning_status': 'ERROR',
'operating_status': 'ERROR'}]})

def test_get_member_info(self):
ret = self.helper.get_member_info(self.pool_id)
self.assertEqual([(self.member_id, '%s:%s' % (self.member_address,


Loading…
Cancel
Save