Update ImageExtension to work with Managed Disks

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

Branch: refs/heads/2.0.x
Commit: ea62a4c39892871fd75663fc9741f16e707655bc
Parents: 64bcdc0
Author: Dani Estevez <[email protected]>
Authored: Fri Mar 17 17:23:49 2017 -0400
Committer: Ignasi Barrera <[email protected]>
Committed: Mon Apr 24 08:19:46 2017 +0200

----------------------------------------------------------------------
 azurecompute-arm/pom.xml                        |  29 +--
 .../azurecompute/arm/AzureComputeApi.java       |   3 +-
 .../arm/AzureComputeProviderMetadata.java       |  39 ++--
 .../arm/compute/AzureComputeServiceAdapter.java | 134 +++++---------
 .../AzureComputeServiceContextModule.java       |  48 ++++-
 .../extensions/AzureComputeImageExtension.java  |  83 ++++-----
 .../compute/functions/CustomImageToVMImage.java |  31 ++++
 .../ResourceDefinitionToCustomImage.java        |  91 ----------
 .../functions/TemplateToAvailabilitySet.java    |   3 +-
 .../arm/compute/functions/VMImageToImage.java   |  32 ++--
 .../functions/VirtualMachineToNodeMetadata.java |  62 ++-----
 .../arm/compute/strategy/CleanupResources.java  |  40 +----
 .../arm/domain/AvailabilitySet.java             |  75 +++++++-
 .../jclouds/azurecompute/arm/domain/Image.java  |  23 ++-
 .../arm/domain/ImageProperties.java             |  17 +-
 .../azurecompute/arm/domain/ImageReference.java |  16 +-
 .../arm/domain/ManagedDiskParameters.java       |  35 +---
 .../jclouds/azurecompute/arm/domain/OSDisk.java |  28 +--
 .../arm/domain/StorageAccountType.java          |  47 +++++
 .../azurecompute/arm/domain/VMImage.java        |  21 ++-
 .../arm/features/AvailabilitySetApi.java        |   9 +-
 .../arm/features/DeploymentApi.java             |   8 +-
 .../azurecompute/arm/features/DiskApi.java      |   4 -
 .../azurecompute/arm/features/ImageApi.java     |   4 -
 .../azurecompute/arm/features/JobApi.java       |   3 +-
 .../arm/features/LoadBalancerApi.java           |   2 -
 .../arm/features/NetworkSecurityGroupApi.java   |   2 -
 .../arm/features/NetworkSecurityRuleApi.java    |   3 +-
 .../arm/features/ResourceGroupApi.java          |   3 -
 .../arm/features/ResourceProviderApi.java       |   1 -
 .../arm/features/StorageAccountApi.java         |   5 -
 .../arm/features/VirtualMachineApi.java         |   4 +-
 .../StorageProfileToStorageAccountName.java     |  38 ----
 .../azurecompute/arm/util/BlobHelper.java       |  83 ---------
 .../jclouds/azurecompute/arm/util/VMImages.java |   2 +-
 .../compute/AzureComputeServiceLiveTest.java    |  16 +-
 .../compute/AzureTemplateBuilderLiveTest.java   |   6 +-
 .../AzureComputeImageExtensionLiveTest.java     |  63 +++++--
 ...reComputeSecurityGroupExtensionLiveTest.java |  15 +-
 .../features/AvailabilitySetApiLiveTest.java    |   9 +-
 .../features/AvailabilitySetApiMockTest.java    |   8 +-
 .../arm/features/DeploymentApiLiveTest.java     |  63 +------
 .../arm/features/DiskApiLiveTest.java           |   8 +-
 .../arm/features/ImageApiLiveTest.java          | 176 +++++++++++++------
 .../arm/features/ImageApiMockTest.java          | 155 ++++++++++++++++
 .../arm/features/LoadBalancerApiLiveTest.java   |   4 +-
 .../arm/features/VirtualMachineApiLiveTest.java | 153 +++++++++-------
 .../arm/features/VirtualMachineApiMockTest.java |   6 +-
 .../arm/internal/AzureLiveTestUtils.java        |  33 ++--
 .../internal/BaseAzureComputeApiLiveTest.java   |  21 +--
 .../resources/virtualmachineimagecreate.json    |  21 +++
 .../test/resources/virtualmachineimageget.json  |  21 +++
 .../test/resources/virtualmachineimagelist.json |  25 +++
 53 files changed, 954 insertions(+), 877 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml
index b8c7eaf..2addd07 100644
--- a/azurecompute-arm/pom.xml
+++ b/azurecompute-arm/pom.xml
@@ -67,7 +67,11 @@
       <groupId>org.apache.jclouds.api</groupId>
       <artifactId>oauth</artifactId>
       <version>${project.version}</version>
-      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-okhttp</artifactId>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.apache.jclouds.api</groupId>
@@ -103,27 +107,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-slf4j</artifactId>
-      <version>${project.parent.version}</version>
-      <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>
     </dependency>
     <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-okhttp</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
       <groupId>com.squareup.okhttp</groupId>
       <artifactId>mockwebserver</artifactId>
       <scope>test</scope>
@@ -135,20 +123,13 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-blobstore</artifactId>
-      <version>${project.parent.version}</version>
-    </dependency>
   </dependencies>
 
   <profiles>
     <profile>
       <id>live</id>
-
       <build>
         <defaultGoal>clean verify</defaultGoal>
-
         <plugins>
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
index 51ed402..7081486 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java
@@ -17,7 +17,6 @@
 package org.jclouds.azurecompute.arm;
 
 import java.io.Closeable;
-
 import javax.ws.rs.PathParam;
 
 import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
@@ -170,7 +169,7 @@ public interface AzureComputeApi extends Closeable {
     */
    @Delegate
    LoadBalancerApi getLoadBalancerApi(@PathParam("resourcegroup") String 
resourcegroup);
-   
+
    /**
     * The AvailabilitySet API includes operations for managing availability 
sets
     * within your subscription.

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index 3bf1ab3..9d3f05d 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
@@ -16,6 +16,23 @@
  */
 package org.jclouds.azurecompute.arm;
 
+import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static 
org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
+import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
 
 import java.net.URI;
 import java.util.Properties;
@@ -44,24 +61,6 @@ import org.jclouds.providers.internal.BaseProviderMetadata;
 
 import com.google.auto.service.AutoService;
 
-import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
-import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static 
org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
-import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
-import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
-
 @AutoService(ProviderMetadata.class)
 public class AzureComputeProviderMetadata extends BaseProviderMetadata {
 
@@ -96,7 +95,7 @@ public class AzureComputeProviderMetadata extends 
BaseProviderMetadata {
       // Default credentials for all images
       properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!");
       properties.put(IMAGE_AUTHENTICATE_SUDO, "true");
-      properties.put(TEMPLATE, 
"imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS");
+      properties.put(TEMPLATE, 
"imageNameMatches=UbuntuServer,osVersionMatches=1[456]\\.[01][04](\\.[0-9])?-LTS");
       // Api versions used in each API
       properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), 
"2016-02-01");
       properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), 
