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) scheme = image_meta.get("store") if scheme and scheme not in store.get_known_schemes(): msg = "Required store %s is invalid" % scheme 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: backend = store.get_store_from_location(location) except store.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, backend) # 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: %s") % utils.exception_to_str(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")
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 store.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 validate_external_location(uri): """ Validate if URI of external location are supported. Only over non-local store types are OK, i.e. S3, Swift, HTTP. Note the absence of 'file://' for security reasons, see LP bug #942118, 1400966, 'swift+config://' is also absent for security reasons, see LP bug #1334196. :param uri: The URI of external image location. :return: Whether given URI of external image location are OK. """ # TODO(zhiyan): This function could be moved to glance_store. # TODO(gm): Use a whitelist of allowed schemes scheme = urlparse.urlparse(uri).scheme return scheme in store_api.get_known_schemes() and scheme not in RESTRICTED_URI_SCHEMAS
def validate_external_location(uri): """ Validate if URI of external location are supported. Only over non-local store types are OK, i.e. S3, Swift, HTTP. Note the absence of 'file://' for security reasons, see LP bug #942118, 1400966, 'swift+config://' is also absent for security reasons, see LP bug #1334196. :param uri: The URI of external image location. :return: Whether given URI of external image location are OK. """ # TODO(zhiyan): This function could be moved to glance_store. # TODO(gm): Use a whitelist of allowed schemes scheme = urlparse.urlparse(uri).scheme return (scheme in store_api.get_known_schemes() and scheme not in RESTRICTED_URI_SCHEMAS)
def validate_external_location(uri): """ Validate if URI of external location are supported. Only over non-local store types are OK, i.e. S3, Swift, HTTP. Note the absence of 'file://' for security reasons, see LP bug #942118, 1400966, 'swift+config://' is also absent for security reasons, see LP bug #1334196. :param uri: The URI of external image location. :return: Whether given URI of external image location are OK. """ # TODO(zhiyan): This function could be moved to glance_store. pieces = urlparse.urlparse(uri) valid_schemes = [scheme for scheme in store_api.get_known_schemes() if scheme != 'file' and scheme != 'swift+config'] return pieces.scheme in valid_schemes
def validate_external_location(uri): """ Validate if URI of external location are supported. Only over non-local store types are OK, i.e. S3, Swift, HTTP. Note the absence of 'file://' for security reasons, see LP bug #942118, 1400966, 'swift+config://' is also absent for security reasons, see LP bug #1334196. :param uri: The URI of external image location. :return: Whether given URI of external image location are OK. """ # TODO(zhiyan): This function could be moved to glance_store. pieces = urlparse.urlparse(uri) valid_schemes = [ scheme for scheme in store_api.get_known_schemes() if scheme != 'file' and scheme != 'swift+config' ] return pieces.scheme in valid_schemes