Fix duplicate VIP address error reporting
With the transition to supporting provider drivers, the error reporting for cases where the user requests a VIP address that is already in use was broken. This patch corrects that such that the user will get a clear error message. Here is an example output from the CLI: The VIP IP address is already in use: IP address 172.24.4.25 already allocated in subnet fb3df045-07f9-4bd5-a7fb-12b016e5f873 (HTTP 409) (Request-ID: req-cece42f5-6dc2-49f8-a551-c11fd1abeb81) Closes-Bug: #2052682 Depends-On: https://review.opendev.org/c/openstack/octavia-lib/+/949546 Change-Id: I9ee1913e57a1addd623c993d9c9083fad9f2bb33
This commit is contained in:
@@ -127,6 +127,12 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
|
||||
|
||||
try:
|
||||
vip, add_vips = network_driver.allocate_vip(lb_obj)
|
||||
except network_base.VIPInUseException as e:
|
||||
message = str(e)
|
||||
if getattr(e, 'orig_msg', None) is not None:
|
||||
message = e.orig_msg
|
||||
raise exceptions.Conflict(user_fault_string=message,
|
||||
operator_fault_string=message)
|
||||
except network_base.AllocateVIPException as e:
|
||||
message = str(e)
|
||||
if getattr(e, 'orig_msg', None) is not None:
|
||||
|
||||
@@ -51,6 +51,10 @@ def call_provider(provider, driver_method, *args, **kwargs):
|
||||
|
||||
try:
|
||||
return driver_method(*args, **kwargs)
|
||||
except lib_exceptions.Conflict as e:
|
||||
LOG.info("Provider '%s' raised a conflict error: %s",
|
||||
provider, e.operator_fault_string)
|
||||
raise exceptions.VIPAddressConflict(msg=e.user_fault_string)
|
||||
except lib_exceptions.DriverError as e:
|
||||
LOG.exception("Provider '%s' raised a driver error: %s",
|
||||
provider, e.operator_fault_string)
|
||||
|
||||
@@ -440,3 +440,8 @@ class ListenerNoChildren(APIException):
|
||||
class MemberSRIOVDisabled(APIException):
|
||||
msg = _('The load balancer flavor does not allow SR-IOV member ports.')
|
||||
code = 400
|
||||
|
||||
|
||||
class VIPAddressConflict(APIException):
|
||||
msg = _('The VIP IP address is already in use: %(msg)s')
|
||||
code = 409
|
||||
|
||||
@@ -591,6 +591,15 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||
port[constants.FIXED_IPS] = fixed_ips
|
||||
try:
|
||||
new_port = self.network_proxy.create_port(**port)
|
||||
except os_exceptions.ConflictException as e:
|
||||
message = _('Error creating neutron port on network '
|
||||
'{network_id} due to {e}.').format(
|
||||
network_id=load_balancer.vip.network_id, e=repr(e))
|
||||
raise base.VIPInUseException(
|
||||
message,
|
||||
orig_msg=getattr(e, 'details', None),
|
||||
orig_code=getattr(e, constants.STATUS_CODE, None),
|
||||
)
|
||||
except Exception as e:
|
||||
message = _('Error creating neutron port on network '
|
||||
'{network_id} due to {e}.').format(
|
||||
|
||||
@@ -74,6 +74,19 @@ class TestAmphoraDriver(base.TestRpc):
|
||||
self.sample_data.provider_vip_dict,
|
||||
[self.sample_data.provider_additional_vip_dict])
|
||||
|
||||
@mock.patch('octavia.common.utils.get_network_driver')
|
||||
def test_create_vip_port_conflict(self, mock_get_net_driver):
|
||||
mock_net_driver = mock.MagicMock()
|
||||
mock_get_net_driver.return_value = mock_net_driver
|
||||
mock_net_driver.allocate_vip.side_effect = (
|
||||
network_base.VIPInUseException())
|
||||
|
||||
self.assertRaises(exceptions.Conflict,
|
||||
self.amp_driver.create_vip_port,
|
||||
self.sample_data.lb_id, self.sample_data.project_id,
|
||||
self.sample_data.provider_vip_dict,
|
||||
[self.sample_data.provider_additional_vip_dict])
|
||||
|
||||
# Load Balancer
|
||||
@mock.patch('oslo_messaging.RPCClient.cast')
|
||||
def test_loadbalancer_create(self, mock_cast):
|
||||
|
||||
@@ -39,6 +39,12 @@ class TestUtils(base.TestCase):
|
||||
"arg1", foo="arg2")
|
||||
mock_driver_method.assert_called_with("arg1", foo="arg2")
|
||||
|
||||
# Test driver raising VIPAddressConflict
|
||||
mock_driver_method.side_effect = lib_exceptions.Conflict
|
||||
self.assertRaises(exceptions.VIPAddressConflict,
|
||||
utils.call_provider, "provider_name",
|
||||
mock_driver_method)
|
||||
|
||||
# Test driver raising DriverError
|
||||
mock_driver_method.side_effect = lib_exceptions.DriverError
|
||||
self.assertRaises(exceptions.ProviderDriverError,
|
||||
|
||||
@@ -700,6 +700,15 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
self.assertRaises(network_base.AllocateVIPException,
|
||||
self.driver.allocate_vip, fake_lb)
|
||||
|
||||
def test_allocate_vip_conflict(self):
|
||||
fake_lb_vip = data_models.Vip(
|
||||
subnet_id=t_constants.MOCK_SUBNET_ID)
|
||||
fake_lb = data_models.LoadBalancer(id='1', vip=fake_lb_vip)
|
||||
create_port = self.driver.network_proxy.create_port
|
||||
create_port.side_effect = os_exceptions.ConflictException
|
||||
self.assertRaises(network_base.VIPInUseException,
|
||||
self.driver.allocate_vip, fake_lb)
|
||||
|
||||
def test_allocate_vip_when_port_creation_fails(self):
|
||||
fake_lb_vip = data_models.Vip(
|
||||
subnet_id=t_constants.MOCK_SUBNET_ID)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixes the error reporting when a user requests a VIP IP address that is
|
||||
already in use.
|
||||
Reference in New Issue
Block a user