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

View File

@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock
from oslo.config import cfg from oslo.config import cfg
import webob import webob
@@ -128,3 +129,35 @@ class RescueTest(test.NoDBTestCase):
resp = req.get_response(self.app) resp = req.get_response(self.app)
self.assertEqual(resp.status_int, 400) 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 # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock
from oslo.config import cfg from oslo.config import cfg
import webob import webob
@@ -168,3 +169,35 @@ class RescueTest(test.NoDBTestCase):
resp = req.get_response(self.app) resp = req.get_response(self.app)
self.assertEqual(400, resp.status_int) 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)