Nsx manager client: return meaningful errors
Change-Id: I03dc53a8aed95d6e8910027e657529170a29fbf5
This commit is contained in:
parent
86c4ddb502
commit
9de1a96d40
|
@ -123,3 +123,17 @@ class DvsNotFound(n_exc.NotFound):
|
|||
class NoRouterAvailable(n_exc.ResourceExhausted):
|
||||
message = _("Unable to create the router. "
|
||||
"No tenant router is available for allocation.")
|
||||
|
||||
|
||||
class ManagerError(NsxPluginException):
|
||||
message = _("Unexpected error from backend manager (%(manager)s) "
|
||||
"for %(operation)s")
|
||||
|
||||
|
||||
class ResourceNotFound(ManagerError):
|
||||
message = _("Resource could not be found on backend (%(manager)s) for "
|
||||
"%(operation)s")
|
||||
|
||||
|
||||
class StaleRevision(ManagerError):
|
||||
pass
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
import requests
|
||||
|
||||
from neutron.i18n import _LI
|
||||
from vmware_nsx.neutron.plugins.vmware.common import exceptions as nsx_exc
|
||||
from vmware_nsx.neutron.plugins.vmware.common import nsx_constants
|
||||
from vmware_nsx.neutron.plugins.vmware.nsxlib.v3 import client
|
||||
|
||||
|
@ -38,8 +35,7 @@ def create_logical_switch(display_name, transport_zone_id, tags,
|
|||
'display_name': display_name,
|
||||
'tags': tags}
|
||||
|
||||
result = client.create_resource(resource, body)
|
||||
return result.json()
|
||||
return client.create_resource(resource, body)
|
||||
|
||||
|
||||
def delete_logical_switch(lswitch_id):
|
||||
|
@ -66,8 +62,7 @@ def create_logical_port(lswitch_id, vif_uuid, tags,
|
|||
if address_bindings:
|
||||
body['address_bindings'] = address_bindings
|
||||
|
||||
result = client.create_resource(resource, body)
|
||||
return result.json()
|
||||
return client.create_resource(resource, body)
|
||||
|
||||
|
||||
def delete_logical_port(logical_port_id):
|
||||
|
@ -85,18 +80,14 @@ def create_logical_router(display_name, edge_cluster_uuid, tags, tier_0=False):
|
|||
'display_name': display_name,
|
||||
'router_type': router_type,
|
||||
'tags': tags}
|
||||
result = client.create_resource(resource, body)
|
||||
return result.json()
|
||||
return client.create_resource(resource, body)
|
||||
|
||||
|
||||
def delete_logical_router(lrouter_id):
|
||||
resource = 'logical-routers/%s/' % lrouter_id
|
||||
|
||||
# TODO(salv-orlando): Must handle connection exceptions
|
||||
result = client.delete_resource(resource)
|
||||
if result.status_code == requests.codes.not_found:
|
||||
LOG.info(_LI("Logical router %s not found on NSX backend"), lrouter_id)
|
||||
raise nsx_exc.LogicalRouterNotFound(entity_id=lrouter_id)
|
||||
return client.delete_resource(resource)
|
||||
|
||||
|
||||
def create_logical_router_port(logical_router_id,
|
||||
|
|
|
@ -24,6 +24,12 @@ from vmware_nsx.neutron.plugins.vmware.common import exceptions as nsx_exc
|
|||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
NOT_FOUND = 404
|
||||
PRECONDITION_FAILED = 412
|
||||
|
||||
ERRORS = {NOT_FOUND: nsx_exc.ResourceNotFound,
|
||||
PRECONDITION_FAILED: nsx_exc.StaleRevision}
|
||||
|
||||
|
||||
def _get_manager_endpoint():
|
||||
manager = _get_manager_ip()
|
||||
|
@ -38,16 +44,19 @@ def _get_manager_ip():
|
|||
return manager
|
||||
|
||||
|
||||
def _validate_result(result, expected, operation):
|
||||
if result.status_code not in expected:
|
||||
def _validate_result(result_status_code, expected, operation):
|
||||
if result_status_code not in expected:
|
||||
# Do not reveal internal details in the exception message, as it will
|
||||
# be user-visible
|
||||
LOG.warning(_LW("The HTTP request returned error code %(result)d, "
|
||||
"whereas %(expected)s response codes were expected"),
|
||||
{'result': result.status_code,
|
||||
{'result': result_status_code,
|
||||
'expected': '/'.join([str(code) for code in expected])})
|
||||
raise nsx_exc.NsxPluginException(
|
||||
err_msg=_("Unexpected error in backend while %s") % operation)
|
||||
|
||||
manager_ip = _get_manager_ip()
|
||||
|
||||
manager_error = ERRORS.get(result_status_code, nsx_exc.ManagerError)
|
||||
raise manager_error(manager=manager_ip, operation=operation)
|
||||
|
||||
|
||||
def get_resource(resource):
|
||||
|
@ -56,9 +65,9 @@ def get_resource(resource):
|
|||
headers = {'Accept': 'application/json'}
|
||||
result = requests.get(url, auth=auth.HTTPBasicAuth(user, password),
|
||||
verify=False, headers=headers)
|
||||
_validate_result(
|
||||
result, [requests.codes.ok], _("reading resource: %s") % resource)
|
||||
return result
|
||||
_validate_result(result.status_code, [requests.codes.ok],
|
||||
_("reading resource: %s") % resource)
|
||||
return result.json()
|
||||
|
||||
|
||||
def create_resource(resource, data):
|
||||
|
@ -69,9 +78,9 @@ def create_resource(resource, data):
|
|||
result = requests.post(url, auth=auth.HTTPBasicAuth(user, password),
|
||||
verify=False, headers=headers,
|
||||
data=jsonutils.dumps(data))
|
||||
_validate_result(result, [requests.codes.created],
|
||||
_validate_result(result.status_code, [requests.codes.created],
|
||||
_("creating resource at: %s") % resource)
|
||||
return result
|
||||
return result.json()
|
||||
|
||||
|
||||
def update_resource(resource, data):
|
||||
|
@ -82,9 +91,9 @@ def update_resource(resource, data):
|
|||
result = requests.put(url, auth=auth.HTTPBasicAuth(user, password),
|
||||
verify=False, headers=headers,
|
||||
data=jsonutils.dumps(data))
|
||||
_validate_result(result, [requests.codes.ok],
|
||||
_validate_result(result.status_code, [requests.codes.ok],
|
||||
_("updating resource: %s") % resource)
|
||||
return result
|
||||
return result.json()
|
||||
|
||||
|
||||
def delete_resource(resource):
|
||||
|
@ -92,6 +101,6 @@ def delete_resource(resource):
|
|||
url = manager + "/api/v1/%s" % resource
|
||||
result = requests.delete(url, auth=auth.HTTPBasicAuth(user, password),
|
||||
verify=False)
|
||||
_validate_result(result, [requests.codes.ok, requests.codes.not_found],
|
||||
_validate_result(result.status_code, [requests.codes.ok],
|
||||
_("deleting resource: %s") % resource)
|
||||
return result
|
||||
return result.json()
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#
|
||||
|
||||
import mock
|
||||
import requests
|
||||
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -28,54 +27,45 @@ LOG = log.getLogger(__name__)
|
|||
|
||||
class NsxLibPortTestCase(nsxlib_testcase.NsxLibTestCase):
|
||||
|
||||
def _create_mock_object(self, fake_object):
|
||||
"""Construct mock response object"""
|
||||
mock_response = mock.Mock()
|
||||
if fake_object is not None:
|
||||
mock_response.json.return_value = fake_object
|
||||
return mock_response
|
||||
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3.requests.post")
|
||||
def test_create_logical_port(self, mock_post):
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3"
|
||||
".client.create_resource")
|
||||
def test_create_logical_port(self, mock_create_resource):
|
||||
"""
|
||||
Test creating a port returns the correct response and 200 status
|
||||
"""
|
||||
mock_post.return_value = self._create_mock_object(
|
||||
test_constants_v3.FAKE_PORT)
|
||||
mock_post.return_value.status_code = requests.codes.created
|
||||
mock_create_resource.return_value = test_constants_v3.FAKE_PORT
|
||||
|
||||
result = nsxlib.create_logical_port(
|
||||
test_constants_v3.FAKE_PORT['logical_switch_id'],
|
||||
test_constants_v3.FAKE_PORT['attachment']['id'],
|
||||
tags={})
|
||||
test_constants_v3.FAKE_PORT['logical_switch_id'],
|
||||
test_constants_v3.FAKE_PORT['attachment']['id'],
|
||||
tags={})
|
||||
|
||||
self.assertEqual(test_constants_v3.FAKE_PORT, result)
|
||||
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3.requests.post")
|
||||
def test_create_logical_port_admin_down(self, mock_post):
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3"
|
||||
".client.create_resource")
|
||||
def test_create_logical_port_admin_down(self, mock_create_resource):
|
||||
"""
|
||||
Test creating port with admin_state down
|
||||
"""
|
||||
fake_port = test_constants_v3.FAKE_PORT
|
||||
fake_port['admin_state'] = "DOWN"
|
||||
mock_post.return_value = self._create_mock_object(fake_port)
|
||||
mock_post.return_value.status_code = requests.codes.created
|
||||
mock_create_resource.return_value = fake_port
|
||||
|
||||
result = nsxlib.create_logical_port(
|
||||
test_constants_v3.FAKE_PORT['logical_switch_id'],
|
||||
test_constants_v3.FAKE_PORT['attachment']['id'],
|
||||
tags={}, admin_state=False)
|
||||
test_constants_v3.FAKE_PORT['logical_switch_id'],
|
||||
test_constants_v3.FAKE_PORT['attachment']['id'],
|
||||
tags={}, admin_state=False)
|
||||
|
||||
self.assertEqual(fake_port, result)
|
||||
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3.requests.delete")
|
||||
def test_delete_logical_port(self, mock_delete):
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3"
|
||||
".client.delete_resource")
|
||||
def test_delete_logical_port(self, mock_delete_resource):
|
||||
"""
|
||||
Test deleting port
|
||||
"""
|
||||
mock_delete.return_value = self._create_mock_object(None)
|
||||
mock_delete.return_value.status_code = requests.codes.ok
|
||||
mock_delete_resource.return_value = None
|
||||
|
||||
result = nsxlib.delete_logical_port(
|
||||
test_constants_v3.FAKE_PORT['id'])
|
||||
result = nsxlib.delete_logical_port(test_constants_v3.FAKE_PORT['id'])
|
||||
self.assertIsNone(result)
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#
|
||||
|
||||
import mock
|
||||
import requests
|
||||
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -28,22 +27,15 @@ LOG = log.getLogger(__name__)
|
|||
|
||||
class NsxLibSwitchTestCase(nsxlib_testcase.NsxLibTestCase):
|
||||
|
||||
def _create_mock_object(self, fake_object):
|
||||
"""Construct mock response object"""
|
||||
mock_response = mock.Mock()
|
||||
mock_response.json.return_value = fake_object
|
||||
return mock_response
|
||||
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3.requests.post")
|
||||
def test_create_logical_switch(self, mock_post):
|
||||
@mock.patch("vmware_nsx.neutron.plugins.vmware.nsxlib.v3"
|
||||
".client.create_resource")
|
||||
def test_create_logical_switch(self, mock_create_resource):
|
||||
"""
|
||||
Test creating a switch returns the correct response and 200 status
|
||||
"""
|
||||
mock_post.return_value = self._create_mock_object(
|
||||
test_constants_v3.FAKE_SWITCH)
|
||||
mock_post.return_value.status_code = requests.codes.created
|
||||
mock_create_resource.return_value = test_constants_v3.FAKE_SWITCH
|
||||
|
||||
result = nsxlib.create_logical_switch(
|
||||
test_constants_v3.FAKE_NAME,
|
||||
test_constants_v3.FAKE_TZ_UUID, tags={})
|
||||
result = nsxlib.create_logical_switch(test_constants_v3.FAKE_NAME,
|
||||
test_constants_v3.FAKE_TZ_UUID,
|
||||
tags={})
|
||||
self.assertEqual(test_constants_v3.FAKE_SWITCH, result)
|
||||
|
|
Loading…
Reference in New Issue