Repository: jclouds-labs
Updated Branches:
  refs/heads/master 50744595d -> 76d7aae6e


JCLOUDS-664 Azurecompute-arm ImageExtension


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/76d7aae6
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/76d7aae6
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/76d7aae6

Branch: refs/heads/master
Commit: 76d7aae6e5c625f92c41b6805933087417e671da
Parents: 5074459
Author: Janne Koskinen <[email protected]>
Authored: Thu Jul 7 13:50:59 2016 +0300
Committer: Ignasi Barrera <[email protected]>
Committed: Wed Aug 10 00:07:37 2016 +0200

----------------------------------------------------------------------
 azurecompute-arm/pom.xml                        | 10 +++
 .../arm/compute/AzureComputeServiceAdapter.java | 54 +++++++----
 .../extensions/AzureComputeImageExtension.java  | 51 +++++++----
 .../functions/DeploymentToNodeMetadata.java     |  2 +-
 .../arm/compute/functions/VMImageToImage.java   | 95 ++++++++++++++------
 .../azurecompute/arm/domain/VMImage.java        | 54 ++++++++++-
 .../azurecompute/arm/util/BlobHelper.java       | 91 +++++++++++++++++++
 .../arm/util/DeploymentTemplateBuilder.java     | 15 ++--
 .../AzureComputeImageExtensionLiveTest.java     |  3 +-
 9 files changed, 300 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml
index 5a41e44..0555c31 100644
--- a/azurecompute-arm/pom.xml
+++ b/azurecompute-arm/pom.xml
@@ -114,6 +114,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.jclouds.provider</groupId>
+      <artifactId>azureblob</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <scope>test</scope>
@@ -135,6 +140,11 @@
         </exclusion>
       </exclusions>
     </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-blobstore</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
   </dependencies>
 
   <profiles>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 53e49ee..b21dcfc 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
@@ -18,7 +18,6 @@ package org.jclouds.azurecompute.arm.compute;
 
 import static java.lang.String.format;
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX;
 import static org.jclouds.util.Predicates2.retry;
 import java.util.ArrayList;
 
@@ -45,6 +44,7 @@ import org.jclouds.azurecompute.arm.domain.DeploymentBody;
 import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
+import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.Location;
@@ -56,6 +56,7 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.features.DeploymentApi;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
+import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.Template;
@@ -97,7 +98,6 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<VMDeplo
 
       this.api = api;
       this.azureComputeConstants = azureComputeConstants;
-
       this.azureGroup = azureComputeConstants.azureResourceGroup();
 
       logger.debug("AzureComputeServiceAdapter set azuregroup to: " + 
azureGroup);
@@ -219,7 +219,7 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<VMDeplo
          for (SKU sku : skuList) {
             Iterable<Version> versionList = 
osImageApi.listVersions(publisherName, offer.name(), sku.name());
             for (Version version : versionList) {
-               VMImage vmImage = VMImage.create(publisherName, offer.name(), 
sku.name(), version.name(), location, false);
+               VMImage vmImage = VMImage.create(publisherName, offer.name(), 
sku.name(), version.name(), location);
                osImagesRef.add(vmImage);
             }
          }
@@ -247,6 +247,17 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<VMDeplo
          osImages.addAll(listImagesByLocation(location.name()));
       }
       checkAndSetImageAvailability(osImages, Sets.newHashSet(locationIds));
+
+      // list custom images
+      List<StorageService> storages = 
api.getStorageAccountApi(azureGroup).list();
+      for (StorageService storage : storages) {
+         String name = storage.name();
+         String key = 
api.getStorageAccountApi(azureGroup).getKeys(name).key1();
+            List<VMImage> images = BlobHelper.getImages("jclouds", azureGroup, 
storage.name(), key,
+                  "custom", storage.location());
+            osImages.addAll(images);
+      }
+
       return osImages;
    }
 
