def _validate_source(source, req): """ External sources (as specified via the location or copy-from headers) are supported only over non-local store types, i.e. S3, Swift, HTTP. Note the absence of file:// for security reasons, see LP bug #942118. If the above constraint is violated, we reject with 400 "Bad Request". """ if source: pieces = urlparse.urlparse(source) schemes = [scheme for scheme in get_known_schemes() if scheme != 'file'] for scheme in schemes: if pieces.scheme == scheme: return source msg = _("External sourcing not supported for store %s") % source LOG.debug(msg) raise HTTPBadRequest(explanation=msg, request=req, content_type="text/plain")
def _reserve(self, req, image_meta): """ Adds the image metadata to the registry and assigns an image identifier if one is not supplied in the request headers. Sets the image's status to `queued`. :param req: The WSGI/Webob Request object :param id: The opaque image identifier :param image_meta: The image metadata :raises HTTPConflict if image already exists :raises HTTPBadRequest if image metadata is not valid """ location = self._external_source(image_meta, req) store = image_meta.get('store') if store and store not in get_known_schemes(): msg = _("Required store %s is invalid") % store LOG.debug(msg) raise HTTPBadRequest(explanation=msg, content_type='text/plain') image_meta['status'] = ('active' if image_meta.get('size') == 0 else 'queued') if location: try: store = get_store_from_location(location) except exception.BadStoreUri: msg = _("Invalid location %s") % location LOG.debug(msg) raise HTTPBadRequest(explanation=msg, request=req, content_type="text/plain") # check the store exists before we hit the registry, but we # don't actually care what it is at this point self.get_store_or_400(req, store) # retrieve the image size from remote store (if not provided) image_meta['size'] = self._get_size(req.context, image_meta, location) else: # Ensure that the size attribute is set to zero for directly # uploadable images (if not provided). The size will be set # to a non-zero value during upload image_meta['size'] = image_meta.get('size', 0) try: image_meta = registry.add_image_metadata(req.context, image_meta) self.notifier.info("image.create", redact_loc(image_meta)) return image_meta except exception.Duplicate: msg = (_("An image with identifier %s already exists") % image_meta['id']) LOG.debug(msg) raise HTTPConflict(explanation=msg, request=req, content_type="text/plain") except exception.Invalid as e: msg = _("Failed to reserve image. Got error: %(e)s") % {'e': e} for line in msg.split('\n'): LOG.debug(line) raise HTTPBadRequest(explanation=msg, request=req, content_type="text/plain") except exception.Forbidden: msg = _("Forbidden to reserve image.") LOG.debug(msg) raise HTTPForbidden(explanation=msg, request=req, content_type="text/plain")