Package io.fathom.cloud.image.api.os.resources

Source Code of io.fathom.cloud.image.api.os.resources.ImagesV1Endpoint

package io.fathom.cloud.image.api.os.resources;

import io.fathom.cloud.Clock;
import io.fathom.cloud.CloudException;
import io.fathom.cloud.blobs.BlobData;
import io.fathom.cloud.image.ImageDataService;
import io.fathom.cloud.image.ImageServiceImpl;
import io.fathom.cloud.image.ImageServiceImpl.ImageImpl;
import io.fathom.cloud.image.api.os.model.ImageListResponse;
import io.fathom.cloud.image.api.os.model.WrappedImage;
import io.fathom.cloud.protobuf.CloudCommons.KeyValueData;
import io.fathom.cloud.protobuf.ImageModel.ImageData;
import io.fathom.cloud.protobuf.ImageModel.ImageLocation;
import io.fathom.cloud.services.ImageService;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fathomdb.utils.Hex;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.persist.Transactional;
import com.google.protobuf.ByteString;

@Path("/openstack/images/v1/images")
@Transactional
public class ImagesV1Endpoint extends ImageResourceBase {
    private static final Logger log = LoggerFactory.getLogger(ImagesV1Endpoint.class);

    @Inject
    ImageServiceImpl imageService;

    @Inject
    ImageDataService imageDataService;

    private ImageData findImage(String id) throws CloudException {
        ImageImpl image = imageService.findImage(getProject(), Long.valueOf(id));
        if (image == null) {
            return null;
        }

        return image.getData();
    }

    // @PUT
    // @Path("{imageId}/file")
    // public Response updateContent(File file) throws CloudException,
    // IOException {
    // ImageData image = findImage();
    // if (image == null) {
    // throw new WebApplicationException(Status.NOT_FOUND);
    // }
    //
    // BlobData data = BlobData.build(file);
    //
    // String stored = imageDataService.storeImageFile(image, data);
    //
    // ImageLocation.Builder b = ImageLocation.newBuilder();
    // b.setStored(stored);
    //
    // imageService.setImageLocation(image.getId(), data.size(),
    // data.getHash(), b.build());
    //
    // return Response.status(Status.NO_CONTENT).build();
    // }
    //
    // private ImageData findImage() throws CloudException {
    // return imageService.findImage(Long.valueOf(imageId));
    // }

    private static final String IMAGE_META_PREFIX = "x-image-meta-";

    @POST
    @Consumes({ "application/octet-stream" })
    public Response createImage(File file) throws CloudException, IOException {
        if (file == null) {
            throw new IllegalArgumentException("No content supplied");
        }

        ImageImpl image;
        {
            Map<String, String> metadata = extractHeaders();
            if (metadata.containsKey("size")) {
                long size = Long.valueOf(metadata.get(ImageService.METADATA_KEY_SIZE));
                if (size != file.length()) {
                    throw new IllegalArgumentException();
                }
            }
            metadata.put("size", "" + Long.valueOf(file.length()));

            image = imageService.createImage(getProject().getId(), metadata);
        }

        {
            BlobData data = BlobData.build(file);
            image = imageService.uploadData(image, data);
        }

        WrappedImage result = new WrappedImage();
        result.image = toModel(image.getData());

        return Response.status(Status.CREATED).entity(result).type(MediaType.APPLICATION_JSON_TYPE).build();
    }

    private Map<String, String> extractHeaders() {
        Map<String, String> metadata = Maps.newHashMap();

        Enumeration<String> headerNames = httpRequest.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();

            // Header names are case-insensitive
            String normalized = headerName.toLowerCase();
            if (normalized.startsWith(IMAGE_META_PREFIX)) {
                String key = headerName.substring(IMAGE_META_PREFIX.length());
                String value = httpRequest.getHeader(headerName);

                metadata.put(key, value);
            }
        }

