diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-06-09 05:50:54 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-06-09 05:50:55 +0000 |
commit | 73820214bf06a30821879dc12e43dbc47a80e86e (patch) | |
tree | 7d1e20d6dfaa0a5bf55c85f6fbffaf4b652a5fe3 | |
parent | 7671050d62589d95fbd833fda83babdf50e04072 (diff) | |
parent | 59716f2347305759025978f6d79cc19f9af7a884 (diff) | |
download | nova-73820214bf06a30821879dc12e43dbc47a80e86e.tar.gz |
Merge "Added validation for rescue image ref" into stable/mitaka
4 files changed, 46 insertions, 7 deletions
diff --git a/nova/api/openstack/compute/legacy_v2/contrib/rescue.py b/nova/api/openstack/compute/legacy_v2/contrib/rescue.py index 1b4e91c0cd..cb5de13515 100644 --- a/nova/api/openstack/compute/legacy_v2/contrib/rescue.py +++ b/nova/api/openstack/compute/legacy_v2/contrib/rescue.py @@ -14,6 +14,7 @@ """The rescue mode extension.""" +from oslo_utils import uuidutils import webob from webob import exc @@ -22,6 +23,7 @@ from nova.api.openstack import extensions as exts from nova.api.openstack import wsgi from nova import compute from nova import exception +from nova.i18n import _ from nova import utils @@ -34,6 +36,15 @@ class RescueController(wsgi.Controller): self.compute_api = compute.API() self.ext_mgr = ext_mgr + def _rescue_image_validation(self, image_ref): + image_uuid = image_ref.split('/').pop() + + if not uuidutils.is_uuid_like(image_uuid): + msg = _("Invalid rescue_image_ref provided.") + raise exc.HTTPBadRequest(explanation=msg) + + return image_uuid + @wsgi.action('rescue') def _rescue(self, req, id, body): """Rescue an instance.""" @@ -50,7 +61,8 @@ class RescueController(wsgi.Controller): rescue_image_ref = None if self.ext_mgr.is_loaded("os-extended-rescue-with-image"): if body['rescue'] and 'rescue_image_ref' in body['rescue']: - rescue_image_ref = body['rescue']['rescue_image_ref'] + rescue_image_ref = self._rescue_image_validation( + body['rescue']['rescue_image_ref']) self.compute_api.rescue(context, instance, rescue_password=password, rescue_image_ref=rescue_image_ref) except exception.InstanceIsLocked as e: diff --git a/nova/api/openstack/compute/rescue.py b/nova/api/openstack/compute/rescue.py index 12990bb9eb..575e6c6c1e 100644 --- a/nova/api/openstack/compute/rescue.py +++ b/nova/api/openstack/compute/rescue.py @@ -15,6 +15,7 @@ """The rescue mode extension.""" from oslo_config import cfg +from oslo_utils import uuidutils from webob import exc from nova.api.openstack import common @@ -24,6 +25,7 @@ from nova.api.openstack import wsgi from nova.api import validation from nova import compute from nova import exception +from nova.i18n import _ from nova import utils @@ -40,6 +42,15 @@ class RescueController(wsgi.Controller): super(RescueController, self).__init__(*args, **kwargs) self.compute_api = compute.API(skip_policy_check=True) + def _rescue_image_validation(self, image_ref): + image_uuid = image_ref.split('/').pop() + + if not uuidutils.is_uuid_like(image_uuid): + msg = _("Invalid rescue_image_ref provided.") + raise exc.HTTPBadRequest(explanation=msg) + + return image_uuid + # TODO(cyeoh): Should be responding here with 202 Accept # because rescue is an async call, but keep to 200 # for backwards compatibility reasons. @@ -59,7 +70,8 @@ class RescueController(wsgi.Controller): instance = common.get_instance(self.compute_api, context, id) rescue_image_ref = None if body['rescue'] and 'rescue_image_ref' in body['rescue']: - rescue_image_ref = body['rescue']['rescue_image_ref'] + rescue_image_ref = self._rescue_image_validation( + body['rescue']['rescue_image_ref']) try: self.compute_api.rescue(context, instance, diff --git a/nova/tests/unit/api/openstack/compute/test_extended_rescue_with_image.py b/nova/tests/unit/api/openstack/compute/test_extended_rescue_with_image.py index f2d8f496db..e86e84abf7 100644 --- a/nova/tests/unit/api/openstack/compute/test_extended_rescue_with_image.py +++ b/nova/tests/unit/api/openstack/compute/test_extended_rescue_with_image.py @@ -54,7 +54,8 @@ class ExtendedRescueWithImageTest(test.NoDBTestCase): rescue_password=mock.ANY, rescue_image_ref=rescue_image_ref) def test_rescue_with_image_specified(self): - body = dict(rescue={"rescue_image_ref": "image-ref"}) + body = dict(rescue={ + "rescue_image_ref": "76fa36fc-c930-4bf3-8c8a-ea2a2420deb6"}) self._make_rescue_request_with_image_ref(body) def test_rescue_without_image_specified(self): diff --git a/nova/tests/unit/api/openstack/compute/test_rescue.py b/nova/tests/unit/api/openstack/compute/test_rescue.py index 3f37f3e8ff..00704e3d70 100644 --- a/nova/tests/unit/api/openstack/compute/test_rescue.py +++ b/nova/tests/unit/api/openstack/compute/test_rescue.py @@ -44,6 +44,10 @@ def fake_compute_get(*args, **kwargs): class RescueTestV21(test.NoDBTestCase): + + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/fake/images/%s' % image_uuid + def setUp(self): super(RescueTestV21, self).setUp() @@ -139,16 +143,26 @@ class RescueTestV21(test.NoDBTestCase): self.fake_req, UUID, body=body) @mock.patch('nova.compute.api.API.rescue') + def test_rescue_with_bad_image_specified(self, mock_compute_api_rescue): + body = {"rescue": {"adminPass": "ABC123", + "rescue_image_ref": "img-id"}} + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller._rescue, + self.fake_req, UUID, body=body) + + @mock.patch('nova.compute.api.API.rescue') def test_rescue_with_image_specified(self, mock_compute_api_rescue): instance = fake_compute_get() body = {"rescue": {"adminPass": "ABC123", - "rescue_image_ref": "img-id"}} + "rescue_image_ref": self.image_href}} resp_json = self.controller._rescue(self.fake_req, UUID, body=body) self.assertEqual("ABC123", resp_json['adminPass']) - mock_compute_api_rescue.assert_called_with(mock.ANY, instance, - rescue_password=u'ABC123', - rescue_image_ref=u'img-id') + mock_compute_api_rescue.assert_called_with( + mock.ANY, + instance, + rescue_password=u'ABC123', + rescue_image_ref=self.image_uuid) @mock.patch('nova.compute.api.API.rescue') def test_rescue_without_image_specified(self, mock_compute_api_rescue): |