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:
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user