Stop masking VIP allocate neutron errors
Previously the neutron network driver was masking the actual error being returned from neutron while doing a VIP port allocation. This patch will pass through the neutron error to the user if it is an API ready exception giving the user more useful information about the error neutron is reporting. For example that the requested VIP address is already allocated. Change-Id: Ic327b06ff9ccf9ae0c9931a8e6569c20d03c4a79 Closes-Bug: #1714593 Story: 1714593 Task: 5005
This commit is contained in:
parent
9df70995be
commit
c1afc15863
|
@ -199,7 +199,16 @@ class LoadBalancersController(base.BaseController):
|
|||
def _create_vip_port_if_not_exist(self, load_balancer_db):
|
||||
"""Create vip port."""
|
||||
network_driver = utils.get_network_driver()
|
||||
vip = network_driver.allocate_vip(load_balancer_db)
|
||||
try:
|
||||
vip = network_driver.allocate_vip(load_balancer_db)
|
||||
except Exception as e:
|
||||
# Convert neutron style exception to octavia style
|
||||
# if the error was API ready
|
||||
if e.orig_code is not None:
|
||||
e.code = e.orig_code
|
||||
e.message = e.orig_msg
|
||||
e.msg = e.orig_msg
|
||||
raise e
|
||||
return vip
|
||||
|
||||
@wsme_pecan.wsexpose(lb_types.LoadBalancerFullRootResponse,
|
||||
|
|
|
@ -31,11 +31,15 @@ class OctaviaException(Exception):
|
|||
with the keyword arguments provided to the constructor.
|
||||
"""
|
||||
message = _("An unknown exception occurred.")
|
||||
orig_msg = None
|
||||
orig_code = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
try:
|
||||
if len(args) > 0:
|
||||
self.message = args[0]
|
||||
self.orig_msg = kwargs.get('orig_msg')
|
||||
self.orig_code = kwargs.get('orig_code')
|
||||
super(OctaviaException, self).__init__(self.message % kwargs)
|
||||
self.msg = self.message % kwargs
|
||||
except Exception:
|
||||
|
|
|
@ -350,12 +350,15 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
|||
port['port']['fixed_ips'] = [fixed_ip]
|
||||
try:
|
||||
new_port = self.neutron_client.create_port(port)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
message = _('Error creating neutron port on network '
|
||||
'{network_id}.').format(
|
||||
network_id=load_balancer.vip.network_id)
|
||||
LOG.exception(message)
|
||||
raise base.AllocateVIPException(message)
|
||||
raise base.AllocateVIPException(
|
||||
message,
|
||||
orig_msg=getattr(e, 'message', None),
|
||||
orig_code=getattr(e, 'status_code', None))
|
||||
new_port = utils.convert_port_dict_to_model(new_port)
|
||||
return self._port_to_vip(new_port, load_balancer)
|
||||
|
||||
|
|
|
@ -433,6 +433,34 @@ class TestLoadBalancer(base.BaseAPITest):
|
|||
self.assertEqual(network.id, api_lb.get('vip_network_id'))
|
||||
self.assertEqual(port.id, api_lb.get('vip_port_id'))
|
||||
|
||||
def test_create_neutron_failure(self):
|
||||
subnet = network_models.Subnet(id=uuidutils.generate_uuid())
|
||||
network = network_models.Network(id=uuidutils.generate_uuid(),
|
||||
subnets=[subnet])
|
||||
port = network_models.Port(id=uuidutils.generate_uuid(),
|
||||
network_id=network.id)
|
||||
lb_json = {
|
||||
'name': 'test1', 'description': 'test1_desc',
|
||||
'vip_address': '10.0.0.1', 'vip_subnet_id': subnet.id,
|
||||
'vip_network_id': network.id, 'vip_port_id': port.id,
|
||||
'admin_state_up': False, 'project_id': self.project_id}
|
||||
body = self._build_body(lb_json)
|
||||
with mock.patch(
|
||||
"octavia.network.drivers.noop_driver.driver.NoopManager"
|
||||
".get_network") as mock_get_network, mock.patch(
|
||||
"octavia.network.drivers.noop_driver.driver.NoopManager"
|
||||
".get_port") as mock_get_port, mock.patch(
|
||||
"octavia.network.drivers.noop_driver.driver.NoopManager"
|
||||
".allocate_vip") as mock_allocate_vip:
|
||||
mock_get_network.return_value = network
|
||||
mock_get_port.return_value = port
|
||||
mock_allocate_vip.side_effect = TestNeutronException(
|
||||
"octavia_msg", "neutron_msg", 409)
|
||||
response = self.post(self.LBS_PATH, body, status=409)
|
||||
# Make sure the faultstring contains the neutron error and not
|
||||
# the octavia error message
|
||||
self.assertIn("neutron_msg", response.json.get("faultstring"))
|
||||
|
||||
def test_create_with_long_name(self):
|
||||
lb_json = {'name': 'n' * 256,
|
||||
'vip_subnet_id': uuidutils.generate_uuid(),
|
||||
|
@ -2445,3 +2473,14 @@ class TestLoadBalancerGraph(base.BaseAPITest):
|
|||
|
||||
self.conf.config(group='api_settings', auth_strategy=auth_strategy)
|
||||
self.assertEqual(self.NOT_AUTHORIZED_BODY, res.json)
|
||||
|
||||
|
||||
class TestNeutronException(Exception):
|
||||
|
||||
def __init__(self, message, orig_msg, orig_code):
|
||||
self.message = message
|
||||
self.orig_msg = orig_msg
|
||||
self.orig_code = orig_code
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.message)
|
||||
|
|
Loading…
Reference in New Issue