@@ -264,24 +275,25 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<VMDeplo
 
    @Override
    public VMImage getImage(final String id) {
-      String[] fields = VMImageToImage.decodeFieldsFromUniqueId(id);
-      if (fields[2].startsWith(CUSTOM_IMAGE_PREFIX)) {
-         String name = fields[2].substring(CUSTOM_IMAGE_PREFIX.length());
-         String sku = fields[3];
-         String version = "1";
-         VMImage ref = VMImage.create(CUSTOM_IMAGE_PREFIX + azureGroup, 
CUSTOM_IMAGE_PREFIX + name, sku, version, fields[0], false);
-         return ref;
+      VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
+      if (image.custom()) {
+         String key = 
api.getStorageAccountApi(azureGroup).getKeys(image.storage()).key1();
+         if (BlobHelper.customImageExists(image.storage(), key))
+            return image;
+         else
+            return null;
+
       }
 
-      String location = fields[0];
-      String publisher = fields[1];
-      String offer = fields[2];
-      String sku = fields[3];
+      String location = image.location();
+      String publisher = image.publisher();
+      String offer = image.offer();
+      String sku = image.sku();
 
       OSImageApi osImageApi = api.getOSImageApi(location);
       List<Version> versions = osImageApi.listVersions(publisher, offer, sku);
       if (!versions.isEmpty()) {
-         return VMImage.create(publisher, offer, sku, versions.get(0).name(), 
location, false);
+         return VMImage.create(publisher, offer, sku, versions.get(0).name(), 
location);
       }
       return null;
    }
@@ -415,8 +427,18 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<VMDeplo
 
       List<VMDeployment> vmDeployments = new ArrayList<VMDeployment>();
       for (Deployment d : deployments){
-         vmDeployments.add(convertDeploymentToVMDeployment(d));
+         // Check that this vm is not generalized and made to custom image
+         try {
+            String storageAccountName = d.name().replaceAll("[^A-Za-z0-9 ]", 
"") + "stor";
+            String key = 
api.getStorageAccountApi(azureGroup).getKeys(storageAccountName).key1();
+            if (!BlobHelper.customImageExists(storageAccountName, key))
+               vmDeployments.add(convertDeploymentToVMDeployment(d));
+         }
+         catch (Exception e) {
+            // This might happen if there is no custom images but vm is 
generalized. No need to list
+         }
       }
+
       return vmDeployments;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index 122a5da..786c17a 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
@@ -17,18 +17,24 @@
 package org.jclouds.azurecompute.arm.compute.extensions;
 
 import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
 import com.google.gson.internal.LinkedTreeMap;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
 import org.jclouds.Constants;
+import org.jclouds.View;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
 import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
+import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
+import static java.lang.String.format;
+import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.domain.CloneImageTemplate;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageTemplate;
@@ -36,27 +42,25 @@ import org.jclouds.compute.domain.ImageTemplateBuilder;
 import org.jclouds.compute.extensions.ImageExtension;
 import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
 
-import static java.lang.String.format;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-
-import com.google.common.util.concurrent.UncheckedTimeoutException;
-
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
 
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+
 
 public class AzureComputeImageExtension implements ImageExtension {
    private final AzureComputeApi api;
+   private final ListeningExecutorService userExecutor;
+   private final Supplier<View> blobstore = null;
+   private final String group;
    private final Predicate<URI> imageAvailablePredicate;
    private final Predicate<String> nodeSuspendedPredicate;
    private final AzureComputeConstants azureComputeConstants;
-   private final ListeningExecutorService userExecutor;
-   private final String group;
    private final VMImageToImage imageReferenceToImage;
-   public static final String CONTAINER_NAME = "vhdsnew";
+   public static final String CONTAINER_NAME = "jclouds";
    public static final String CUSTOM_IMAGE_PREFIX = "#";
 
    @Inject
@@ -69,29 +73,28 @@ public class AzureComputeImageExtension implements 
ImageExtension {
       this.userExecutor = userExecutor;
       this.group = azureComputeConstants.azureResourceGroup();
       this.imageReferenceToImage = imageReferenceToImage;
-      this.api = api;
       this.imageAvailablePredicate = imageAvailablePredicate;
       this.nodeSuspendedPredicate = nodeSuspendedPredicate;
       this.azureComputeConstants = azureComputeConstants;
+      this.api = api;
    }
 
    @Override
    public ImageTemplate buildImageTemplateFromNode(String name, String id) {
-      String imageName = name.toLowerCase();
-      return new 
ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(imageName).build();
+      String nameLowerCase = name.toLowerCase();
+      return new 
ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(nameLowerCase).build();
    }
 
    @Override
    public ListenableFuture<Image> createImage(ImageTemplate template) {
+
+
       final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
       final String id = cloneTemplate.getSourceNodeId();
       final String name = cloneTemplate.getName();
       final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + 
"stor";
 
-      // VM needs to be stopped before it can be generalized
-      String status = "";
       api.getVirtualMachineApi(group).stop(id);
-      //Poll until resource is ready to be used
       if (nodeSuspendedPredicate.apply(id)) {
          return userExecutor.submit(new Callable<Image>() {
             @Override
@@ -118,26 +121,36 @@ public class AzureComputeImageExtension implements 
ImageExtension {
                            disks[1] = datadiskObject.get("name");
 
                            VirtualMachine vm = 
api.getVirtualMachineApi(group).get(id);
-                           String location = vm.location();
-                           final VMImage ref = 
VMImage.create(CUSTOM_IMAGE_PREFIX + group, CUSTOM_IMAGE_PREFIX + name, 
disks[0], disks[1], location, false);
+                           final VMImage ref = VMImage.create(group, 
storageAccountName, disks[0], disks[1], name, "custom", vm.location());
                            return imageReferenceToImage.apply(ref);
                         }
                      }
                   }
                }
                throw new UncheckedTimeoutException("Image was not created 
within the time limit: "
-                       + cloneTemplate.getName());
+                     + cloneTemplate.getName());
             }
          });
       } else {
          final String illegalStateExceptionMessage = format("Node %s was not 
suspended within %sms.",
-                 id, azureComputeConstants.operationTimeout());
+               id, azureComputeConstants.operationTimeout());
          throw new IllegalStateException(illegalStateExceptionMessage);
       }
    }
 
    @Override
    public boolean deleteImage(String id) {
+
+      VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
+      if (image.custom()) {
+         StorageServiceKeys keys = 
api.getStorageAccountApi(image.group()).getKeys(image.storage());
+
+         // This removes now all the images in this storage. At least in 
theory, there should be just one and if there is
+         // more, they should be copies of each other.
+         BlobHelper.deleteContainerIfExists(image.storage(), keys.key1(), 
"system");
+         return !BlobHelper.customImageExists(image.storage(), keys.key1());
+      }
+
       return false;
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
index 8ea8235..532e786 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java
@@ -210,7 +210,7 @@ public class DeploymentToNodeMetadata implements 
Function<VMDeployment, NodeMeta
 
          if (imageReference != null) {
             VMImage vmImage = VMImage.create(imageReference.publisher(), 
imageReference.offer(), imageReference.sku(),
-                    imageReference.version(), locationName, false);
+                    imageReference.version(), locationName);
             Image image = vmImageToImage.apply(vmImage);
             builder.imageId(image.getId());
          }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
