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:
@@ -21,6 +21,7 @@ import re
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
import six.moves.urllib.parse as urlparse
|
import six.moves.urllib.parse as urlparse
|
||||||
import webob
|
import webob
|
||||||
@@ -567,3 +568,41 @@ def is_all_tenants(search_opts):
|
|||||||
# The empty string is considered enabling all_tenants
|
# The empty string is considered enabling all_tenants
|
||||||
all_tenants = 'all_tenants' in search_opts
|
all_tenants = 'all_tenants' in search_opts
|
||||||
return all_tenants
|
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
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
"""The rescue mode extension."""
|
"""The rescue mode extension."""
|
||||||
|
|
||||||
from oslo_utils import uuidutils
|
|
||||||
import webob
|
import webob
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
@@ -23,7 +22,6 @@ from nova.api.openstack import extensions as exts
|
|||||||
from nova.api.openstack import wsgi
|
from nova.api.openstack import wsgi
|
||||||
from nova import compute
|
from nova import compute
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova.i18n import _
|
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
|
|
||||||
@@ -36,15 +34,6 @@ class RescueController(wsgi.Controller):
|
|||||||
self.compute_api = compute.API()
|
self.compute_api = compute.API()
|
||||||
self.ext_mgr = ext_mgr
|
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')
|
@wsgi.action('rescue')
|
||||||
def _rescue(self, req, id, body):
|
def _rescue(self, req, id, body):
|
||||||
"""Rescue an instance."""
|
"""Rescue an instance."""
|
||||||
@@ -61,8 +50,8 @@ class RescueController(wsgi.Controller):
|
|||||||
rescue_image_ref = None
|
rescue_image_ref = None
|
||||||
if self.ext_mgr.is_loaded("os-extended-rescue-with-image"):
|
if self.ext_mgr.is_loaded("os-extended-rescue-with-image"):
|
||||||
if body['rescue'] and 'rescue_image_ref' in body['rescue']:
|
if body['rescue'] and 'rescue_image_ref' in body['rescue']:
|
||||||
rescue_image_ref = self._rescue_image_validation(
|
rescue_image_ref = common.image_uuid_from_href(
|
||||||
body['rescue']['rescue_image_ref'])
|
body['rescue']['rescue_image_ref'], 'rescue_image_ref')
|
||||||
self.compute_api.rescue(context, instance,
|
self.compute_api.rescue(context, instance,
|
||||||
rescue_password=password, rescue_image_ref=rescue_image_ref)
|
rescue_password=password, rescue_image_ref=rescue_image_ref)
|
||||||
except exception.InstanceIsLocked as e:
|
except exception.InstanceIsLocked as e:
|
||||||
|
|||||||
@@ -864,21 +864,6 @@ class Controller(wsgi.Controller):
|
|||||||
msg = _("Missing imageRef attribute")
|
msg = _("Missing imageRef attribute")
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
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):
|
def _image_from_req_data(self, data):
|
||||||
"""Get image data from the request or raise appropriate
|
"""Get image data from the request or raise appropriate
|
||||||
exceptions
|
exceptions
|
||||||
@@ -897,7 +882,7 @@ class Controller(wsgi.Controller):
|
|||||||
return ''
|
return ''
|
||||||
else:
|
else:
|
||||||
image_href = self._image_ref_from_req_data(data)
|
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
|
return image_uuid
|
||||||
|
|
||||||
def _flavor_id_from_req_data(self, data):
|
def _flavor_id_from_req_data(self, data):
|
||||||
@@ -975,7 +960,7 @@ class Controller(wsgi.Controller):
|
|||||||
msg = _("Could not parse imageRef from request.")
|
msg = _("Could not parse imageRef from request.")
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
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)
|
password = self._get_server_admin_password(body)
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
"""The rescue mode extension."""
|
"""The rescue mode extension."""
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from nova.api.openstack import common
|
from nova.api.openstack import common
|
||||||
@@ -25,7 +24,6 @@ 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.i18n import _
|
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
|
|
||||||
@@ -42,15 +40,6 @@ class RescueController(wsgi.Controller):
|
|||||||
super(RescueController, self).__init__(*args, **kwargs)
|
super(RescueController, self).__init__(*args, **kwargs)
|
||||||
self.compute_api = compute.API(skip_policy_check=True)
|
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
|
# TODO(cyeoh): Should be responding here with 202 Accept
|
||||||
# because rescue is an async call, but keep to 200
|
# because rescue is an async call, but keep to 200
|
||||||
# for backwards compatibility reasons.
|
# for backwards compatibility reasons.
|
||||||
@@ -70,8 +59,8 @@ class RescueController(wsgi.Controller):
|
|||||||
instance = common.get_instance(self.compute_api, context, id)
|
instance = common.get_instance(self.compute_api, context, id)
|
||||||
rescue_image_ref = None
|
rescue_image_ref = None
|
||||||
if body['rescue'] and 'rescue_image_ref' in body['rescue']:
|
if body['rescue'] and 'rescue_image_ref' in body['rescue']:
|
||||||
rescue_image_ref = self._rescue_image_validation(
|
rescue_image_ref = common.image_uuid_from_href(
|
||||||
body['rescue']['rescue_image_ref'])
|
body['rescue']['rescue_image_ref'], 'rescue_image_ref')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.compute_api.rescue(context, instance,
|
self.compute_api.rescue(context, instance,
|
||||||
|
|||||||
@@ -952,17 +952,6 @@ class ServersController(wsgi.Controller):
|
|||||||
common.raise_http_conflict_for_instance_invalid_state(state_error,
|
common.raise_http_conflict_for_instance_invalid_state(state_error,
|
||||||
'delete', id)
|
'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):
|
def _image_from_req_data(self, server_dict, create_kwargs):
|
||||||
"""Get image data from the request or raise appropriate
|
"""Get image data from the request or raise appropriate
|
||||||
exceptions.
|
exceptions.
|
||||||
@@ -975,7 +964,8 @@ class ServersController(wsgi.Controller):
|
|||||||
if not image_href and create_kwargs.get('block_device_mapping'):
|
if not image_href and create_kwargs.get('block_device_mapping'):
|
||||||
return ''
|
return ''
|
||||||
elif image_href:
|
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:
|
else:
|
||||||
msg = _("Missing imageRef attribute")
|
msg = _("Missing imageRef attribute")
|
||||||
raise exc.HTTPBadRequest(explanation=msg)
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
@@ -1012,7 +1002,7 @@ class ServersController(wsgi.Controller):
|
|||||||
rebuild_dict = body['rebuild']
|
rebuild_dict = body['rebuild']
|
||||||
|
|
||||||
image_href = rebuild_dict["imageRef"]
|
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)
|
password = self._get_server_admin_password(rebuild_dict)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user