"2015-11-01");
@@ -113,7 +112,7 @@ public class AzureComputeProviderMetadata extends 
BaseProviderMetadata {
       properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), 
"2015-06-15");
       properties.put(API_VERSION_PREFIX + 
VirtualMachineApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + 
LoadBalancerApi.class.getSimpleName(), "2016-03-30");
-      properties.put(API_VERSION_PREFIX + 
AvailabilitySetApi.class.getSimpleName(), "2016-03-30");
+      properties.put(API_VERSION_PREFIX + 
AvailabilitySetApi.class.getSimpleName(), "2016-04-30-preview");
       properties.put(API_VERSION_PREFIX + DiskApi.class.getSimpleName(), 
"2017-03-30");
       properties.put(API_VERSION_PREFIX + ImageApi.class.getSimpleName(), 
"2016-04-30-preview");
       

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/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 e79c50d..8f9b67c 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
@@ -16,6 +16,19 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableList.builder;
+import static com.google.common.collect.ImmutableList.of;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Iterables.transform;
+import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
+import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
+import static 
org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -27,6 +40,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
@@ -52,10 +66,8 @@ import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
 import org.jclouds.azurecompute.arm.domain.SKU;
+import org.jclouds.azurecompute.arm.domain.StorageAccountType;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
-import org.jclouds.azurecompute.arm.domain.StorageService;
-import org.jclouds.azurecompute.arm.domain.StorageService.Status;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMHardware;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VMSize;
@@ -64,7 +76,6 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
 import org.jclouds.azurecompute.arm.features.OSImageApi;
 import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.OsFamily;
@@ -86,23 +97,6 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.ImmutableList.builder;
-import static com.google.common.collect.ImmutableList.of;
-import static com.google.common.collect.Iterables.contains;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
-import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
-import static 
org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation 
and
  * the jclouds {@link org.jclouds.compute.ComputeService}.
@@ -122,17 +116,20 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
    private final Supplier<Set<String>> regionIds;
    private final PublicIpAvailablePredicateFactory publicIpAvailable;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private final CustomImageToVMImage customImagetoVmImage;
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, 
@Named(IMAGE_PUBLISHERS) String imagePublishers,
-                              CleanupResources cleanupResources, @Region 
Supplier<Set<String>> regionIds,
-                              PublicIpAvailablePredicateFactory 
publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap) {
+         CleanupResources cleanupResources, @Region Supplier<Set<String>> 
regionIds,
+         PublicIpAvailablePredicateFactory publicIpAvailable, 
LoadingCache<String, ResourceGroup> resourceGroupMap,
+         CustomImageToVMImage customImagetoVmImage) {
       this.api = api;
       this.imagePublishers = 
Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
       this.cleanupResources = cleanupResources;
       this.regionIds = regionIds;
       this.publicIpAvailable = publicIpAvailable;
       this.resourceGroupMap = resourceGroupMap;
+      this.customImagetoVmImage = customImagetoVmImage;
    }
 
    @Override
@@ -223,50 +220,30 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
       }
       return osImages;
    }
+   
+   private List<VMImage> listCustomImagesByLocation(String location) {
+      ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
+      List<org.jclouds.azurecompute.arm.domain.Image> customImages = 
api.getVirtualMachineImageApi(resourceGroup.name()).list();
+      return Lists.transform(customImages, customImagetoVmImage);
+   }
 
    @Override
    public Iterable<VMImage> listImages() {
-      final List<VMImage> osImages = Lists.newArrayList();
-
-      final List<String> availableLocationNames = 
FluentIterable.from(listLocations())
-          .transform(new Function<Location, String>() {
-             @Override public String apply(Location location) {
-                return location.name();
-             }
-          }).toList();
+      final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder();
+      
+      Iterable<String> availableLocationNames = transform(listLocations(), new 
Function<Location, String>() {
+         @Override
+         public String apply(Location location) {
+            return location.name();
+         }
+      });
 
       for (String locationName : availableLocationNames) {
          osImages.addAll(listImagesByLocation(locationName));
+         osImages.addAll(listCustomImagesByLocation(locationName));
       }
 
-      // list custom images
-      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
-         String azureGroup = resourceGroup.name();
-         List<StorageService> storages = 
api.getStorageAccountApi(azureGroup).list();
-
-         for (StorageService storage : storages) {
-            try {
-               String name = storage.name();
-               StorageService storageService = 
api.getStorageAccountApi(azureGroup).get(name);
-               if (storageService != null
-                       && Status.Succeeded == 
storageService.storageServiceProperties().provisioningState()) {
-                  String key = 
api.getStorageAccountApi(azureGroup).getKeys(name).key1();
-                  BlobHelper blobHelper = new BlobHelper(storage.name(), key);
-                  try {
-                     List<VMImage> images = 
blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
-                             storage.location());
-                     osImages.addAll(images);
-                  } finally {
-                     closeQuietly(blobHelper);
-                  }
-               }
-            } catch (Exception ex) {
-               logger.warn("<< could not get custom images from storage 
account %s: %s", storage, ex.getMessage());
-            }
-         }
-      }
-
-      return osImages;
+      return osImages.build();
    }
 
    @Override
@@ -275,30 +252,8 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
       ResourceGroup resourceGroup = 
resourceGroupMap.getUnchecked(image.location());
 
       if (image.custom()) {
-         VMImage customImage = null;
-         StorageServiceKeys keys = 
api.getStorageAccountApi(resourceGroup.name()).getKeys(image.storage());
-         if (keys == null) {
-            // If the storage account for the image does not exist, it means 
the
-            // image was deleted
-            return null;
-         }
-
-         BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
-         try {
-            if (blobHelper.customImageExists()) {
-               List<VMImage> customImagesInStorage = 
blobHelper.getImages(CONTAINER_NAME, resourceGroup.name(),
-                       CUSTOM_IMAGE_OFFER, image.location());
-               customImage = find(customImagesInStorage, new 
Predicate<VMImage>() {
-                  @Override
-                  public boolean apply(VMImage input) {
-                     return id.equals(encodeFieldsToUniqueIdCustom(input));
-                  }
-               }, null);
-            }
-         } finally {
-            closeQuietly(blobHelper);
-         }
-         return customImage;
+         org.jclouds.azurecompute.arm.domain.Image vmImage = 
api.getVirtualMachineImageApi(resourceGroup.name()).get(image.name());
+         return vmImage == null ? null : customImagetoVmImage.apply(vmImage);
       }
 
       String location = image.location();
@@ -313,6 +268,7 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
          return 
VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(version.name())
                  
.location(location).versionProperties(version.properties()).build();
       }
+      
       return null;
    }
 
