Refine HTTP error code for os-interface
When attaching interface to an instance, Neutron may return several types of errors. Nova need to translate those errors into appropriate HTTP error codes, so that end user will be able to know the exact failure reason. Propose to change the following mappings: PortNotFound - 400 --> 404 PortInUse - 400 --> 409 NetworkNotFound - 400 --> 404 FixedIpAlreadyInUse - 400 --> 409 In order to keep V2 api backward-compatibility, only propose to adjust the error code of V2.1/V3 api. Change-Id: Icc80c1f847bb9c5737e7282ce8543be52cde8f89 Closes-Bug: 1380901
This commit is contained in:
parent
c54039c507
commit
5b4bd2aa16
|
@ -117,15 +117,16 @@ class InterfaceAttachmentController(object):
|
|||
try:
|
||||
vif = self.compute_api.attach_interface(context,
|
||||
instance, network_id, port_id, req_ip)
|
||||
except (exception.PortNotFound,
|
||||
exception.FixedIpAlreadyInUse,
|
||||
exception.PortInUse,
|
||||
exception.NetworkDuplicated,
|
||||
exception.NetworkAmbiguous,
|
||||
exception.NetworkNotFound) as e:
|
||||
except (exception.NetworkDuplicated,
|
||||
exception.NetworkAmbiguous) as e:
|
||||
raise exc.HTTPBadRequest(explanation=e.format_message())
|
||||
except exception.InstanceIsLocked as e:
|
||||
except (exception.InstanceIsLocked,
|
||||
exception.FixedIpAlreadyInUse,
|
||||
exception.PortInUse) as e:
|
||||
raise exc.HTTPConflict(explanation=e.format_message())
|
||||
except (exception.PortNotFound,
|
||||
exception.NetworkNotFound) as e:
|
||||
raise exc.HTTPNotFound(explanation=e.format_message())
|
||||
except NotImplementedError as e:
|
||||
raise webob.exc.HTTPNotImplemented(explanation=e.format_message())
|
||||
except exception.InterfaceAttachFailed as e:
|
||||
|
|
|
@ -41,6 +41,7 @@ FAKE_UUID2 = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'
|
|||
FAKE_PORT_ID1 = '11111111-1111-1111-1111-111111111111'
|
||||
FAKE_PORT_ID2 = '22222222-2222-2222-2222-222222222222'
|
||||
FAKE_PORT_ID3 = '33333333-3333-3333-3333-333333333333'
|
||||
FAKE_NOT_FOUND_PORT_ID = '00000000-0000-0000-0000-000000000000'
|
||||
|
||||
FAKE_NET_ID1 = '44444444-4444-4444-4444-444444444444'
|
||||
FAKE_NET_ID2 = '55555555-5555-5555-5555-555555555555'
|
||||
|
@ -107,6 +108,8 @@ def fake_attach_interface(self, context, instance, network_id, port_id,
|
|||
raise exception.NetworkNotFound(network_id=network_id)
|
||||
if not port_id:
|
||||
port_id = ports[fake_networks.index(network_id)]['id']
|
||||
if port_id == FAKE_NOT_FOUND_PORT_ID:
|
||||
raise exception.PortNotFound(port_id=port_id)
|
||||
vif = fake_network_cache_model.new_vif()
|
||||
vif['id'] = port_id
|
||||
vif['network']['id'] = network_id
|
||||
|
@ -129,6 +132,8 @@ class InterfaceAttachTestsV21(test.NoDBTestCase):
|
|||
url = '/v3/os-interfaces'
|
||||
controller_cls = attach_interfaces_v3.InterfaceAttachmentController
|
||||
validate_exc = exception.ValidationError
|
||||
in_use_exc = exc.HTTPConflict
|
||||
not_found_exc = exc.HTTPNotFound
|
||||
|
||||
def setUp(self):
|
||||
super(InterfaceAttachTestsV21, self).setUp()
|
||||
|
@ -322,6 +327,18 @@ class InterfaceAttachTestsV21(test.NoDBTestCase):
|
|||
self.attachments.create, req, FAKE_UUID1,
|
||||
body=jsonutils.loads(req.body))
|
||||
|
||||
def _attach_interface_not_found_case(self, body):
|
||||
self.stubs.Set(compute_api.API, 'attach_interface',
|
||||
fake_attach_interface)
|
||||
req = webob.Request.blank(self.url + '/attach')
|
||||
req.method = 'POST'
|
||||
req.body = jsonutils.dumps(body)
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.environ['nova.context'] = self.context
|
||||
self.assertRaises(self.not_found_exc,
|
||||
self.attachments.create, req, FAKE_UUID1,
|
||||
body=jsonutils.loads(req.body))
|
||||
|
||||
def test_attach_interface_with_port_and_network_id(self):
|
||||
body = {
|
||||
'interfaceAttachment': {
|
||||
|
@ -331,13 +348,21 @@ class InterfaceAttachTestsV21(test.NoDBTestCase):
|
|||
}
|
||||
self._attach_interface_bad_request_case(body)
|
||||
|
||||
def test_attach_interface_with_invalid_data(self):
|
||||
def test_attach_interface_with_not_found_network_id(self):
|
||||
body = {
|
||||
'interfaceAttachment': {
|
||||
'net_id': FAKE_BAD_NET_ID
|
||||
}
|
||||
}
|
||||
self._attach_interface_bad_request_case(body)
|
||||
self._attach_interface_not_found_case(body)
|
||||
|
||||
def test_attach_interface_with_not_found_port_id(self):
|
||||
body = {
|
||||
'interfaceAttachment': {
|
||||
'port_id': FAKE_NOT_FOUND_PORT_ID
|
||||
}
|
||||
}
|
||||
self._attach_interface_not_found_case(body)
|
||||
|
||||
def test_attach_interface_with_invalid_state(self):
|
||||
def fake_attach_interface_invalid_state(*args, **kwargs):
|
||||
|
@ -406,7 +431,30 @@ class InterfaceAttachTestsV21(test.NoDBTestCase):
|
|||
req.body = jsonutils.dumps({})
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.environ['nova.context'] = self.context
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.assertRaises(self.in_use_exc,
|
||||
self.attachments.create, req, FAKE_UUID1,
|
||||
body=jsonutils.loads(req.body))
|
||||
attach_mock.assert_called_once_with(self.context, fake_instance, None,
|
||||
None, None)
|
||||
get_mock.assert_called_once_with(self.context, FAKE_UUID1,
|
||||
want_objects=True,
|
||||
expected_attrs=None)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'get')
|
||||
@mock.patch.object(compute_api.API, 'attach_interface')
|
||||
def test_attach_interface_port_in_use(self,
|
||||
attach_mock,
|
||||
get_mock):
|
||||
fake_instance = objects.Instance(uuid=FAKE_UUID1)
|
||||
get_mock.return_value = fake_instance
|
||||
attach_mock.side_effect = exception.PortInUse(
|
||||
port_id=FAKE_PORT_ID1)
|
||||
req = webob.Request.blank(self.url + '/attach')
|
||||
req.method = 'POST'
|
||||
req.body = jsonutils.dumps({})
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.environ['nova.context'] = self.context
|
||||
self.assertRaises(self.in_use_exc,
|
||||
self.attachments.create, req, FAKE_UUID1,
|
||||
body=jsonutils.loads(req.body))
|
||||
attach_mock.assert_called_once_with(self.context, fake_instance, None,
|
||||
|
@ -444,6 +492,8 @@ class InterfaceAttachTestsV2(InterfaceAttachTestsV21):
|
|||
url = '/v2/fake/os-interfaces'
|
||||
controller_cls = attach_interfaces_v2.InterfaceAttachmentController
|
||||
validate_exc = exc.HTTPBadRequest
|
||||
in_use_exc = exc.HTTPBadRequest
|
||||
not_found_exc = exc.HTTPBadRequest
|
||||
|
||||
def test_attach_interface_instance_with_non_uuid_net_id(self):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue