Package org.platformlayer.ops.instances

Source Code of org.platformlayer.ops.instances.ImageFactory

package org.platformlayer.ops.instances;

import java.util.Arrays;
import java.util.List;

import javax.inject.Inject;

import org.platformlayer.PlatformLayerClientException;
import org.platformlayer.core.model.ItemBase;
import org.platformlayer.core.model.PlatformLayerKey;
import org.platformlayer.core.model.Tag;
import org.platformlayer.images.model.DiskImage;
import org.platformlayer.images.model.DiskImageRecipe;
import org.platformlayer.ops.CloudContext;
import org.platformlayer.ops.OpsContext;
import org.platformlayer.ops.OpsException;
import org.platformlayer.ops.helpers.ProviderHelper;
import org.platformlayer.ops.images.CloudImage;
import org.platformlayer.ops.images.ImageFormat;
import org.platformlayer.ops.images.ImageStore;
import org.platformlayer.ops.machines.MachineProvider;
import org.platformlayer.ops.machines.PlatformLayerHelpers;
import org.platformlayer.xml.JaxbHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fathomdb.TimeSpan;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;

public class ImageFactory {

  static final Logger log = LoggerFactory.getLogger(ImageFactory.class);

  private static final Tag BOOTSTRAP_IMAGE_TAG = Tag.build("system_id",
      "http://org.platformlayer/service/imagefactory/v1.0:bootstrap");

  // public static final String FORMAT_TAR = "tar";
  // public static final String FORMAT_DISK = "disk";
  // public static final String FORMAT_QCOW2 = "qcow2";

  // public static final Tag TAG_IMAGEFORMAT_TAR = buildImageFormatTag(ImageFormat.Tar);
  // public static final Tag TAG_IMAGEFORMAT_DISK_RAW = buildImageFormatTag(ImageFormat.DiskRaw);
  // public static final Tag TAG_IMAGEFORMAT_DISK_QCOW2 = buildImageFormatTag(ImageFormat.DiskQcow2);

  @Inject
  PlatformLayerHelpers platformLayer;

  @Inject
  OpsContext ops;

  @Inject
  ProviderHelper providers;

  public DiskImageRecipe getOrCreateRecipe(DiskImageRecipe template) throws OpsException {
    DiskImageRecipe best = null;

    // TODO: What should be the parent of a disk image? It's not really owned by anyone...

    // TODO: This needs fixing once we've got the state transitions properly working
    try {
      for (DiskImageRecipe candidate : platformLayer.listItems(DiskImageRecipe.class)) {
        if (isMatch(candidate, template)) {
          best = candidate;
          break;
        }
      }

      if (best == null) {
        best = platformLayer.putItem(template);
      }
    } catch (PlatformLayerClientException e) {
      throw new OpsException("Error fetching or building recipe", e);
    }
    return best;
  }

  public DiskImage getOrCreateImage(DiskImage template) throws OpsException {
    DiskImage best = null;

    try {
      for (DiskImage candidate : platformLayer.listItems(DiskImage.class)) {
        if (isMatch(candidate, template)) {
          best = candidate;
          break;
        }
      }

      if (best == null) {
        // We should be owned by the recipe
        PlatformLayerKey recipeKey = template.getRecipeId();
        if (recipeKey != null) {
          template.getTags().add(Tag.buildParentTag(recipeKey));
        }

        best = platformLayer.putItem(template);
      }
    } catch (PlatformLayerClientException e) {
      throw new OpsException("Error fetching or building image", e);
    }
    return best;
  }

  public CloudImage getOrCreateImageId(MachineProvider targetCloud, List<ImageFormat> formats,
      DiskImageRecipe recipeTemplate) throws OpsException {
    DiskImageRecipe recipeItem = getOrCreateRecipe(recipeTemplate);
    PlatformLayerKey recipeKey = recipeItem.getKey();

    return getOrCreateImageId(targetCloud, formats, recipeKey);
  }

  @Inject
  CloudContext cloud;

  public CloudImage getOrCreateImageId(ItemBase targetCloud, List<ImageFormat> formats, PlatformLayerKey recipeKey)
      throws OpsException {
    MachineProvider machineProvider = providers.toInterface(targetCloud, MachineProvider.class);
    return getOrCreateImageId(machineProvider, formats, recipeKey);
  }

