Rescue API handle NotImplementedError

There are several nova virt drivers that don't implement the rescue API,
but the os compute API doesn't handle NotImplementedError,
it returns a 400 instead of a 501.

The patch add the proper logic to return a 501 instead.

Change-Id: Ia649c4dadd50985efed631ce8f3e4b212646766e
Closes-Bug: #1287367
This commit is contained in:
Leandro I. Costantino 2014-03-03 21:09:52 -03:00
parent 80e8555e10
commit f3f46b532c
4 changed files with 84 additions and 2 deletions

View File

@ -67,6 +67,10 @@ class RescueController(wsgi.Controller):
except exception.InstanceNotRescuable as non_rescuable:
raise exc.HTTPBadRequest(
explanation=non_rescuable.format_message())
except NotImplementedError:
msg = _("The rescue operation is not implemented by this "
"cloud.")
raise exc.HTTPNotImplemented(explanation=msg)
return {'adminPass': password}
@ -81,6 +85,10 @@ class RescueController(wsgi.Controller):
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'unrescue')
except NotImplementedError:
msg = _("The unrescue operation is not implemented by this cloud.")
raise exc.HTTPNotImplemented(explanation=msg)
return webob.Response(status_int=202)

View File

@ -25,6 +25,7 @@ from nova.api.openstack import wsgi
from nova.api import validation
from nova import compute
from nova import exception
from nova.openstack.common.gettextutils import _
from nova import utils
@ -42,7 +43,7 @@ class RescueController(wsgi.Controller):
self.compute_api = compute.API()
@wsgi.response(202)
@extensions.expected_errors((400, 404, 409))
@extensions.expected_errors((400, 404, 409, 501))
@wsgi.action('rescue')
@validation.schema(rescue.rescue)
def _rescue(self, req, id, body):
@ -68,13 +69,16 @@ class RescueController(wsgi.Controller):
except exception.InstanceNotRescuable as non_rescuable:
raise exc.HTTPBadRequest(
explanation=non_rescuable.format_message())
except NotImplementedError:
msg = _("The rescue operation is not implemented by this cloud.")
raise exc.HTTPNotImplemented(explanation=msg)
if CONF.enable_instance_password:
return {'admin_password': password}
else:
return {}
@extensions.expected_errors((404, 409))
@extensions.expected_errors((404, 409, 501))
@wsgi.action('unrescue')
def _unrescue(self, req, id, body):
"""Unrescue an instance."""
@ -87,6 +91,10 @@ class RescueController(wsgi.Controller):
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'unrescue')
except NotImplementedError:
msg = _("The unrescue operation is not implemented by this cloud.")
raise exc.HTTPNotImplemented(explanation=msg)
return webob.Response(status_int=202)

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo.config import cfg
import webob
@ -128,3 +129,35 @@ class RescueTest(test.NoDBTestCase):
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 400)
@mock.patch('nova.compute.api.API.rescue')
def test_rescue_raises_not_implemented(self, rescue_mock):
body = dict(rescue=None)
def fake_rescue(*args, **kwargs):
raise NotImplementedError('not implemented')
rescue_mock.side_effect = fake_rescue
req = webob.Request.blank('/v2/fake/servers/test_inst/action')
req.method = "POST"
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 501)
@mock.patch('nova.compute.api.API.unrescue')
def test_unrescue_raises_not_implemented(self, unrescue_mock):
body = dict(unrescue=None)
def fake_unrescue(*args, **kwargs):
raise NotImplementedError('not implemented')
unrescue_mock.side_effect = fake_unrescue
req = webob.Request.blank('/v2/fake/servers/test_inst/action')
req.method = "POST"
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 501)

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo.config import cfg
import webob
@ -168,3 +169,35 @@ class RescueTest(test.NoDBTestCase):
resp = req.get_response(self.app)
self.assertEqual(400, resp.status_int)
@mock.patch('nova.compute.api.API.rescue')
def test_rescue_raises_not_implemented(self, rescue_mock):
body = dict(rescue=None)
def fake_rescue(*args, **kwargs):
raise NotImplementedError('fake message')
rescue_mock.side_effect = fake_rescue
req = webob.Request.blank('/v3/servers/test_inst/action')
req.method = "POST"
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 501)
@mock.patch('nova.compute.api.API.unrescue')
def test_unrescue_raises_not_implemented(self, unrescue_mock):
body = dict(unrescue=None)
def fake_unrescue(*args, **kwargs):
raise NotImplementedError('fake message')
unrescue_mock.side_effect = fake_unrescue
req = webob.Request.blank('/v3/servers/test_inst/action')
req.method = "POST"
req.body = jsonutils.dumps(body)
req.headers["content-type"] = "application/json"
resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 501)