@@ -458,13 +414,9 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
    }
 
    private ImageReference createImageReference(Image image) {
-      return isCustom(image.getId()) ? 
ImageReference.builder().id(image.getId()).build() :
-              ImageReference.builder()
-                      .publisher(image.getProviderId())
-                      .offer(image.getName())
-                      .sku(image.getVersion())
-                      .version("latest")
-                      .build();
+      return isCustom(image.getId()) ? 
ImageReference.builder().customImageId(image.getProviderId()).build() : 
ImageReference
+            
.builder().publisher(image.getProviderId()).offer(image.getName()).sku(image.getVersion())
+            .version("latest").build();
    }
 
    private OSDisk createOSDisk(Image image) {
@@ -474,7 +426,7 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
               .osType(osType)
               .caching(DataDisk.CachingTypes.READ_WRITE.toString())
               .createOption(CreationData.CreateOptions.FROM_IMAGE.toString())
-              .managedDiskParameters(ManagedDiskParameters.create(null, 
ManagedDiskParameters.StorageAccountTypes.STANDARD_LRS.toString()))
+              .managedDiskParameters(ManagedDiskParameters.create(null, 
StorageAccountType.STANDARD_LRS.toString()))
               .build();
    }
    

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index 690022b..cf3c90c 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
@@ -40,7 +40,6 @@ import 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeSecurityGroup
 import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
 import 
org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityGroupToSecurityGroup;
 import 
org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityRuleToIpPermission;
-import 
org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
 import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
 import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
 import 
org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata;
@@ -48,6 +47,7 @@ import 
org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded;
 import org.jclouds.azurecompute.arm.compute.loaders.ResourceGroupForLocation;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import 
org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
+import org.jclouds.azurecompute.arm.domain.Image;
 import org.jclouds.azurecompute.arm.domain.Location;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@@ -86,7 +86,6 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Provides;
 import com.google.inject.TypeLiteral;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 public class AzureComputeServiceContextModule extends
       ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, 
Location> {
@@ -115,8 +114,6 @@ public class AzureComputeServiceContextModule extends
       install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, 
VMHardware, VMImage, Location>() {
       });
 
-      install(new 
FactoryModuleBuilder().build(ResourceDefinitionToCustomImage.Factory.class));
-
       bind(TemplateOptions.class).to(AzureTemplateOptions.class);
       
bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
       
bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
@@ -163,9 +160,9 @@ public class AzureComputeServiceContextModule extends
 
    @Provides
    @Named(TIMEOUT_IMAGE_AVAILABLE)
