Consolidate image_href to image uuid validation code

The server rebuild and rescue APIs were using very similar
helper methods for parsing the image uuid out of the image_href
request parameter and also validating an image uuid was provided.

This moves that into a common utility method so we don't have
the copy/paste everywhere.

Change-Id: I7c38d576bbfc459f40eba75452cdfc97bdd9e724
This commit is contained in:
Matt Riedemann
2016-04-19 15:46:53 -04:00
parent 8a93fd1378
commit 938b71ce32
5 changed files with 48 additions and 56 deletions

View File

@@ -21,6 +21,7 @@ import re
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import strutils
from oslo_utils import uuidutils
import six
import six.moves.urllib.parse as urlparse
import webob
@@ -567,3 +568,41 @@ def is_all_tenants(search_opts):
# The empty string is considered enabling all_tenants
all_tenants = 'all_tenants' in search_opts
return all_tenants
def image_uuid_from_href(image_href, key):
"""If the image href was generated by nova api, strip image_href down to an
id and use the default glance connection params
:param image_href: URL or UUID for an image.
:param key: The request body key for the image_href value. This is used in
error messages.
:returns: The parsed image UUID.
:raises: webob.exc.HTTPBadRequest if the image_href does not have a valid
image UUID in it.
"""
if not image_href:
# NOTE(mriedem): This error message is copied from how our jsonschema
# validation error looks.
msg = _("Invalid input for field/attribute %(path)s. "
"Value: %(value)s. %(message)s") % {
'path': key, 'value': image_href,
'message': (
'Invalid image reference format. Specify the image '
'reference by UUID or full URL.')
}
raise exc.HTTPBadRequest(explanation=msg)
image_uuid = image_href.split('/').pop()
if not uuidutils.is_uuid_like(image_uuid):
msg = _("Invalid input for field/attribute %(path)s. "
"Value: %(value)s. %(message)s") % {
'path': key, 'value': image_href,
'message': (
'Invalid image reference format. Specify the image '
'reference by UUID or full URL.')
}
raise exc.HTTPBadRequest(explanation=msg)
return image_uuid

View File

@@ -14,7 +14,6 @@
"""The rescue mode extension."""
from oslo_utils import uuidutils
import webob
from webob import exc
@@ -23,7 +22,6 @@ 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
@@ -36,15 +34,6 @@ 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."""
@@ -61,8 +50,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 = self._rescue_image_validation(
body['rescue']['rescue_image_ref'])
rescue_image_ref = common.image_uuid_from_href(
body['rescue']['rescue_image_ref'], 'rescue_image_ref')
self.compute_api.rescue(context, instance,
rescue_password=password, rescue_image_ref=rescue_image_ref)
except exception.InstanceIsLocked as e:

View File

@@ -864,21 +864,6 @@ class Controller(wsgi.Controller):
msg = _("Missing imageRef attribute")
raise exc.HTTPBadRequest(explanation=msg)
def _image_uuid_from_href(self, image_href):
if not image_href:
msg = _("Invalid imageRef provided.")
raise exc.HTTPBadRequest(explanation=msg)
# If the image href was generated by nova api, strip image_href
# down to an id and use the default glance connection params
image_uuid = image_href.split('/').pop()
if not uuidutils.is_uuid_like(image_uuid):
msg = _("Invalid imageRef provided.")
raise exc.HTTPBadRequest(explanation=msg)
return image_uuid
def _image_from_req_data(self, data):
"""Get image data from the request or raise appropriate
exceptions
@@ -897,7 +882,7 @@ class Controller(wsgi.Controller):
return ''
else:
image_href = self._image_ref_from_req_data(data)
image_uuid = self._image_uuid_from_href(image_href)
image_uuid = common.image_uuid_from_href(image_href, 'imageRef')
return image_uuid
def _flavor_id_from_req_data(self, data):
@@ -975,7 +960,7 @@ class Controller(wsgi.Controller):
msg = _("Could not parse imageRef from request.")
raise exc.HTTPBadRequest(explanation=msg)
image_href = self._image_uuid_from_href(image_href)
image_href = common.image_uuid_from_href(image_href, 'imageRef')
password = self._get_server_admin_password(body)

View File

@@ -15,7 +15,6 @@
"""The rescue mode extension."""
from oslo_config import cfg
from oslo_utils import uuidutils
from webob import exc
from nova.api.openstack import common
@@ -25,7 +24,6 @@ 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
@@ -42,15 +40,6 @@ 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.
@@ -70,8 +59,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 = self._rescue_image_validation(
body['rescue']['rescue_image_ref'])
rescue_image_ref = common.image_uuid_from_href(
body['rescue']['rescue_image_ref'], 'rescue_image_ref')
try:
self.compute_api.rescue(context, instance,

View File

@@ -952,17 +952,6 @@ class ServersController(wsgi.Controller):
common.raise_http_conflict_for_instance_invalid_state(state_error,
'delete', id)
def _image_uuid_from_href(self, image_href):
# If the image href was generated by nova api, strip image_href
# down to an id and use the default glance connection params
image_uuid = image_href.split('/').pop()
if not uuidutils.is_uuid_like(image_uuid):
msg = _("Invalid imageRef provided.")
raise exc.HTTPBadRequest(explanation=msg)
return image_uuid
def _image_from_req_data(self, server_dict, create_kwargs):
"""Get image data from the request or raise appropriate
exceptions.
@@ -975,7 +964,8 @@ class ServersController(wsgi.Controller):
if not image_href and create_kwargs.get('block_device_mapping'):
return ''
elif image_href:
return self._image_uuid_from_href(six.text_type(image_href))
return common.image_uuid_from_href(six.text_type(image_href),
'imageRef')
else:
msg = _("Missing imageRef attribute")
raise exc.HTTPBadRequest(explanation=msg)
@@ -1012,7 +1002,7 @@ class ServersController(wsgi.Controller):
rebuild_dict = body['rebuild']
image_href = rebuild_dict["imageRef"]
image_href = self._image_uuid_from_href(image_href)
image_href = common.image_uuid_from_href(image_href, 'imageRef')
password = self._get_server_admin_password(rebuild_dict)