index db2ab9c..f784842 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java
@@ -17,7 +17,6 @@
 package org.jclouds.azurecompute.arm.compute.functions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX;
 import static 
org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
 import static 
org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
 
@@ -67,8 +66,33 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
       return (imageReference.globallyAvailable() ? "global" : 
imageReference.location()) + "/" + imageReference.publisher() + "/" + 
imageReference.offer() + "/" + imageReference.sku();
    }
 
-   public static String[] decodeFieldsFromUniqueId(final String id) {
-      return checkNotNull(id, "id").split("/");
+   public static String encodeFieldsToUniqueIdCustom(VMImage imageReference){
+      return (imageReference.globallyAvailable() ? "global" : 
imageReference.location()) + "/" + imageReference.group() + "/" + 
imageReference.storage() + "/" + imageReference.vhd1() + "/" + 
imageReference.offer();
+   }
+
+   public static VMImage decodeFieldsFromUniqueId(final String id) {
+      String fields[] = checkNotNull(id, "id").split("/");
+      VMImage vmImage;
+      boolean custom = fields.length == 5;
+      if (custom) {
+         /* id fields indexes
+         0: imageReference.location) + "/" +
+         1: imageReference.group + "/" +
+         2: imageReference.storage + "/" +
+         3: imageReference.vhd1 + "/" +
+         4: imageReference.offer
+         */
+         vmImage = VMImage.create(fields[1], fields[2], fields[3], null, null, 
fields[4], fields[0]);
+      } else {
+         /* id fields indexes
+         0: imageReference.location) + "/" +
+         1: imageReference.publisher + "/" +
+         2: imageReference.offer + "/" +
+         3: imageReference.sku + "/" +
+         */
+         vmImage = VMImage.create(fields[1], fields[2], fields[3], null, 
fields[0]);
+      }
+      return vmImage;
    }
 
    @Inject
@@ -80,26 +104,41 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
    public Image apply(final VMImage image) {
 
       Credentials credentials = new Credentials(AZURE_LOGIN_USERNAME, 
AZURE_LOGIN_PASSWORD);
-      String name = "";
-      if (image.offer().startsWith(CUSTOM_IMAGE_PREFIX)) {
-         name = image.offer().substring(CUSTOM_IMAGE_PREFIX.length());
-      } else {
-            name = image.offer();
+      if (image.custom()) {
+
+         final ImageBuilder builder = new ImageBuilder()
+               .location(FluentIterable.from(locations.get())
+                     .firstMatch(LocationPredicates.idEquals(image.location()))
+                     .get())
+               .name(image.name())
+               .description("#" + image.group())
+               .status(Image.Status.AVAILABLE)
+               .version(image.storage())
+               .providerId(image.vhd1())
+               .id(encodeFieldsToUniqueIdCustom(image))
+               
.defaultCredentials(LoginCredentials.fromCredentials(credentials));
+
+         final OperatingSystem.Builder osBuilder = osFamily().apply(image);
+         Image retimage = builder.operatingSystem(osBuilder.build()).build();
+         return retimage;
+
+      }
+      else {
+         final ImageBuilder builder = new ImageBuilder()
+               .name(image.offer())
+               .description(image.sku())
+               .status(Image.Status.AVAILABLE)
+               .version(image.sku())
+               .id(encodeFieldsToUniqueId(image))
+               
.defaultCredentials(LoginCredentials.fromCredentials(credentials))
+               .providerId(image.publisher())
+               .location(image.globallyAvailable() ? null : 
FluentIterable.from(locations.get())
+                     .firstMatch(LocationPredicates.idEquals(image.location()))
+                     .get());
+
+         final OperatingSystem.Builder osBuilder = osFamily().apply(image);
+         return builder.operatingSystem(osBuilder.build()).build();
       }
-      final ImageBuilder builder = new ImageBuilder()
-              .name(name)
-              .description(image.sku())
-              .status(Image.Status.AVAILABLE)
-              .version(image.sku())
-              .id(encodeFieldsToUniqueId(image))
-              
.defaultCredentials(LoginCredentials.fromCredentials(credentials))
-              .providerId(image.publisher())
-              .location(image.globallyAvailable() ? null : 
FluentIterable.from(locations.get())
-                      
.firstMatch(LocationPredicates.idEquals(image.location()))
-                      .get());
-
-      final OperatingSystem.Builder osBuilder = osFamily().apply(image);
-      return builder.operatingSystem(osBuilder.build()).build();
    }
 
    public static Function<VMImage, OperatingSystem.Builder> osFamily() {
@@ -124,12 +163,16 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
                family = OsFamily.OEL;
             }
 
+            String sku = image.sku();
+            if (image.custom())
+               sku = image.vhd1();
+
             // only 64bit OS images are supported by Azure ARM
             return OperatingSystem.builder().
-                    family(family).
-                    is64Bit(true).
-                    description(image.sku()).
-                    version(image.sku());
+                  family(family).
+                  is64Bit(true).
+                  description(sku).
+                  version(sku);
          }
       };
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
index 2d4fc91..c83eafe 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java
@@ -17,34 +17,39 @@
 package org.jclouds.azurecompute.arm.domain;
 
 import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 @AutoValue
 public abstract class VMImage {
-
    /**
     * The publisher of the image reference.
     */
+   @Nullable
    public abstract String publisher();
 
    /**
     * The offer of the image reference.
     */
+   @Nullable
    public abstract String offer();
 
    /**
     * The sku of the image reference.
     */
+   @Nullable
    public abstract String sku();
 
    /**
     * The version of the image reference.
     */
+   @Nullable
    public abstract String version();
 
    /**
     * The location from where Image was fetched
     */
+   @Nullable
    public abstract String location();
 
    /**
@@ -52,9 +57,50 @@ public abstract class VMImage {
     */
    public abstract boolean globallyAvailable();
 
-   @SerializedNames({ "publisher", "offer", "sku", "version", "location", 
"globallyAvailable"})
-   public static VMImage create(String publisher, String offer, String sku, 
String version, String location, boolean globallyAvailable) {
+   /**
+    * The group of the custom image
+    */
+   @Nullable
+   public abstract String group();
+
+   /**
+    * The storage of the custom image.
+    */
+   @Nullable
+   public abstract String storage();
+
+   /**
+    * The vhd1 of the custom image
+    */
+   @Nullable
+   public abstract String vhd1();
+
+   /**
+    * The vhd2 of the custom image.
+    */
+   @Nullable
+   public abstract String vhd2();
+
+   /**
+    * The name of the custom image template.
+    */
+   @Nullable
+   public abstract String name();
+
+   /**
+    * True if custom image
+    */
+   public abstract boolean custom();
+
+   @SerializedNames({ "publisher", "offer", "sku", "version", "location"})
+   public static VMImage create(String publisher, String offer, String sku, 
String version, String location) {
+
+      return new AutoValue_VMImage(publisher, offer, sku, version, location, 
false, null, null, null, null, null, false);
+   }
+
+   @SerializedNames({ "group", "storage", "vhd1", "vhd2", "name", "offer", 
"location"})
+   public static VMImage create(String group, String storage, String vhd1, 
String vhd2, String name, String offer, String location) {
 
-      return new AutoValue_VMImage(publisher, offer, sku, version, location, 
globallyAvailable);
+      return new AutoValue_VMImage(null, offer, null, null, location, false, 
group, storage, vhd1, vhd2, name, true);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
new file mode 100644
index 0000000..ee794ec
--- /dev/null
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azurecompute.arm.util;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.azure.storage.domain.BoundedSet;
+import org.jclouds.azureblob.AzureBlobClient;
+import org.jclouds.azureblob.domain.BlobProperties;
+import org.jclouds.azureblob.domain.ContainerProperties;
+import org.jclouds.azureblob.domain.ListBlobsResponse;
+import org.jclouds.azurecompute.arm.domain.VMImage;
+import org.jclouds.util.Closeables2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BlobHelper {
+
+   public static void deleteContainerIfExists(String storage, String key, 
String containerName) {
+      final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
+              .credentials(storage, key)
+              .buildApi(AzureBlobClient.class);
+
+      try {
+         azureBlob.deleteContainer(containerName);
+      }
+      finally {
+         Closeables2.closeQuietly(azureBlob);
+      }
+   }
+
+   public static boolean customImageExists(String storage, String key) {
+      final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
+              .credentials(storage, key)
+              .buildApi(AzureBlobClient.class);
+
+      try {
+         return azureBlob.containerExists("system");
+      }
+      finally {
+         Closeables2.closeQuietly(azureBlob);
+      }
+   }
+
+   public static List<VMImage> getImages(String containerName, String group,
+                                         String storageAccountName, String 
key, String offer, String location) {
+      final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
+              .credentials(storageAccountName, key)
+              .buildApi(AzureBlobClient.class);
+
+
+      List<VMImage> list = new ArrayList<VMImage>();
+      try {
+         BoundedSet<ContainerProperties> containerList = 
azureBlob.listContainers();
+         for (ContainerProperties props : containerList) {
+            if (props.getName().equals("system")) {
+               ListBlobsResponse blobList = azureBlob.listBlobs("system");
+               String osDisk = "";
+               String dataDisk = "";
+
+               for (BlobProperties blob : blobList) {
+                  String name = blob.getName();
+
+                  if (dataDisk.length() == 0) dataDisk = name.substring(1 + 
name.lastIndexOf('/'));
+                  else if (osDisk.length() == 0) osDisk = name.substring(1 + 
name.lastIndexOf('/'));
+               }
+               final VMImage ref = VMImage.create(group, storageAccountName, 
osDisk, dataDisk, "test-create-image", "custom", location);
+               list.add(ref);
+            }
+         }
+      }
+      finally {
+         Closeables2.closeQuietly(azureBlob);
+      }
+      return list;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
index d0750bd..e5b0a43 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/DeploymentTemplateBuilder.java
@@ -182,7 +182,7 @@ public class DeploymentTemplateBuilder {
 
       String imageName = template.getImage().getName();
       if (imageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
-         storageAccountName = 
imageName.substring(CUSTOM_IMAGE_PREFIX.length()); // get group name
+         storageAccountName = template.getImage().getVersion();
       }
 
       if (Strings.isNullOrEmpty(storageAccountName)) {
@@ -414,13 +414,12 @@ public class DeploymentTemplateBuilder {
       boolean usingMarketplaceImage = true;
       String cusotomImageUri = "";
 
-      // TODO: make new fields for group information
-      String publisher = template.getImage().getProviderId();
-      String storageName = template.getImage().getName();
-      String sku = template.getImage().getDescription(); // this is actual VHD
-      if (storageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
-         storageName = storageName.substring(CUSTOM_IMAGE_PREFIX.length()); // 
get group name
-         cusotomImageUri = sku;
+      // Handle custom image case if description starts with 
CUSTOM_IMAGE_PREFIX
+      String vhd1 = template.getImage().getProviderId();
+      String description = template.getImage().getDescription();
+      if (description.substring(0, 
CUSTOM_IMAGE_PREFIX.length()).equals(CUSTOM_IMAGE_PREFIX)) {
+         String storageName = template.getImage().getVersion();
+         cusotomImageUri = vhd1;
          cusotomImageUri = "https://"; + storageName + 
".blob.core.windows.net/system/Microsoft.Compute/Images/" + 
AzureComputeImageExtension.CONTAINER_NAME + "/" + cusotomImageUri;
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/76d7aae6/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
 
b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
index fecd0fd..06f9ab7 100644
--- 
a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
+++ 
b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
@@ -63,7 +63,7 @@ public class AzureComputeImageExtensionLiveTest extends 
BaseImageExtensionLiveTe
       properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
       properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
       properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
-      properties.put(RESOURCE_GROUP_NAME, "a5");
+      properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup");
 
       properties.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000);
       properties.put(ComputeServiceProperties.POLL_MAX_PERIOD, 10000);
@@ -86,4 +86,5 @@ public class AzureComputeImageExtensionLiveTest extends 
BaseImageExtensionLiveTe
       return pm;
    }
 
+
 }

Reply via email to