-   protected Predicate<URI> provideImageAvailablePredicate(final 
AzureComputeApi api, final Timeouts timeouts,
+   protected Predicate<URI> provideImageCapturedPredicate(final 
AzureComputeApi api, final Timeouts timeouts,
          final PollPeriod pollPeriod) {
-      return retry(new ImageDonePredicate(api), timeouts.imageAvailable, 
pollPeriod.pollInitialPeriod,
+      return retry(new ImageCapturedPredicate(api), timeouts.imageAvailable, 
pollPeriod.pollInitialPeriod,
             pollPeriod.pollMaxPeriod);
    }
 
@@ -196,6 +193,13 @@ public class AzureComputeServiceContextModule extends
          Predicate<Supplier<Provisionable>> resourceAvailable) {
       return new SecurityGroupAvailablePredicateFactory(api, 
resourceAvailable);
    }
+   
+   @Provides
+   protected ImageAvailablePredicateFactory 
provideImageAvailablePredicate(final AzureComputeApi api,
+         Predicate<Supplier<Provisionable>> resourceAvailable, final Timeouts 
timeouts, final PollPeriod pollPeriod) {
+      return new ImageAvailablePredicateFactory(api, retry(new 
ResourceInStatusPredicate("Succeeded"),
+            timeouts.imageAvailable, pollPeriod.pollInitialPeriod, 
pollPeriod.pollMaxPeriod));
+   }
 
    @Provides
    protected Predicate<Supplier<Provisionable>> 
provideResourceAvailablePredicate(final AzureComputeApi api,
@@ -231,11 +235,11 @@ public class AzureComputeServiceContextModule extends
    }
 
    @VisibleForTesting
-   static class ImageDonePredicate implements Predicate<URI> {
+   static class ImageCapturedPredicate implements Predicate<URI> {
 
       private final AzureComputeApi api;
 
-      public ImageDonePredicate(final AzureComputeApi api) {
+      public ImageCapturedPredicate(final AzureComputeApi api) {
          this.api = checkNotNull(api, "api must not be null");
       }
 
@@ -351,5 +355,33 @@ public class AzureComputeServiceContextModule extends
          };
       }
    }
+   
+   public static class ImageAvailablePredicateFactory {
+      private final AzureComputeApi api;
+      private final Predicate<Supplier<Provisionable>> resourceAvailable;
+      
+      ImageAvailablePredicateFactory(final AzureComputeApi api,
+            Predicate<Supplier<Provisionable>> resourceAvailable) {
+         this.api = checkNotNull(api, "api cannot be null");
+         this.resourceAvailable = resourceAvailable;
+      }
+
+      public Predicate<String> create(final String resourceGroup) {
+         checkNotNull(resourceGroup, "resourceGroup cannot be null");
+         return new Predicate<String>() {
+            @Override
+            public boolean apply(final String name) {
+               checkNotNull(name, "name cannot be null");
+               return resourceAvailable.apply(new Supplier<Provisionable>() {
+                  @Override
+                  public Provisionable get() {
+                     Image img = 
api.getVirtualMachineImageApi(resourceGroup).get(name);
+                     return img == null ? null : img.properties();
+                  }
+               });
+            }
+         };
+      }
+   }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/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 cae2c7e..4bfa449 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
@@ -16,30 +16,29 @@
  */
 package org.jclouds.azurecompute.arm.compute.extensions;
 
+import static com.google.common.base.Functions.compose;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.util.Closeables2.closeQuietly;
 
 import java.net.URI;
-import java.util.List;
 import java.util.concurrent.Callable;
 
 import javax.annotation.Resource;
 
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
 import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
-import 
org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
-import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
+import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
+import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.compute.domain.CloneImageTemplate;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageTemplate;
@@ -48,6 +47,7 @@ import org.jclouds.compute.extensions.ImageExtension;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -56,7 +56,6 @@ import com.google.inject.Inject;
 import com.google.inject.name.Named;
 
 public class AzureComputeImageExtension implements ImageExtension {
-   public static final String CONTAINER_NAME = "jclouds";
    public static final String CUSTOM_IMAGE_OFFER = "custom";
 
    @Resource
@@ -65,26 +64,29 @@ public class AzureComputeImageExtension implements 
ImageExtension {
 
    private final AzureComputeApi api;
    private final ListeningExecutorService userExecutor;
-   private final Predicate<URI> imageAvailablePredicate;
+   private final ImageAvailablePredicateFactory imageAvailablePredicate;
    private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate;
-   private final ResourceDefinitionToCustomImage.Factory 
resourceDefinitionToImage;
-   private final CleanupResources cleanupResources;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private final Function<VMImage, Image> vmImageToImage;
+   private final Predicate<URI> resourceDeleted;
+   private final CustomImageToVMImage customImagetoVmImage;
 
    @Inject
    AzureComputeImageExtension(AzureComputeApi api,
-         @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> 
imageAvailablePredicate,
+         ImageAvailablePredicateFactory imageAvailablePredicate,
          @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory 
nodeSuspendedPredicate,
          @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService 
userExecutor,
-         ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, 
CleanupResources cleanupResources,
-         LoadingCache<String, ResourceGroup> resourceGroupMap) {
+         Function<VMImage, Image> vmImageToImage, LoadingCache<String, 
ResourceGroup> resourceGroupMap,
+         @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
+         CustomImageToVMImage customImagetoVmImage) {
       this.api = api;
       this.imageAvailablePredicate = imageAvailablePredicate;
       this.nodeSuspendedPredicate = nodeSuspendedPredicate;
       this.userExecutor = userExecutor;
-      this.resourceDefinitionToImage = resourceDefinitionToImage;
-      this.cleanupResources = cleanupResources;
+      this.vmImageToImage = vmImageToImage;
       this.resourceGroupMap = resourceGroupMap;
+      this.resourceDeleted = resourceDeleted;
+      this.customImagetoVmImage = customImagetoVmImage;
    }
 
    @Override
@@ -95,11 +97,13 @@ public class AzureComputeImageExtension implements 
ImageExtension {
    @Override
    public ListenableFuture<Image> createImage(ImageTemplate template) {
       final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
-
       final RegionAndId regionAndId = 
RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId());
       ResourceGroup resourceGroup = 
resourceGroupMap.getUnchecked(regionAndId.region());
       final String resourceGroupName = resourceGroup.name();
 
+      final VirtualMachine vm = 
api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
+      final IdReference vmIdRef = IdReference.create(vm.id());
+
       logger.debug(">> stopping node %s...", regionAndId.slashEncode());
       api.getVirtualMachineApi(resourceGroupName).stop(regionAndId.id());
       
checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(regionAndId.id()),
@@ -109,23 +113,17 @@ public class AzureComputeImageExtension implements 
ImageExtension {
          @Override
          public Image call() throws Exception {
             logger.debug(">> generalizing virtal machine %s...", 
regionAndId.id());
+
             
api.getVirtualMachineApi(resourceGroupName).generalize(regionAndId.id());
 
-            logger.debug(">> capturing virtual machine %s to container %s...", 
regionAndId.id(), CONTAINER_NAME);
-            URI uri = api.getVirtualMachineApi(resourceGroupName)
-                  .capture(regionAndId.id(), cloneTemplate.getName(), 
CONTAINER_NAME);
-            checkState(uri != null && imageAvailablePredicate.apply(uri),
-                  "Image for node %s was not created within the configured 
time limit", cloneTemplate.getName());
+            org.jclouds.azurecompute.arm.domain.Image imageFromVM = 
api.getVirtualMachineImageApi(resourceGroupName)
+                  .createOrUpdate(cloneTemplate.getName(), 
regionAndId.region(),
+                        
ImageProperties.builder().sourceVirtualMachine(vmIdRef).build());
 
-            List<ResourceDefinition> definitions = 
api.getJobApi().captureStatus(uri);
-            checkState(definitions.size() == 1,
-                  "Expected one resource definition after creating the image 
but %s were returned", definitions.size());
+            
checkState(imageAvailablePredicate.create(resourceGroupName).apply(imageFromVM.name()),
+                  "Image for node %s was not created within the configured 
time limit", cloneTemplate.getName());
 
-            Image image = 
resourceDefinitionToImage.create(cloneTemplate.getSourceNodeId(), 
cloneTemplate.getName())
-                  .apply(definitions.get(0));
-            checkState(image != null, "Image for node %s was not created", 
cloneTemplate.getSourceNodeId());
-            logger.debug(">> created %s", image);
-            return image;
+            return compose(vmImageToImage, 
customImagetoVmImage).apply(imageFromVM);
          }
       });
    }
@@ -137,25 +135,8 @@ public class AzureComputeImageExtension implements 
ImageExtension {
 
       logger.debug(">> deleting image %s", id);
 
-      StorageServiceKeys keys = 
api.getStorageAccountApi(image.group()).getKeys(image.storage());
-      BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
-
-      try {
-         // 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("system");
-         boolean result = !blobHelper.customImageExists();
-
-         if (!blobHelper.hasContainers()) {
-            logger.debug(">> storage account is empty after deleting the 
custom image. Deleting the storage account...");
-            api.getStorageAccountApi(image.group()).delete(image.storage());
-            cleanupResources.deleteResourceGroupIfEmpty(image.group());
-         }
-
-         return result;
-      } finally {
-         closeQuietly(blobHelper);
-      }
+      ResourceGroup resourceGroup = 
resourceGroupMap.getUnchecked(image.location());
+      URI uri = 
api.getVirtualMachineImageApi(resourceGroup.name()).delete(image.name());
+      return resourceDeleted.apply(uri);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
new file mode 100644
index 0000000..9cb2188
--- /dev/null
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/CustomImageToVMImage.java
@@ -0,0 +1,31 @@
+/*
+ * 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.compute.functions;
+
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.VMImage;
+
+import com.google.common.base.Function;
+
+public class CustomImageToVMImage implements Function<Image, VMImage> {
+
+   @Override
+   public VMImage apply(Image input) {
+      return 
VMImage.customImage().customImageId(input.id()).location(input.location()).name(input.name())
+            
.offer(input.properties().storageProfile().osDisk().osType()).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
deleted file mode 100644
index c27f584..0000000
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.compute.functions;
-
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.jclouds.azurecompute.arm.AzureComputeApi;
-import org.jclouds.azurecompute.arm.domain.RegionAndId;
-import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.VMImage;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import 
org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
-import org.jclouds.compute.domain.Image;
-
-import com.google.common.base.Function;
-import com.google.common.cache.LoadingCache;
-import com.google.inject.assistedinject.Assisted;
-
-public class ResourceDefinitionToCustomImage implements 
Function<ResourceDefinition, Image> {
-
-   public interface Factory {
-      ResourceDefinitionToCustomImage create(@Assisted("nodeId") String 
nodeId, @Assisted("imageName") String imageName);
-   }
-
-   private final Function<VMImage, Image> vmImageToImage;
-   private final String imageName;
-   private final String nodeId;
-   private final AzureComputeApi api;
-   private final StorageProfileToStorageAccountName 
storageProfileToStorageAccountName;
-   private final LoadingCache<String, ResourceGroup> resourceGroupMap;
-
-   @Inject
-   ResourceDefinitionToCustomImage(AzureComputeApi api,
-         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
-         Function<VMImage, Image> vmImageToImage, LoadingCache<String, 
ResourceGroup> resourceGroupMap,
-         @Assisted("nodeId") String nodeId, @Assisted("imageName") String 
imageName) {
-      this.api = api;
-      this.vmImageToImage = vmImageToImage;
-      this.nodeId = nodeId;
-      this.imageName = imageName;
-      this.storageProfileToStorageAccountName = 
storageProfileToStorageAccountName;
-      this.resourceGroupMap = resourceGroupMap;
-   }
-
-   @SuppressWarnings("unchecked")
-   @Override
-   public Image apply(ResourceDefinition input) {
-      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId);
-      ResourceGroup resourceGroup = 
resourceGroupMap.getUnchecked(regionAndId.region());
-      
-      VirtualMachine vm = 
api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
-      if (vm == null) {
-         return null;
-      }
-      String storageAccountName = 
storageProfileToStorageAccountName.apply(vm.properties().storageProfile());
-
-      VMImage.Builder builder = 
VMImage.customImage().group(resourceGroup.name()).storage(storageAccountName)
-            .name(imageName).offer(CUSTOM_IMAGE_OFFER).location(vm.location());
-
-      Map<String, String> properties = (Map<String, String>) 
input.properties();
-
-      Object storageObject = properties.get("storageProfile");
-      Map<String, String> storageProperties = (Map<String, String>) 
storageObject;
-
-      Object osDiskObject = storageProperties.get("osDisk");
-      Map<String, String> osProperties = (Map<String, String>) osDiskObject;
-      builder.vhd1(osProperties.get("name"));
-
-      return vmImageToImage.apply(builder.build());
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
index 1416872..2732b6e 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/TemplateToAvailabilitySet.java
@@ -87,7 +87,8 @@ public class TemplateToAvailabilitySet implements 
Function<Template, Availabilit
             logger.debug(">> creating availability set [%s]", 
options.getAvailabilitySet().name());
 
             availabilitySet = 
api.getAvailabilitySetApi(resourceGroup).createOrUpdate(
-                  options.getAvailabilitySet().name(), location, tags, 
options.getAvailabilitySet().properties());
+                  options.getAvailabilitySet().name(), 
options.getAvailabilitySet().sku(), location, tags,
+                  options.getAvailabilitySet().properties());
          }
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/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 25bcc3b..4f02100 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
@@ -19,6 +19,7 @@ package org.jclouds.azurecompute.arm.compute.functions;
 import java.util.Map;
 import java.util.Set;
 
+import 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
 import org.jclouds.azurecompute.arm.domain.Plan;
 import org.jclouds.azurecompute.arm.domain.VMImage;
@@ -55,20 +56,25 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
 
    private final Supplier<Set<? extends org.jclouds.domain.Location>> 
locations;
 
-   public static String encodeFieldsToUniqueId(boolean globallyAvailable, 
String locatioName,
+   public static String encodeFieldsToUniqueId(boolean globallyAvailable, 
String locationName,
          ImageReference imageReference) {
-      return (globallyAvailable ? "global" : locatioName) + "/" + 
imageReference.publisher() + "/"
+      return (globallyAvailable ? "global" : locationName) + "/" + 
imageReference.publisher() + "/"
             + imageReference.offer() + "/" + imageReference.sku();
    }
 
+   public static String encodeFieldsToUniqueIdCustom(boolean 
globallyAvailable, String locationName,
+         ImageReference imageReference) {
+      return (globallyAvailable ? "global" : locationName) + "/" + 
imageReference.customImageId()
+            .substring(imageReference.customImageId().lastIndexOf("/") + 1);
+   }
+
    public static String encodeFieldsToUniqueId(VMImage imageReference) {
       return (imageReference.globallyAvailable() ? "global" : 
imageReference.location()) + "/"
             + imageReference.publisher() + "/" + imageReference.offer() + "/" 
+ imageReference.sku();
    }
 
    public static String encodeFieldsToUniqueIdCustom(VMImage imageReference) {
-      return (imageReference.globallyAvailable() ? "global" : 
imageReference.location()) + "/" + imageReference.group()
-            + "/" + imageReference.storage() + "/" + imageReference.offer() + 
"/" + imageReference.name();
+      return (imageReference.globallyAvailable() ? "global" : 
imageReference.location()) + "/" + imageReference.name();
    }
 
    public static VMImage decodeFieldsFromUniqueId(final String id) {
@@ -76,17 +82,13 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
       String[] fields = checkNotNull(id, "id").split("/");
       if (isCustom(id)) {
          /* id fields indexes
-         0: imageReference.location) + "/" +
-         1: imageReference.group + "/" +
-         2: imageReference.storage + "/" +
-         3: imageReference.offer + "/" +
-         4: imageReference.name
+         0: imageReference.location + "/" +
+         1: imageReference.name
          */
-         vmImage = 
VMImage.customImage().location(fields[0]).group(fields[1]).storage(fields[2]).vhd1(fields[3])
-               .offer(fields[4]).build();
+         vmImage = 
VMImage.customImage().location(fields[0]).name(fields[1]).build();
       } else {
          /* id fields indexes
-         0: imageReference.location) + "/" +
+         0: imageReference.location + "/" +
          1: imageReference.publisher + "/" +
          2: imageReference.offer + "/" +
          3: imageReference.sku + "/" +
@@ -98,7 +100,7 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
    }
 
    @Inject
-   VMImageToImage(@Memoized final Supplier<Set<? extends Location>> locations) 
{
+   VMImageToImage(@Memoized Supplier<Set<? extends Location>> locations) {
       this.locations = locations;
    }
 
@@ -110,7 +112,7 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
          builder.location(
                      
FluentIterable.from(locations.get()).firstMatch(LocationPredicates.idEquals(image.location()))
                            
.get()).name(image.name()).description(image.group()).status(Image.Status.AVAILABLE)
-               
.version("latest").providerId(image.vhd1()).id(encodeFieldsToUniqueIdCustom(image));
+               
.version("latest").providerId(image.customImageId()).id(encodeFieldsToUniqueIdCustom(image));
 
          final OperatingSystem.Builder osBuilder = osFamily().apply(image);
          builder.operatingSystem(osBuilder.build());
@@ -165,7 +167,7 @@ public class VMImageToImage implements Function<VMImage, 
Image> {
 
             // only 64bit OS images are supported by Azure ARM
             return OperatingSystem.builder().family(family).is64Bit(true)
-                  .description(image.custom() ? image.vhd1() : image.sku())
+                  .description(image.custom() ? 
AzureComputeImageExtension.CUSTOM_IMAGE_OFFER : image.sku())
                   .version(image.custom() ? "latest" : image.sku());
          }
       };

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index cb40a14..9bad6e5 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
@@ -16,6 +16,15 @@
  */
 package org.jclouds.azurecompute.arm.compute.functions;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.nullToEmpty;
+import static com.google.common.collect.Iterables.find;
+import static 
org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
+import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
+import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
+import static 
org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -33,11 +42,7 @@ import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
-import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import 
org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Image;
@@ -59,18 +64,6 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Strings.nullToEmpty;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.tryFind;
-import static 
org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
-import static 
org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
-import static 
org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
-import static 
org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
-import static org.jclouds.location.predicates.LocationPredicates.idEquals;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, 
NodeMetadata> {
 
    @Resource
@@ -81,8 +74,6 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
    private final GroupNamingConvention nodeNamingConvention;
    private final Supplier<Set<? extends Location>> locations;
    private final Supplier<Map<String, ? extends Hardware>> hardwares;
-   private final Function<VMImage, Image> vmImageToImge;
-   private final StorageProfileToStorageAccountName 
storageProfileToStorageAccountName;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final ImageCacheSupplier imageCache;
    private final VirtualMachineToStatus virtualMachineToStatus;
@@ -90,16 +81,12 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
    @Inject
    VirtualMachineToNodeMetadata(AzureComputeApi api, 
GroupNamingConvention.Factory namingConvention,
          Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized 
Supplier<Set<? extends Location>> locations,
-         Map<String, Credentials> credentialStore, Function<VMImage, Image> 
vmImageToImge,
-         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
-         LoadingCache<String, ResourceGroup> resourceGroupMap, @Memoized 
Supplier<Set<? extends Image>> imageCache,
-         VirtualMachineToStatus virtualMachineToStatus) {
+         Map<String, Credentials> credentialStore, LoadingCache<String, 
ResourceGroup> resourceGroupMap,
+         @Memoized Supplier<Set<? extends Image>> imageCache, 
VirtualMachineToStatus virtualMachineToStatus) {
       this.api = api;
       this.nodeNamingConvention = namingConvention.createWithoutPrefix();
       this.locations = locations;
       this.hardwares = hardwares;
-      this.vmImageToImge = vmImageToImge;
-      this.storageProfileToStorageAccountName = 
storageProfileToStorageAccountName;
       this.resourceGroupMap = resourceGroupMap;
       this.virtualMachineToStatus = virtualMachineToStatus;
       checkArgument(imageCache instanceof ImageCacheSupplier,
@@ -207,29 +194,14 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
    protected Optional<? extends Image> findImage(final StorageProfile 
storageProfile, String locatioName,
          String azureGroup) {
       if (storageProfile.imageReference() != null) {
-         String imageId = encodeFieldsToUniqueId(false, locatioName, 
storageProfile.imageReference());
+         // FIXME check this condition
+         String imageId = storageProfile.imageReference().customImageId() != 
null ?
+               encodeFieldsToUniqueIdCustom(false, locatioName, 
storageProfile.imageReference()) :
+               encodeFieldsToUniqueId(false, locatioName, 
storageProfile.imageReference());
          return imageCache.get(imageId);
       } else {
-         String storageAccountName = 
storageProfileToStorageAccountName.apply(storageProfile);
-         StorageServiceKeys keys = 
api.getStorageAccountApi(azureGroup).getKeys(storageAccountName);
-         BlobHelper blobHelper = new BlobHelper(storageAccountName, 
keys.key1());
-
-         try {
-            // Custom image. Let's find it by uri
-            List<VMImage> customImagesInStorage = 
blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
-                  locatioName);
-            Optional<VMImage> customImage = tryFind(customImagesInStorage, new 
Predicate<VMImage>() {
-               @Override
-               public boolean apply(VMImage input) {
-                  return 
input.vhd1().equals(storageProfile.osDisk().image().uri());
-               }
-            });
-
-            return customImage.isPresent() ? 
Optional.of(vmImageToImge.apply(customImage.get())) : Optional
-                  .<Image> absent();
-         } finally {
-            closeQuietly(blobHelper);
-         }
+         logger.warn("could not find image for storage profile %s", 
storageProfile);
+         return Optional.absent();
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
index 481f695..fb635aa 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java
@@ -16,6 +16,11 @@
  */
 package org.jclouds.azurecompute.arm.compute.strategy;
 
+import static com.google.common.base.Predicates.notNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+
 import java.net.URI;
 import java.util.List;
 
@@ -32,11 +37,8 @@ import 
org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
-import 
org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
-import org.jclouds.azurecompute.arm.util.BlobHelper;
 import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
@@ -48,12 +50,6 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-import static com.google.common.base.Predicates.notNull;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
-import static org.jclouds.util.Closeables2.closeQuietly;
-
 @Singleton
 public class CleanupResources {
 
@@ -63,17 +59,14 @@ public class CleanupResources {
 
    private final AzureComputeApi api;
    private final Predicate<URI> resourceDeleted;
-   private final StorageProfileToStorageAccountName 
storageProfileToStorageAccountName;
    private final LoadingCache<String, ResourceGroup> resourceGroupMap;
    private final GroupNamingConvention.Factory namingConvention;
 
    @Inject
    CleanupResources(AzureComputeApi azureComputeApi, 
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
-         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
          LoadingCache<String, ResourceGroup> resourceGroupMap, 
GroupNamingConvention.Factory namingConvention) {
       this.api = azureComputeApi;
       this.resourceDeleted = resourceDeleted;
-      this.storageProfileToStorageAccountName = 
storageProfileToStorageAccountName;
       this.resourceGroupMap = resourceGroupMap;
       this.namingConvention = namingConvention;
    }
@@ -95,7 +88,6 @@ public class CleanupResources {
       // group. It will be deleted when the resource group is deleted
 
       cleanupVirtualMachineNICs(resourceGroupName, virtualMachine);
-      cleanupVirtualMachineStorage(resourceGroupName, virtualMachine);
       cleanupAvailabilitySetIfOrphaned(resourceGroupName, virtualMachine);
 
       return vmDeleted;
@@ -117,28 +109,6 @@ public class CleanupResources {
       }
    }
 
-   public void cleanupVirtualMachineStorage(String group, VirtualMachine 
virtualMachine) {
-      String storageAccountName = storageProfileToStorageAccountName
-            .apply(virtualMachine.properties().storageProfile());
-      StorageServiceKeys keys = 
api.getStorageAccountApi(group).getKeys(storageAccountName);
-
-      // Remove the virtual machine files
-      logger.debug(">> deleting virtual machine disk storage...");
-      BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
-      try {
-         blobHelper.deleteContainerIfExists("vhds");
-
-         if (!blobHelper.customImageExists()) {
-            logger.debug(">> deleting storage account %s...", 
storageAccountName);
-            api.getStorageAccountApi(group).delete(storageAccountName);
-         } else {
-            logger.debug(">> the storage account contains custom images. Will 
not delete it!");
-         }
-      } finally {
-         closeQuietly(blobHelper);
-      }
-   }
-
    public boolean cleanupSecurityGroupIfOrphaned(String resourceGroup, String 
group) {
       String name = namingConvention.create().sharedNameForGroup(group);
       NetworkSecurityGroupApi sgapi = 
api.getNetworkSecurityGroupApi(resourceGroup);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
index 624c664..4c4720e 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/AvailabilitySet.java
@@ -90,6 +90,47 @@ public abstract class AvailabilitySet {
          }
       }
    }
+   
+   public static enum AvailabilitySetType {
+      MANAGED("Aligned"),
+      CLASSIC("Classic");
+      
+      private final String value;
+
+      AvailabilitySetType(String value) {
+         this.value = value;
+      }
+
+      public static AvailabilitySetType fromString(String value) {
+         AvailabilitySetType[] items = AvailabilitySetType.values();
+         for (AvailabilitySetType item : items) {
+            if (item.toString().equalsIgnoreCase(value)) {
+               return item;
+            }
+         }
+         throw new IllegalArgumentException("Unexpected type: " + value);
+      }
+
+      @Override
+      public String toString() {
+         return this.value;
+      }
+   }
+   
+   @AutoValue
+   public abstract static class SKU {
+      
+      public abstract AvailabilitySetType type();
+      
+      @SerializedNames({ "name" })
+      public static SKU create(final String type) {
+         return create(AvailabilitySetType.fromString(type));
+      }
+      
+      public static SKU create(AvailabilitySetType type) {
+         return new AutoValue_AvailabilitySet_SKU(type);
+      }
+   }
 
    /**
     * The id of the availability set
@@ -116,30 +157,44 @@ public abstract class AvailabilitySet {
    public abstract String location();
 
    /**
+    * Specifies the type of the availability set
+    */
+   @Nullable
+   public abstract SKU sku();
+   
+   /**
     * Specifies the tags of the availability set
     */
    @Nullable
    public abstract Map<String, String> tags();
-
+   
    /**
     * Specifies the properties of the availability set
     */
    @Nullable
    public abstract AvailabilitySetProperties properties();
 
-
-   @SerializedNames({"id", "name", "type", "location", "tags", "properties"})
+   @SerializedNames({ "id", "name", "type", "location", "sku", "tags", 
"properties" })
    public static AvailabilitySet create(final String id, final String name, 
final String type, final String location,
-                                        final Map<String, String> tags, 
AvailabilitySetProperties properties) {
-      return 
builder().id(id).name(name).type(type).location(location).tags(tags).properties(properties).build();
+         SKU sku, final Map<String, String> tags, AvailabilitySetProperties 
properties) {
+      return 
builder().id(id).name(name).type(type).location(location).sku(sku).tags(tags).properties(properties)
+            .build();
    }
    
    public abstract Builder toBuilder();
    
-   public static Builder builder() {
+   private static Builder builder() {
       return new AutoValue_AvailabilitySet.Builder();
    }
    
+   public static Builder managed() {
+      return builder().managed();
+   }
+   
+   public static Builder classic() {
+      return builder().classic();
+   }
+   
    @AutoValue.Builder
    public abstract static class Builder {
       public abstract Builder id(String id);
@@ -149,6 +204,14 @@ public abstract class AvailabilitySet {
       public abstract Builder tags(Map<String, String> tags);
       public abstract Builder properties(AvailabilitySetProperties properties);
       
+      abstract Builder sku(SKU sku);
+      public Builder managed() {
+         return sku(SKU.create(AvailabilitySetType.MANAGED));
+      }
+      public Builder classic() {
+         return sku(SKU.create(AvailabilitySetType.CLASSIC));
+      }
+      
       abstract Map<String, String> tags();
       abstract AvailabilitySet autoBuild();
       

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
index 5d9226b..b442617 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/Image.java
@@ -26,6 +26,18 @@ import com.google.common.collect.ImmutableMap;
 
 @AutoValue
 public abstract class Image {
+   
+   /**
+    * The id of the image
+    */
+   @Nullable
+   public abstract String id();
+
+   /**
+    * The name of the image
+    */
+   @Nullable
+   public abstract String name();
 
    /**
     * The location of the image
@@ -42,9 +54,10 @@ public abstract class Image {
     */
    @Nullable public abstract Map<String, String> tags();
 
-   @SerializedNames({"location", "properties", "tags"})
-   public static Image create(final String location, final ImageProperties 
properties, final Map<String, String> tags) {
-      return 
builder().location(location).properties(properties).tags(tags).build();
+   @SerializedNames({"id", "name", "location", "properties", "tags"})
+   public static Image create(final String id, final String name, final String 
location,
+         final ImageProperties properties, final Map<String, String> tags) {
+      return 
builder().id(id).name(name).location(location).properties(properties).tags(tags).build();
    }
 
    public abstract Builder toBuilder();
@@ -55,10 +68,10 @@ public abstract class Image {
 
    @AutoValue.Builder
    public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
       public abstract Builder location(String location);
-
       public abstract Builder properties(ImageProperties properties);
-
       public abstract Builder tags(Map<String, String> tags);
 
       abstract Map<String, String> tags();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
index ef877be..44cb16e 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageProperties.java
@@ -24,17 +24,8 @@ import com.google.auto.value.AutoValue;
 @AutoValue
 public abstract class ImageProperties implements Provisionable {
 
-   @AutoValue
-   public abstract static class SourceVirtualMachine {
-      public abstract String id();
-
-      @SerializedNames({"id"})
-      public static SourceVirtualMachine create(final String id) {
-         return new AutoValue_ImageProperties_SourceVirtualMachine(id);
-      }
-   }
-   
-   public abstract SourceVirtualMachine sourceVirtualMachine();
+   @Nullable
+   public abstract IdReference sourceVirtualMachine();
    
    @Nullable
    public abstract StorageProfile storageProfile();
@@ -43,7 +34,7 @@ public abstract class ImageProperties implements 
Provisionable {
    public abstract String provisioningState();
    
    @SerializedNames({ "sourceVirtualMachine", "storageProfile", 
"provisioningState"})
-   public static ImageProperties create(final SourceVirtualMachine 
sourceVirtualMachine, 
+   public static ImageProperties create(final IdReference 
sourceVirtualMachine, 
                                         final StorageProfile storageProfile,
                                         final String provisioningState) {
       return builder()
@@ -61,7 +52,7 @@ public abstract class ImageProperties implements 
Provisionable {
 
    @AutoValue.Builder
    public abstract static class Builder {
-      public abstract Builder sourceVirtualMachine(SourceVirtualMachine 
sourceVirtualMachine);
+      public abstract Builder sourceVirtualMachine(IdReference 
sourceVirtualMachine);
       public abstract Builder storageProfile(StorageProfile storageProfile);
       public abstract Builder provisioningState(String provisioningState);
       public abstract ImageProperties build();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
index 443e054..d9b43cd 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ImageReference.java
@@ -25,11 +25,12 @@ import com.google.auto.value.AutoValue;
 public abstract class ImageReference {
 
    /**
-    * The id of the image reference.
+    * Specifies the resource identifier of a virtual machine image in your 
subscription. This element is only used
+    * for virtual machine images, not platform images or marketplace images.
     */
    @Nullable
-   public abstract String id();
-   
+   public abstract String customImageId();
+
    /**
     * The publisher of the image reference.
     */
@@ -53,6 +54,10 @@ public abstract class ImageReference {
     */
    @Nullable
    public abstract String version();
+   
+   ImageReference() {
+      
+   }
 
    @SerializedNames({"id", "publisher", "offer", "sku", "version"})
    public static ImageReference create(final String id,
@@ -61,8 +66,7 @@ public abstract class ImageReference {
                                        final String sku,
                                        final String version) {
 
-      return builder()
-              .id(id)
+      return builder().customImageId(id)
               .publisher(publisher)
               .offer(offer)
               .sku(sku)
@@ -78,7 +82,7 @@ public abstract class ImageReference {
 
    @AutoValue.Builder
    public abstract static class Builder {
-      public abstract Builder id(String id);
+      public abstract Builder customImageId(String ids);
       public abstract Builder publisher(String publisher);
       public abstract Builder offer(String offer);
       public abstract Builder sku(String sku);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
index 84cbab1..a8a0ae3 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/ManagedDiskParameters.java
@@ -24,42 +24,13 @@ import com.google.auto.value.AutoValue;
 @AutoValue
 public abstract class ManagedDiskParameters {
 
-   public enum StorageAccountTypes {
-      /** Enum value Standard_LRS. */
-      STANDARD_LRS("Standard_LRS"),
-
-      /** Enum value Premium_LRS. */
-      PREMIUM_LRS("Premium_LRS");
-
-      /** The actual serialized value for a StorageAccountTypes instance. */
-      private String value;
-
-      StorageAccountTypes(String value) {
-         this.value = value;
-      }
-
-      public static StorageAccountTypes fromString(String value) {
-         StorageAccountTypes[] items = StorageAccountTypes.values();
-         for (StorageAccountTypes item : items) {
-            if (item.toString().equalsIgnoreCase(value)) {
-               return item;
-            }
-         }
-         return null;
-      }
-
-      @Override
-      public String toString() {
-         return this.value;
-      }
-   }
-
    @Nullable public abstract String id();
 
-   public abstract StorageAccountTypes storageAccountType();
+   // Might be null in custom images. In that case the API returns it in the 
OSDisk object.
+   @Nullable public abstract StorageAccountType storageAccountType();
 
    @SerializedNames({"id", "storageAccountType"})
    public static ManagedDiskParameters create(final String id, final String 
storageAccountType) {
-      return new AutoValue_ManagedDiskParameters(id, 
StorageAccountTypes.fromString(storageAccountType));
+      return new AutoValue_ManagedDiskParameters(id, 
StorageAccountType.fromString(storageAccountType));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
index c87fe75..20392a0 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java
@@ -64,21 +64,20 @@ public abstract class OSDisk {
     */
    @Nullable public abstract ManagedDiskParameters managedDiskParameters();
    
-   @SerializedNames({"osType", "name", "vhd", "caching", "createOption", 
"image", "managedDisk"})
-   public static OSDisk create(final String osType, final String name, final 
VHD vhd,
-                               final String caching, final String 
createOption, final VHD image, 
-                               final ManagedDiskParameters 
managedDiskParamenters) {
-      return builder()
-            .osType(osType)
-            .name(name)
-            .vhd(vhd)
-            .caching(caching)
-            .createOption(createOption)
-            .image(image)
-              .managedDiskParameters(managedDiskParamenters)
-              .build();
+   /**
+    * The storage account type. This field is returned in custom images.
+    */
+   @Nullable public abstract StorageAccountType storageAccountType();
+
+   @SerializedNames({ "osType", "name", "vhd", "caching", "createOption", 
"image", "managedDisk", "storageAccountType" })
+   public static OSDisk create(final String osType, final String name, final 
VHD vhd, final String caching,
+         final String createOption, final VHD image, final 
ManagedDiskParameters managedDiskParamenters,
+         final String storageAccountType) {
+      return 
builder().osType(osType).name(name).vhd(vhd).caching(caching).createOption(createOption).image(image)
+            .managedDiskParameters(managedDiskParamenters)
+            
.storageAccountType(StorageAccountType.fromString(storageAccountType)).build();
    }
-   
+
    public abstract Builder toBuilder();
 
    public static Builder builder() {
@@ -94,6 +93,7 @@ public abstract class OSDisk {
       public abstract Builder vhd(VHD vhd);
       public abstract Builder image(VHD image);
       public abstract Builder managedDiskParameters(ManagedDiskParameters 
managedDiskParameters);
+      public abstract Builder storageAccountType(StorageAccountType 
storageAccountType);
       public abstract OSDisk build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
new file mode 100644
index 0000000..33e1109
--- /dev/null
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageAccountType.java
@@ -0,0 +1,47 @@
+/*
+ * 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.domain;
+
+public enum StorageAccountType {
+   /** Enum value Standard_LRS. */
+   STANDARD_LRS("Standard_LRS"),
+
+   /** Enum value Premium_LRS. */
+   PREMIUM_LRS("Premium_LRS");
+
+   /** The actual serialized value for a StorageAccountTypes instance. */
+   private String value;
+
+   StorageAccountType(String value) {
+      this.value = value;
+   }
+
+   public static StorageAccountType fromString(String value) {
+      StorageAccountType[] items = StorageAccountType.values();
+      for (StorageAccountType item : items) {
+         if (item.toString().equalsIgnoreCase(value)) {
+            return item;
+         }
+      }
+      return null;
+   }
+
+   @Override
+   public String toString() {
+      return this.value;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/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 04863ad..a01ed23 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
@@ -87,12 +87,18 @@ public abstract class VMImage {
     */
    @Nullable
    public abstract String name();
-
+   
    /**
     * True if custom image
     */
    public abstract boolean custom();
-   
+
+   /**
+    * The id of the custom image template.
+    */
+   @Nullable
+   public abstract String customImageId();
+
    /**
     * Extended version properties.
     */
@@ -104,18 +110,23 @@ public abstract class VMImage {
    }
    
    public static Builder azureImage() {
-      return new 
AutoValue_VMImage.Builder().globallyAvailable(false).custom(false);
+      return builder().globallyAvailable(false).custom(false);
    }
    
    public static Builder customImage() {
-      return new 
AutoValue_VMImage.Builder().globallyAvailable(false).custom(true);
+      return builder().globallyAvailable(false).custom(true);
+   }
+   
+   VMImage() {
+      
    }
    
    public abstract Builder toBuilder();
    
    @AutoValue.Builder
    public abstract static class Builder {
-      
+
+      public abstract Builder customImageId(String id);
       public abstract Builder publisher(String published);
       public abstract Builder offer(String offer);
       public abstract Builder sku(String sku);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/ea62a4c3/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
index 30456d4..cf5116c 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApi.java
@@ -28,13 +28,13 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
 import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
 import 
org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
+import org.jclouds.azurecompute.arm.domain.AvailabilitySet.SKU;
 import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
 import org.jclouds.azurecompute.arm.functions.URIParser;
 import org.jclouds.javax.annotation.Nullable;
@@ -65,12 +65,13 @@ public interface AvailabilitySetApi extends Closeable {
    AvailabilitySet get(@PathParam("name") String name);
 
    @Named("availabilityset:createOrUpdate")
+   @MapBinder(BindToJsonPayload.class)
    @Path("/{name}")
    @PUT
-   @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    AvailabilitySet createOrUpdate(@PathParam("name") String name,
-         @PayloadParam("location") String location, @Nullable 
@PayloadParam("tags") Map<String, String> tags,
+         @Nullable @PayloadParam("sku") SKU sku,
+         @PayloadParam("location") String location,
+         @Nullable @PayloadParam("tags") Map<String, String> tags,
          @PayloadParam("properties") AvailabilitySetProperties properties);
 
    @Named("availabilityset:delete")

Reply via email to