  public CloudImage getOrCreateImageId(MachineProvider targetCloud, List<ImageFormat> formats,
      PlatformLayerKey recipeKey) throws OpsException {
    if (recipeKey == null) {
      log.debug("Looking for bootstrap image");

      for (ImageFormat format : formats) {
        CloudImage bootstrapImage = findBootstrapImage(format, cloud.getImageStore(targetCloud));
        if (bootstrapImage != null) {
          return bootstrapImage;
          // Tags tags = bootstrapImage.getTags();
          // String compression = tags.findUnique("org.openstack.sync__1__expand");
          // return new ImageInfo(bootstrapImage.getId(), format, compression);
        }
      }
      throw new OpsException("Cannot find bootstrap image for format " + Joiner.on(",").join(formats));
    }

    DiskImage imageTemplate = new DiskImage();
    imageTemplate.setFormat(formats.get(0).name());
    imageTemplate.setRecipeId(recipeKey);
    String id = "image-" + recipeKey.getItemId().getKey();
    imageTemplate.setKey(PlatformLayerKey.fromId(id));

    PlatformLayerKey cloudKey = targetCloud.getModel().getKey();
    imageTemplate.setCloud(cloudKey);

    DiskImage image = getOrCreateImage(imageTemplate);
    return getImageInfo(image);
  }

  private CloudImage findBootstrapImage(ImageFormat format, ImageStore imageStore) throws OpsException {
    // Tag formatTag = buildImageFormatTag(format);
    //
    // CloudImage image = imageStore.findImage(Lists.newArrayList(formatTag, BOOTSTRAP_IMAGE_TAG));
    // if (image != null) {
    // return image;
    // }

    Tag osDebian = Tag.build(Tag.IMAGE_OS_DISTRIBUTION, "debian.org");
    Tag osSqueeze = Tag.build(Tag.IMAGE_OS_VERSION, "6.0.4");

    Tag diskFormatTag;
    switch (format) {
    case DiskQcow2:
      diskFormatTag = format.toTag();
      break;
    default:
      log.warn("Unsupported format: " + format);
      return null;
    }

    List<CloudImage> images = imageStore.findImages(Arrays.asList(diskFormatTag, osDebian, osSqueeze));
    for (CloudImage candidate : images) {
      return candidate;
    }

    return null;
  }

  private CloudImage getImageInfo(DiskImage recipe) throws OpsException {
    final String imageId = Tag.IMAGE_ID.findUnique(recipe.getTags());
    if (imageId == null) {
      throw new OpsException("Image is not yet built: " + recipe).setRetry(TimeSpan.ONE_MINUTE);
    }
    final ImageFormat imageFormat = ImageFormat.valueOf(recipe.getFormat());
    String compression = null;
    switch (imageFormat) {
    case Tar:
      compression = "gzip";
      break;
    case DiskRaw:
      compression = "gzip";
      break;
    }
    return new CloudImage() {

      @Override
      public String getId() {
        return imageId;
      }

      @Override
      public ImageFormat getFormat() {
        return imageFormat;
      }

    };
  }

  <T> T cloneThroughJaxb(T a) {
    // TODO: This is probably not the most efficient way to do this!
    try {
      String xml = JaxbHelper.toXml(a, false);
      return (T) JaxbHelper.deserializeXmlObject(xml, a.getClass());
    } catch (Exception e) {
      throw new IllegalStateException("Error while cloning object", e);
    }
  }

  private boolean isMatch(DiskImageRecipe a, DiskImageRecipe b) {
    // TODO: Don't be evil

    DiskImageRecipe aCopy = cloneThroughJaxb(a);
    DiskImageRecipe bCopy = cloneThroughJaxb(b);

    aCopy.setKey(null);
    bCopy.setKey(null);

    aCopy.tags = null;
    bCopy.tags = null;

    aCopy.version = 0;
    bCopy.version = 0;

    aCopy.state = null;
    bCopy.state = null;

    aCopy.secret = null;
    bCopy.secret = null;

    try {
      // TODO: What if e.g. package order is different

      String aXml = JaxbHelper.toXml(aCopy, false);
      String bXml = JaxbHelper.toXml(bCopy, false);
      return Objects.equal(aXml, bXml);
    } catch (Exception e) {
      throw new IllegalArgumentException("Error comparing objects", e);
    }
  }

  private boolean isMatch(DiskImage a, DiskImage b) {
    // TODO: Don't be evil

    DiskImage aCopy = cloneThroughJaxb(a);
    DiskImage bCopy = cloneThroughJaxb(b);

    aCopy.setKey(null);
    bCopy.setKey(null);

    aCopy.tags = null;
    bCopy.tags = null;

    aCopy.version = 0;
    bCopy.version = 0;

    aCopy.state = null;
    bCopy.state = null;

    aCopy.secret = null;
    bCopy.secret = null;

    try {
      // TODO: What if e.g. package order is different

      String aXml = JaxbHelper.toXml(aCopy, false);
      String bXml = JaxbHelper.toXml(bCopy, false);
      return Objects.equal(aXml, bXml);
    } catch (Exception e) {
      throw new IllegalArgumentException("Error comparing objects", e);
    }
  }

}
TOP

Related Classes of org.platformlayer.ops.instances.ImageFactory

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.