예제 #1
0
 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")
예제 #2
0
    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")