        return metadata;
    }

    @GET
    @Path("detail")
    @Produces({ JSON })
    public ImageListResponse doImageDetailsGet() throws CloudException {
        ImageListResponse response = new ImageListResponse();

        response.images = Lists.newArrayList();

        ImageFilter filter = new ImageFilter();
        filter.name = httpRequest.getParameter("name");

        for (ImageService.Image data : imageService.listImages(getProject(), filter)) {
            response.images.add(toModel(data));
        }

        return response;
    }

    @DELETE
    @Path("{id}")
    public Response deleteImage(@PathParam("id") String id) throws CloudException, IOException {
        ImageData image = findImage(id);
        if (image == null) {
            throw new WebApplicationException(Status.NOT_FOUND);
        }

        imageService.deleteImage(getProject(), image.getId());

        return Response.status(Status.NO_CONTENT).build();
    }

    @PUT
    @Path("{id}")
    public Response updateImage(@PathParam("id") String id, File content) throws CloudException, IOException {
        if (content != null && content.length() != 0) {
            throw new UnsupportedOperationException();
        }

        ImageData image = findImage(id);
        if (image == null) {
            throw new WebApplicationException(Status.NOT_FOUND);
        }

        // TODO: Some
        // -H 'x-image-meta-protected: True'
        // -H 'x-glance-registry-purge-props: false'

        Map<String, String> metadata = extractHeaders();

        image = imageService.updateImage(getProject(), image.getId(), metadata);

        // ResponseBuilder response = Response.ok();
        // setHttpHeaders(image, response);
        // return response.build();

        WrappedImage result = new WrappedImage();
        result.image = toModel(image);
        return Response.status(Status.CREATED).entity(result).type(MediaType.APPLICATION_JSON_TYPE).build();
    }

    @HEAD
    @Path("{id}")
    public Response getImageInfo(@PathParam("id") String id) throws CloudException, IOException {
        ImageData image = findImage(id);
        if (image == null) {
            throw new WebApplicationException(Status.NOT_FOUND);
        }

        ResponseBuilder response = Response.ok();
        setHttpHeaders(image, response);
        return response.build();
    }

    @GET
    @Path("{id}")
    public Response getImage(@PathParam("id") String id) throws CloudException, IOException {
        ImageData image = findImage(id);
        if (image == null) {
            throw new WebApplicationException(Status.NOT_FOUND);
        }

        ResponseBuilder response;
        ImageLocation imageLocation = image.getLocation();
        if (imageLocation.hasStored()) {
            String cookie = imageLocation.getStored();

            BlobData blob = imageDataService.getImageFile(cookie);

            response = Response.ok().entity(blob.asEntity());

            ByteString md5 = blob.getHash();
            response.header("Content-MD5", Hex.toHex(md5.toByteArray()));
        } else {
            response = Response.status(Status.NO_CONTENT);
        }

        setHttpHeaders(image, response);
        return response.build();
    }

    private void setHttpHeaders(ImageData image, ResponseBuilder response) {
        // TODO: We could fix this up to be less hacky, but this works for now

        response.header("x-image-meta-id", "" + image.getId());
        response.header("x-image-meta-uri", imageService.getUrl(httpRequest, image.getId()));

        if (image.hasName()) {
            response.header("x-image-meta-name", image.getName());
        }

        if (image.hasDiskFormat()) {
            response.header("x-image-meta-disk_format", image.getDiskFormat());
        }

        if (image.hasContainerFormat()) {
            response.header("x-image-meta-container_format", image.getContainerFormat());
        }

        if (image.hasImageSize()) {
            response.header("x-image-meta-size", "" + image.getImageSize());
        }
        if (image.hasImageChecksum()) {
            response.header("x-image-meta-checksum", Hex.toHex(image.getImageChecksum().toByteArray()));
        }

        if (image.hasCreatedAt()) {
            response.header("x-image-meta-created_at", Clock.toDate(image.getCreatedAt()));
        }
        if (image.hasUpdatedAt()) {
            response.header("x-image-meta-updated_at", Clock.toDate(image.getUpdatedAt()));
        }

        if (image.hasDeletedAt()) {
            response.header("x-image-meta-deleted_at", Clock.toDate(image.getDeletedAt()));
        }

        String status = "queued";
        if (image.hasImageState()) {
            status = image.getImageState().toString().toLowerCase();
        }
        response.header("x-image-meta-status", status);

        if (image.hasIsPublic()) {
            response.header("x-image-meta-is_public", Boolean.toString(image.getIsPublic()));
        }

        response.header("x-image-meta-protected", image.getIsProtected());
        response.header("x-image-meta-owner", "" + image.getOwnerProject());

        if (image.hasAttributes()) {
            for (KeyValueData kv : image.getAttributes().getUserAttributesList()) {
                response.header("x-image-meta-property-" + kv.getKey(), kv.getValue());
            }
        }

        // x-image-meta-is-public true

        // x-image-meta-min-ram 256
        // x-image-meta-min-disk 0
        // x-image-meta-owner null
        // x-image-meta-property-distro Ubuntu 10.04 LTS
    }
}
TOP

Related Classes of io.fathom.cloud.image.api.os.resources.ImagesV1Endpoint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.