Octavia driver to honor Octavia API status codes
Currently the Octavia driver for neutron-lbaas is not honoring Octavia API status codes. This can lead to a race condition where the status update thread is behind the actual object status in Octavia. This updates the driver to raise the appropriate status code to the neutron API. Change-Id: I3ec78578c941e4648d1fccfc92b349e3415015e6 Story: 2001257 Task: 5787
This commit is contained in:
parent
dba5e27ede
commit
cfea70bdc4
|
@ -54,3 +54,27 @@ class CertificateStorageException(TLSException):
|
|||
class LoadbalancerReschedulingFailed(exceptions.Conflict):
|
||||
message = _("Failed rescheduling loadbalancer %(loadbalancer_id)s: "
|
||||
"no eligible lbaas agent found.")
|
||||
|
||||
|
||||
class BadRequestException(exceptions.BadRequest):
|
||||
message = "%(fault_string)s"
|
||||
|
||||
|
||||
class ConflictException(exceptions.Conflict):
|
||||
message = "%(fault_string)s"
|
||||
|
||||
|
||||
class NotAuthorizedException(exceptions.NotAuthorized):
|
||||
message = "%(fault_string)s"
|
||||
|
||||
|
||||
class NotFoundException(exceptions.NotFound):
|
||||
message = "%(fault_string)s"
|
||||
|
||||
|
||||
class ServiceUnavailableException(exceptions.ServiceUnavailable):
|
||||
message = "%(fault_string)s"
|
||||
|
||||
|
||||
class UnknownException(exceptions.NeutronException):
|
||||
message = "%(fault_string)s"
|
||||
|
|
|
@ -25,6 +25,7 @@ from oslo_utils import excutils
|
|||
import requests
|
||||
|
||||
from neutron_lbaas._i18n import _
|
||||
from neutron_lbaas.common import exceptions
|
||||
from neutron_lbaas.common import keystone
|
||||
from neutron_lbaas.drivers import driver_base
|
||||
from neutron_lbaas.drivers.octavia import octavia_messaging_consumer
|
||||
|
@ -144,6 +145,27 @@ class OctaviaRequest(object):
|
|||
LOG.debug("Octavia Response Code: {0}".format(r.status_code))
|
||||
LOG.debug("Octavia Response Body: {0}".format(r.content))
|
||||
LOG.debug("Octavia Response Headers: {0}".format(r.headers))
|
||||
# We need to raise Octavia errors up to neutron API.
|
||||
try:
|
||||
fault_string = jsonutils.loads(r.content)['faultstring']
|
||||
except Exception:
|
||||
fault_string = "Unknown Octavia error."
|
||||
if r.status_code == 400:
|
||||
raise exceptions.BadRequestException(fault_string=fault_string)
|
||||
elif r.status_code == 401:
|
||||
raise exceptions.NotAuthorizedException(fault_string=fault_string)
|
||||
elif r.status_code == 403:
|
||||
raise exceptions.NotAuthorizedException(fault_string=fault_string)
|
||||
elif r.status_code == 404:
|
||||
raise exceptions.NotFoundException(fault_string=fault_string)
|
||||
elif r.status_code == 409:
|
||||
raise exceptions.ConflictException(fault_string=fault_string)
|
||||
elif r.status_code == 500:
|
||||
raise exceptions.UnknownException(fault_string=fault_string)
|
||||
elif r.status_code == 503:
|
||||
raise exceptions.ServiceUnavailableException(
|
||||
fault_string=fault_string)
|
||||
|
||||
if method != 'DELETE':
|
||||
return r.json()
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ from oslo_utils import encodeutils
|
|||
|
||||
from neutron_lbaas import agent_scheduler as agent_scheduler_v2
|
||||
import neutron_lbaas.common.cert_manager
|
||||
from neutron_lbaas.common import exceptions
|
||||
from neutron_lbaas.common.tls_utils import cert_parser
|
||||
from neutron_lbaas.db.loadbalancer import loadbalancer_dbv2 as ldbv2
|
||||
from neutron_lbaas.db.loadbalancer import models
|
||||
|
@ -178,6 +179,13 @@ class LoadBalancerPluginv2(loadbalancerv2.LoadBalancerPluginBaseV2,
|
|||
except (lbaas_agentschedulerv2.NoEligibleLbaasAgent,
|
||||
lbaas_agentschedulerv2.NoActiveLbaasAgent) as no_agent:
|
||||
raise no_agent
|
||||
# Pass these exceptions through to neutron
|
||||
except (exceptions.ConflictException,
|
||||
exceptions.NotFoundException,
|
||||
exceptions.NotAuthorizedException,
|
||||
exceptions.BadRequestException,
|
||||
exceptions.ServiceUnavailableException):
|
||||
raise
|
||||
except Exception as e:
|
||||
LOG.exception("There was an error in the driver")
|
||||
self._handle_driver_error(context, db_entity)
|
||||
|
|
|
@ -18,6 +18,7 @@ import mock
|
|||
from neutron_lib import context
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron_lbaas.common import exceptions
|
||||
from neutron_lbaas.drivers.octavia import driver
|
||||
from neutron_lbaas.services.loadbalancer import constants
|
||||
from neutron_lbaas.services.loadbalancer import data_models
|
||||
|
@ -625,3 +626,65 @@ class TestThreadedDriver(BaseOctaviaDriverTest):
|
|||
delete=False,
|
||||
lb_create=True)
|
||||
self.assertEqual(expected_vip, self.lb.vip_address)
|
||||
|
||||
|
||||
class TestOctaviaRequest(test_db_loadbalancerv2.LbaasPluginDbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestOctaviaRequest, self).setUp()
|
||||
self.OctaviaRequestObj = driver.OctaviaRequest("TEST_URL",
|
||||
"TEST_SESSION")
|
||||
|
||||
@mock.patch('requests.request')
|
||||
def test_request(self, mock_requests):
|
||||
mock_response = mock.MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.content = "TEST"
|
||||
mock_response.headers = "TEST headers"
|
||||
mock_response.json.return_value = "TEST json"
|
||||
|
||||
mock_requests.return_value = mock_response
|
||||
|
||||
fake_header = {'X-Auth-Token': "TEST_TOKEN"}
|
||||
result = self.OctaviaRequestObj.request("TEST_METHOD", "TEST_URL",
|
||||
headers=fake_header)
|
||||
|
||||
self.assertEqual("TEST json", result)
|
||||
|
||||
@mock.patch('requests.request')
|
||||
def _test_request_Octavia(self, status_code, exception, mock_requests):
|
||||
mock_response = mock.MagicMock()
|
||||
mock_response.status_code = status_code
|
||||
mock_response.content = '{"faultstring": "FAILED"}'
|
||||
mock_response.headers = "TEST headers"
|
||||
|
||||
mock_requests.return_value = mock_response
|
||||
|
||||
fake_header = {'X-Auth-Token': "TEST_TOKEN"}
|
||||
self.assertRaisesRegex(exception,
|
||||
"FAILED",
|
||||
self.OctaviaRequestObj.request,
|
||||
"TEST_METHOD", "TEST_URL", headers=fake_header)
|
||||
|
||||
mock_response.json.assert_not_called()
|
||||
|
||||
def test_request_Octavia_400(self):
|
||||
self._test_request_Octavia(400, exceptions.BadRequestException)
|
||||
|
||||
def test_request_Octavia_401(self):
|
||||
self._test_request_Octavia(401, exceptions.NotAuthorizedException)
|
||||
|
||||
def test_request_Octavia_403(self):
|
||||
self._test_request_Octavia(403, exceptions.NotAuthorizedException)
|
||||
|
||||
def test_request_Octavia_404(self):
|
||||
self._test_request_Octavia(404, exceptions.NotFoundException)
|
||||
|
||||
def test_request_Octavia_409(self):
|
||||
self._test_request_Octavia(409, exceptions.ConflictException)
|
||||
|
||||
def test_request_Octavia_500(self):
|
||||
self._test_request_Octavia(500, exceptions.UnknownException)
|
||||
|
||||
def test_request_Octavia_503(self):
|
||||
self._test_request_Octavia(503, exceptions.ServiceUnavailableException)
|
||||
|
|
Loading…
Reference in New Issue