summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-06-09 05:50:54 +0000
committerGerrit Code Review <review@openstack.org>2016-06-09 05:50:55 +0000
commit73820214bf06a30821879dc12e43dbc47a80e86e (patch)
tree7d1e20d6dfaa0a5bf55c85f6fbffaf4b652a5fe3
parent7671050d62589d95fbd833fda83babdf50e04072 (diff)
parent59716f2347305759025978f6d79cc19f9af7a884 (diff)
downloadnova-73820214bf06a30821879dc12e43dbc47a80e86e.tar.gz
Merge "Added validation for rescue image ref" into stable/mitaka
-rw-r--r--nova/api/openstack/compute/legacy_v2/contrib/rescue.py14
-rw-r--r--nova/api/openstack/compute/rescue.py14
-rw-r--r--nova/tests/unit/api/openstack/compute/test_extended_rescue_with_image.py3
-rw-r--r--nova/tests/unit/api/openstack/compute/test_rescue.py22
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):