Update ImageExtension to work with Managed Disks
diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml
index 5860c30..028e476 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>
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 @@
     */
    @Delegate
    LoadBalancerApi getLoadBalancerApi(@PathParam("resourcegroup") String resourcegroup);
-   
+
    /**
     * The AvailabilitySet API includes operations for managing availability sets
     * within your subscription.
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 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 @@
       // 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 @@
       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");
       
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 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.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.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.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 @@
    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 @@
       }
       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 @@
       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 @@
          return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(version.name())
                  .location(location).versionProperties(version.properties()).build();
       }
+      
       return null;
    }
 
@@ -458,13 +414,9 @@
    }
 
    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 @@
               .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();
    }
    
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.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.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.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 @@
       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 @@
 
    @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 @@
          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 @@
    }
 
    @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 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();
+                  }
+               });
+            }
+         };
+      }
+   }
 
 }
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.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.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 @@
 
    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 @@
    @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 @@
          @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),
+            org.jclouds.azurecompute.arm.domain.Image imageFromVM = api.getVirtualMachineImageApi(resourceGroupName)
+                  .createOrUpdate(cloneTemplate.getName(), regionAndId.region(),
+                        ImageProperties.builder().sourceVirtualMachine(vmIdRef).build());
+
+            checkState(imageAvailablePredicate.create(resourceGroupName).apply(imageFromVM.name()),
                   "Image for node %s was not created within the configured time limit", cloneTemplate.getName());
 
-            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());
-
-            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 @@
 
       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);
    }
 }
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();
+   }
+}
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());
-   }
-
-}
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 @@
             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());
          }
       }
 
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 @@
 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 @@
 
    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 @@
       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 @@
    }
 
    @Inject
-   VMImageToImage(@Memoized final Supplier<Set<? extends Location>> locations) {
+   VMImageToImage(@Memoized Supplier<Set<? extends Location>> locations) {
       this.locations = locations;
    }
 
@@ -110,7 +112,7 @@
          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 @@
 
             // 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());
          }
       };
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.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.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 @@
    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 @@
    @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 @@
    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();
       }
    }
 
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.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.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 @@
 
    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 @@
       // 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 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);
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 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 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 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();
       
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 @@
 
 @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 @@
     */
    @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 @@
 
    @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();
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 @@
 @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 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 @@
 
    @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();
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 @@
 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 @@
     */
    @Nullable
    public abstract String version();
+   
+   ImageReference() {
+      
+   }
 
    @SerializedNames({"id", "publisher", "offer", "sku", "version"})
    public static ImageReference create(final String id,
@@ -61,8 +66,7 @@
                                        final String sku,
                                        final String version) {
 
-      return builder()
-              .id(id)
+      return builder().customImageId(id)
               .publisher(publisher)
               .offer(offer)
               .sku(sku)
@@ -78,7 +82,7 @@
 
    @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);
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 @@
 @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));
    }
 }
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 @@
     */
    @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 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();
    }
 }
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;
+   }
+}
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 @@
     */
    @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 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);
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.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 @@
    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")
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
index 8d446a5..1ff43de 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DeploymentApi.java
@@ -60,11 +60,11 @@
     */
    @Named("deployment:create")
    @Path("/{deploymentname}")
-   @Payload("{properties}")
+   @Payload("{template}")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    Deployment create(@PathParam("deploymentname") String deploymentname,
-                               @PayloadParam("properties") String properties);
+                               @PayloadParam("template") String template);
 
    /**
     * Get Deployment Information returns information about the specified deployment.
@@ -80,11 +80,11 @@
     */
    @Named("deployment:validate")
    @Path("/{deploymentname}/validate")
-   @Payload("{properties}")
+   @Payload("{template}")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    Deployment validate(@PathParam("deploymentname") String deploymentname,
-                                 @PayloadParam("properties") String properties);
+                                 @PayloadParam("template") String template);
 
    /**
     * List all deployments in a resource group
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
index 0797dbd..10e9ac6 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/DiskApi.java
@@ -26,7 +26,6 @@
 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;
@@ -38,7 +37,6 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
@@ -58,10 +56,8 @@
 
    @Named("disk:create_or_update")
    @PUT
-   @Payload("%7B\"location\":\"{location}\",\"properties\":{properties}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{diskName}")
-   @Produces(MediaType.APPLICATION_JSON)
    Disk createOrUpdate(@PathParam("diskName") String diskName,
                        @PayloadParam("location") String location,
                        @PayloadParam("properties") DiskProperties properties);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
index c97b0ac..96caa40 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ImageApi.java
@@ -26,7 +26,6 @@
 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;
@@ -38,7 +37,6 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
@@ -58,10 +56,8 @@
 
    @Named("image:create_or_update")
    @PUT
-   @Payload("%7B\"location\":\"{location}\",\"properties\":{properties}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{imageName}")
-   @Produces(MediaType.APPLICATION_JSON)
    Image createOrUpdate(@PathParam("imageName") String imageName,
                        @PayloadParam("location") String location,
                        @PayloadParam("properties") ImageProperties properties);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
index 3c3bab9..5a01e90 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java
@@ -40,7 +40,8 @@
 
 @RequestFilters(OAuthFilter.class)
 @Consumes(MediaType.APPLICATION_JSON)
-public interface JobApi extends Closeable{
+public interface JobApi extends Closeable {
+   
    @GET
    @ResponseParser(ParseJobStatus.class)
    JobStatus jobStatus(@EndpointParam URI jobURI);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
index f0ea900..f9805c0 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/LoadBalancerApi.java
@@ -27,7 +27,6 @@
 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;
@@ -67,7 +66,6 @@
    @Path("/{loadbalancername}")
    @PUT
    @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    LoadBalancer createOrUpdate(@PathParam("loadbalancername") String lbName,
          @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
          @PayloadParam("properties") LoadBalancerProperties properties);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
index ba4c2cd..41c0c85 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityGroupApi.java
@@ -27,7 +27,6 @@
 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;
@@ -68,7 +67,6 @@
    @Path("/{networksecuritygroupname}")
    @PUT
    @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    NetworkSecurityGroup createOrUpdate(@PathParam("networksecuritygroupname") String nsgName,
          @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
          @PayloadParam("properties") NetworkSecurityGroupProperties properties);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
index 8def4e3..7404234 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/NetworkSecurityRuleApi.java
@@ -26,7 +26,6 @@
 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;
@@ -48,11 +47,11 @@
 @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
 @Consumes(MediaType.APPLICATION_JSON)
 public interface NetworkSecurityRuleApi {
+
    @Named("networksecurityrule:createOrUpdate")
    @Path("/securityRules/{networksecurityrulename}")
    @PUT
    @MapBinder(BindToJsonPayload.class)
-   @Produces(MediaType.APPLICATION_JSON)
    NetworkSecurityRule createOrUpdate(@PathParam("networksecurityrulename") String ruleName,
                                       @PayloadParam("properties") NetworkSecurityRuleProperties properties);
 
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
index 2c6a8b3..7c51621 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceGroupApi.java
@@ -28,7 +28,6 @@
 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;
@@ -67,7 +66,6 @@
    @Named("resourcegroup:create")
    @PUT
    @Path("/{name}")
-   @Produces(MediaType.APPLICATION_JSON)
    @MapBinder(BindToJsonPayload.class)
    ResourceGroup create(@PathParam("name") String name, @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags);
 
@@ -87,7 +85,6 @@
 
    @Named("resourcegroup:update")
    @PATCH
-   @Produces(MediaType.APPLICATION_JSON)
    @Path("/{name}")
    @MapBinder(BindToJsonPayload.class)
    ResourceGroup update(@PathParam("name") String name, @Nullable @PayloadParam("tags") Map<String, String> tags);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
index a25e2a5..56dd0d4 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/ResourceProviderApi.java
@@ -16,7 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-
 import java.io.Closeable;
 import java.util.List;
 
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
index 5d2e06c..0c9399c 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/StorageAccountApi.java
@@ -79,9 +79,7 @@
     * PUT
     */
    @Named("storageaccount:create")
-   @Payload("%7B\"location\":\"{location}\",\"tags\":{tags},\"properties\":{properties}%7D")
    @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}")
-   @Produces(MediaType.APPLICATION_JSON)
    @ResponseParser(URIParser.class)
    @MapBinder(BindToJsonPayload.class)
    @PUT
@@ -120,7 +118,6 @@
    @Named("storageaccountkey:get")
    @POST
    @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}/listKeys")
-   @Produces(MediaType.APPLICATION_JSON)
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    StorageServiceKeys getKeys(@PathParam("storageAccountName") String storageAccountName);
 
@@ -143,10 +140,8 @@
     */
    @Named("storageaccount:update")
    @PATCH
-   @Payload("%7B\"tags\":{tags},\"properties\":{properties}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/resourcegroups/{resourceGroup}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}")
-   @Produces(MediaType.APPLICATION_JSON)
    StorageServiceUpdateParams update(
            @PathParam("storageAccountName") String storageAccountName,
            @Nullable @PayloadParam("tags") Map<String, String> tags,
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
index c87390e..39ed860 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/VirtualMachineApi.java
@@ -77,11 +77,9 @@
    
    @Named("CreateOrUpdateVirtualMachine")
    @PUT
-   @Payload("%7B\"location\":\"{location}\",\"tags\":{tags},\"properties\":{properties},\"plan\":{plan}%7D")
    @MapBinder(BindToJsonPayload.class)
    @Path("/{vmname}")
    @QueryParams(keys = "validating", values = "false")
-   @Produces(MediaType.APPLICATION_JSON)
    VirtualMachine createOrUpdate(@PathParam("vmname") String vmname,
                                  @PayloadParam("location") String location,
                                  @PayloadParam("properties") VirtualMachineProperties properties,
@@ -130,10 +128,10 @@
    @Named("capture")
    @POST
    @Payload("%7B\"vhdPrefix\":\"{vhdPrefix}\",\"destinationContainerName\":\"{destinationContainerName}\",\"overwriteVhds\":\"true\"%7D")
-   @MapBinder(BindToJsonPayload.class)
    @Path("/{name}/capture")
    @ResponseParser(URIParser.class)
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Produces(MediaType.APPLICATION_JSON)
    URI capture(@PathParam("name") String name,
                @PayloadParam("vhdPrefix") String vhdPrefix,
                @PayloadParam("destinationContainerName") String destinationContainerName);
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
deleted file mode 100644
index f624886..0000000
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/StorageProfileToStorageAccountName.java
+++ /dev/null
@@ -1,38 +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.functions;
-
-import java.net.URI;
-
-import org.jclouds.azurecompute.arm.domain.StorageProfile;
-
-import com.google.common.base.Function;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-
-/**
- * Returns the storage account name for a given storage profile.
- */
-public class StorageProfileToStorageAccountName implements Function<StorageProfile, String> {
-
-   @Override
-   public String apply(StorageProfile input) {
-      String storageAccountNameURI = input.osDisk().vhd().uri();
-      return Iterables.get(Splitter.on(".").split(URI.create(storageAccountNameURI).getHost()), 0);
-   }
-
-}
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
deleted file mode 100644
index b42ea5e..0000000
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/BlobHelper.java
+++ /dev/null
@@ -1,83 +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.util;
-
-import static org.jclouds.util.Closeables2.closeQuietly;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jclouds.ContextBuilder;
-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;
-
-public class BlobHelper implements Closeable {
-
-   private final String storageAccount;
-   private final AzureBlobClient azureBlob;
-
-   public BlobHelper(String storageAccount, String key) {
-      this.storageAccount = storageAccount;
-      this.azureBlob = ContextBuilder.newBuilder("azureblob").credentials(storageAccount, key)
-            .buildApi(AzureBlobClient.class);
-   }
-
-   @Override
-   public void close() throws IOException {
-      closeQuietly(azureBlob);
-   }
-
-   public void deleteContainerIfExists(String containerName) {
-      azureBlob.deleteContainer(containerName);
-   }
-
-   public boolean hasContainers() {
-      return !azureBlob.listContainers().isEmpty();
-   }
-
-   public boolean customImageExists() {
-      return azureBlob.containerExists("system");
-   }
-
-   public List<VMImage> getImages(String containerName, String group, String offer, String location) {
-      List<VMImage> list = new ArrayList<VMImage>();
-
-      ContainerProperties systemContainer = azureBlob.getContainerProperties("system");
-      if (systemContainer != null) {
-         ListBlobsResponse blobList = azureBlob.listBlobs(systemContainer.getName());
-         for (BlobProperties blob : blobList) {
-            String name = blob.getName();
-
-            if (name.contains("-osDisk")) {
-               String imageName = name.substring(name.lastIndexOf('/') + 1, name.indexOf("-osDisk"));
-               String imageUrl = blob.getUrl().toString();
-
-               list.add(VMImage.customImage().group(group).storage(storageAccount).vhd1(imageUrl).name(imageName)
-                     .offer(offer).location(location).build());
-            }
-         }
-      }
-
-      return list;
-   }
-
-}
diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
index d5b6394..a5944ec 100644
--- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
+++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/util/VMImages.java
@@ -21,7 +21,7 @@
 public class VMImages {
 
    public static boolean isCustom(String imageId) {
-      return checkNotNull(imageId, "id").split("/").length == 5;
+      return checkNotNull(imageId, "id").split("/").length == 2;
    }
   
 }
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
index 9c2427c..7c5c97f 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
@@ -16,8 +16,11 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.Properties;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
@@ -38,10 +41,12 @@
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 /**
  * Live tests for the {@link org.jclouds.compute.ComputeService} integration.
@@ -50,6 +55,7 @@
 public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
    
    private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
 
    public AzureComputeServiceLiveTest() {
       provider = "azurecompute-arm";
@@ -61,6 +67,8 @@
       resourceGroupMap = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
             }));
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
    }
 
    @Override
@@ -71,7 +79,11 @@
             ResourceGroup rg = resourceGroupMap.getIfPresent(template.getLocation().getId());
             if (rg != null) {
                AzureComputeApi api = view.unwrapApi(AzureComputeApi.class);
-               api.getResourceGroupApi().delete(rg.name());
+               URI uri = api.getResourceGroupApi().delete(rg.name());
+               if (uri != null) {
+                  assertTrue(resourceDeleted.apply(uri),
+                        String.format("Resource %s was not terminated in the configured timeout", uri));
+               }
             }
          }
       } finally {
@@ -97,7 +109,7 @@
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
index 56200c4..d4cbdb0 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
@@ -56,7 +56,7 @@
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -65,8 +65,8 @@
    @Test
    public void testDefaultTemplateBuilder() throws IOException {
       Template defaultTemplate = view.getComputeService().templateBuilder().build();
-      assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[45]\\.[01][04]\\.[0-9]-LTS"),
-            "Version mismatch, expected dd.dd.d-LTS, found: "
+      assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[456]\\.[01][04](\\.[0-9])?-LTS"),
+            "Version mismatch, expected dd.dd(.d)?-LTS, found: "
                   + defaultTemplate.getImage().getOperatingSystem().getVersion());
       assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
       assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
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 a6d19fa..d708723 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
@@ -17,7 +17,12 @@
 package org.jclouds.azurecompute.arm.compute.extensions;
 
 import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.Map;
 import java.util.Properties;
 
@@ -26,18 +31,23 @@
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
 import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.TemplateBuilder;
 import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
 import org.jclouds.domain.Location;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.sshj.config.SshjSshClientModule;
 import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 /**
  * Live tests for the {@link org.jclouds.compute.extensions.ImageExtension}
@@ -45,32 +55,34 @@
  */
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
 public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
-   
-   public static final String NAME_PREFIX = "%s";
-   
-   private LoadingCache<String, ResourceGroup> resourceGroupMap;
 
+   private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
+   private ResourceGroup testResourceGroup;
+   
    public AzureComputeImageExtensionLiveTest() {
       provider = "azurecompute-arm";
    }
-
-   @Override
-   public void initializeContext() {
-      super.initializeContext();
+   
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
       resourceGroupMap = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
             }));
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
+      createResourceGroup();
    }
-
+   
+   @AfterClass(groups = { "integration", "live" })
    @Override
-   @AfterClass(groups = "live", alwaysRun = true)
    protected void tearDownContext() {
       try {
-         Location location = getNodeTemplate().build().getLocation();
-         ResourceGroup rg = resourceGroupMap.getIfPresent(location.getId());
-         if (rg != null) {
-            AzureComputeApi api = view.unwrapApi(AzureComputeApi.class);
-            api.getResourceGroupApi().delete(rg.name());
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         if (uri != null) {
+            assertTrue(resourceDeleted.apply(uri),
+                  String.format("Resource %s was not terminated in the configured timeout", uri));
          }
       } finally {
          super.tearDownContext();
@@ -78,6 +90,17 @@
    }
 
    @Override
+   protected void prepareNodeBeforeCreatingImage(NodeMetadata node) {
+      // Don't wrap in the init-script, since the comand will clear the user
+      // config, and jclouds won't be able to execute more than one command
+      // (won't be able to poll for the execution status of the command when
+      // running with the init-script)
+      ExecResponse result = view.getComputeService().runScriptOnNode(node.getId(), "waagent -deprovision+user -force",
+            wrapInInitScript(false));
+      assertEquals(result.getExitStatus(), 0);
+   }
+
+   @Override
    protected Module getSshModule() {
       return new SshjSshClientModule();
    }
@@ -85,7 +108,7 @@
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
@@ -99,9 +122,11 @@
    public TemplateBuilder getNodeTemplate() {
       Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
       return super.getNodeTemplate().options(
-            authorizePublicKey(keyPair.get("public"))
-            .overrideLoginPrivateKey(keyPair.get("private")));
+            authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
    }
 
-
+   private void createResourceGroup() {
+      Location location = getNodeTemplate().build().getLocation();
+      testResourceGroup = resourceGroupMap.getUnchecked(location.getId());
+   }
 }
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
index 9296d69..e00880b 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtensionLiveTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.collect.Iterables.get;
 import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
 import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
 import static org.jclouds.compute.options.TemplateOptions.Builder.securityGroups;
 import static org.jclouds.compute.predicates.NodePredicates.inGroup;
@@ -26,6 +27,7 @@
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -49,9 +51,11 @@
 import org.testng.annotations.Test;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
 import com.google.common.cache.LoadingCache;
 import com.google.inject.Key;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 /**
  * Live test for AzureCompute
@@ -61,6 +65,7 @@
 public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
 
    private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
    private ResourceGroup testResourceGroup;
 
    public AzureComputeSecurityGroupExtensionLiveTest() {
@@ -73,6 +78,8 @@
       resourceGroupMap = context.utils().injector()
             .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
             }));
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
       createResourceGroup();
    }
 
@@ -134,7 +141,11 @@
    @Override
    protected void tearDownContext() {
       try {
-         view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
+         if (uri != null) {
+            assertTrue(resourceDeleted.apply(uri),
+                  String.format("Resource %s was not terminated in the configured timeout", uri));
+         }
       } finally {
          super.tearDownContext();
       }
@@ -143,7 +154,7 @@
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, "sgelivetest");
       setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
index 6e9e1e7..2b9e30a 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiLiveTest.java
@@ -17,6 +17,7 @@
 package org.jclouds.azurecompute.arm.features;
 
 import static com.google.common.collect.Iterables.any;
+import static org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetType.MANAGED;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -27,6 +28,7 @@
 
 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.internal.BaseAzureComputeApiLiveTest;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -56,10 +58,13 @@
    public void createAvailabilitySet() {
       AvailabilitySetProperties props = AvailabilitySetProperties.builder().platformUpdateDomainCount(2)
             .platformFaultDomainCount(3).build();
-      AvailabilitySet as = api().createOrUpdate(asName, LOCATION, null, props);
+      AvailabilitySet as = api().createOrUpdate(asName, SKU.create(MANAGED), LOCATION, null, props);
 
       assertNotNull(as);
       assertEquals(as.name(), asName);
+      
+      assertNotNull(as.sku());
+      assertEquals(as.sku().type(), MANAGED);
    }
 
    @Test(dependsOnMethods = "createAvailabilitySet")
@@ -80,7 +85,7 @@
    @Test(dependsOnMethods = "createAvailabilitySet")
    public void updateAvailabilitySet() {
       AvailabilitySet as = api().get(asName);
-      as = api().createOrUpdate(asName, LOCATION, ImmutableMap.of("foo", "bar"), as.properties());
+      as = api().createOrUpdate(asName, SKU.create(MANAGED), LOCATION, ImmutableMap.of("foo", "bar"), as.properties());
 
       assertNotNull(as);
       assertTrue(as.tags().containsKey("foo"));
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
index db9a7ed..430c32f 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/AvailabilitySetApiMockTest.java
@@ -17,6 +17,7 @@
 package org.jclouds.azurecompute.arm.features;
 
 import static com.google.common.collect.Iterables.isEmpty;
+import static org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetType.MANAGED;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -27,6 +28,7 @@
 
 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.internal.BaseAzureComputeApiMockTest;
 import org.testng.annotations.Test;
 
@@ -36,7 +38,7 @@
    private final String subscriptionid = "SUBSCRIPTIONID";
    private final String resourcegroup = "myresourcegroup";
    private final String asName = "myas";
-   private final String apiVersion = "api-version=2016-03-30";
+   private final String apiVersion = "api-version=2016-04-30-preview";
 
    public void createAvailabilitySet() throws InterruptedException {
 
@@ -46,12 +48,12 @@
 
       AvailabilitySetProperties props = AvailabilitySetProperties.builder().platformUpdateDomainCount(2)
             .platformFaultDomainCount(3).build();
-      AvailabilitySet as = asApi.createOrUpdate(asName, "westeurope", null, props);
+      AvailabilitySet as = asApi.createOrUpdate(asName, SKU.create(MANAGED), "westeurope", null, props);
 
       String path = String.format(
             "/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/availabilitySets/%s?%s", subscriptionid,
             resourcegroup, asName, apiVersion);
-      String json = "{\"location\":\"westeurope\",\"properties\":{\"platformUpdateDomainCount\":2,\"platformFaultDomainCount\":3}}";
+      String json = "{\"location\":\"westeurope\",\"properties\":{\"platformUpdateDomainCount\":2,\"platformFaultDomainCount\":3},\"sku\":{\"name\":\"Aligned\"}}";
       assertSent(server, "PUT", path, json);
 
       assertEquals(as.name(), asName);
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
index b485dc2..0b9ab05 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DeploymentApiLiveTest.java
@@ -23,11 +23,8 @@
 import java.net.URI;
 import java.util.List;
 
-import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.Deployment;
 import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
-import org.jclouds.azurecompute.arm.domain.Subnet;
-import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
 import org.jclouds.util.Predicates2;
 import org.testng.Assert;
@@ -37,12 +34,10 @@
 import com.google.common.base.Predicate;
 import com.google.common.net.UrlEscapers;
 
-@Test(testName = "DeploymentApiLiveTest", singleThreaded = true)
+@Test(groups = "live", testName = "DeploymentApiLiveTest", singleThreaded = true)
 public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    private String deploymentName;
-   private String subnetId;
-
    private String properties;
    private String badProperties;
 
@@ -52,7 +47,6 @@
       super.setup();
       createTestResourceGroup();
       deploymentName = "jc" + System.currentTimeMillis();
-      String virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
       String storageAccountName = String.format("st%s%s", System.getProperty("user.name"), RAND);
 
       String rawtemplate = "{\"$schema\":\"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#\",\"contentVersion\":\"1.0.0.0\",\"parameters\":{\"newStorageAccountName\":{\"type\":\"string\",\"metadata\":{\"description\":\"Name of the Storage Account\"}},\"storageAccountType\":{\"type\":\"string\",\"defaultValue\":\"Standard_LRS\",\"allowedValues\":[\"Standard_LRS\",\"Standard_GRS\",\"Standard_ZRS\"],\"metadata\":{\"description\":\"Storage Account type\"}},\"location\":{\"type\":\"string\",\"allowedValues\":[\"East US\",\"West US\",\"West Europe\",\"East Asia\",\"Southeast Asia\"],\"metadata\":{\"description\":\"Location of storage account\"}}},\"resources\":[{\"type\":\"Microsoft.Storage/storageAccounts\",\"name\":\"[parameters('newStorageAccountName')]\",\"apiVersion\":\"2015-05-01-preview\",\"location\":\"[parameters('location')]\",\"properties\":{\"accountType\":\"[parameters('storageAccountType')]\"}}]}";
@@ -61,17 +55,6 @@
 
       properties = getPutBody(rawtemplate, "Incremental", rawparameters);
       badProperties = getPutBody(rawtemplate, "Incremental", rawbadParameters);
-
-      //Subnets belong to a virtual network so that needs to be created first
-      VirtualNetwork vn = createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.3.0.0/16", LOCATION);
-      assertNotNull(vn);
-
-      //Subnet needs to be up & running before NIC can be created
-      String subnetName = String.format("s-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
-      Subnet subnet = createDefaultSubnet(resourceGroupName, subnetName, virtualNetworkName, "10.3.0.0/23");
-      assertNotNull(subnet);
-      assertNotNull(subnet.id());
-      subnetId = subnet.id();
    }
 
    private String getPutBody(String template, String mode, String parameters) {
@@ -104,48 +87,10 @@
       }
       assertNotNull(deploymentValid);
    }
-   @Test
+   
+   @Test(dependsOnMethods = "testValidate")
    public void testCreate() {
-      String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
-
-      AzureTemplateOptions options = new AzureTemplateOptions();
-      options.authorizePublicKey(rsakey);
-      options.subnetId(subnetId);
-
-      String deploymentTemplate = "{\n" +
-              "  \"id\": \"/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064\",\n" +
-              "  \"name\": \"jcdep1458344383064\",\n" +
-              "  \"properties\": {\n" +
-              "    \"parameters\": {\n" +
-              "      \"newStorageAccountName\": {\n" +
-              "        \"type\": \"String\",\n" +
-              "        \"value\": \"jcres1458344383064\"\n" +
-              "      },\n" +
-              "      \"storageAccountType\": {\n" +
-              "        \"type\": \"String\",\n" +
-              "        \"value\": \"Standard_LRS\"\n" +
-              "      },\n" +
-              "      \"location\": {\n" +
-              "        \"type\": \"String\",\n" +
-              "        \"value\": \"West US\"\n" +
-              "      }\n" +
-              "    },\n" +
-              "    \"mode\": \"Incremental\",\n" +
-              "    \"provisioningState\": \"Accepted\",\n" +
-              "    \"timestamp\": \"2016-03-18T23:39:47.3048037Z\",\n" +
-              "    \"duration\": \"PT2.4433028S\",\n" +
-              "    \"correlationId\": \"8dee9711-8632-4948-9fe6-368bb75e6438\",\n" +
-              "    \"providers\": [{\n" +
-              "      \"namespace\": \"Microsoft.Storage\",\n" +
-              "      \"resourceTypes\": [{\n" +
-              "        \"resourceType\": \"storageAccounts\",\n" +
-              "        \"locations\": [\"westus\"]\n" +
-              "      }]\n" +
-              "    }],\n" +
-              "    \"dependencies\": []\n" +
-              "  }\n" +
-              "}";
-      deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
+      String deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(properties);
 
       Deployment deploymentValid = api().validate(deploymentName, deploymentTemplate);
       assertNotNull(deploymentValid);
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
index becfccd..f5af885 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/DiskApiLiveTest.java
@@ -36,10 +36,10 @@
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
-@Test(groups = "live", singleThreaded = true)
+@Test(groups = "live", testName = "DiskApiLiveTest", singleThreaded = true)
 public class DiskApiLiveTest extends BaseAzureComputeApiLiveTest {
 
-   public static final String JCLOUDS_IMAGE_PREFIX = "jclouds-";
+   public static final String JCLOUDS_DISK_PREFIX = "jclouds-";
    private String diskName;
 
    @BeforeClass
@@ -47,12 +47,12 @@
    public void setup() {
       super.setup();
       createTestResourceGroup();
-      diskName = JCLOUDS_IMAGE_PREFIX + RAND;
+      diskName = JCLOUDS_DISK_PREFIX + RAND;
    }
 
    @Test
    public void deleteDiskResourceDoesNotExist() {
-      assertNull(api().delete(JCLOUDS_IMAGE_PREFIX + UUID.randomUUID()));
+      assertNull(api().delete(JCLOUDS_DISK_PREFIX + UUID.randomUUID()));
    }
 
    @Test
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
index 038fc31..d976258 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiLiveTest.java
@@ -16,90 +16,154 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
-import org.jclouds.azurecompute.arm.domain.Image;
-import org.jclouds.azurecompute.arm.domain.ImageProperties;
-import org.jclouds.azurecompute.arm.domain.Provisionable;
-import org.jclouds.azurecompute.arm.domain.VirtualMachine;
-import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
-import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Supplier;
-
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
-@Test(groups = "live", singleThreaded = true)
-public class ImageApiLiveTest extends BaseAzureComputeApiLiveTest {
+import java.net.URI;
+import java.util.Properties;
 
-   public static final String JCLOUDS_VM_IMAGE_PREFIX = "jclouds-vm-image-";
-   private String imageName;
-   private VirtualMachine virtualMachine;
+import org.jclouds.azurecompute.arm.AzureComputeApi;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
+import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.domain.Location;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
 
-   @BeforeClass
+import com.google.common.base.Predicate;
+import com.google.common.cache.LoadingCache;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+// We extend the BaseComputeServiceContextLiveTest to create nodes using the abstraction, which is much easier
+@Test(groups = "live", singleThreaded = true, testName = "ImageApiLiveTest")
+public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
+
+   private static final String imageName = "imageFromRest";
+
+   private LoadingCache<String, ResourceGroup> resourceGroupMap;
+   private Predicate<URI> resourceDeleted;
+   private AzureComputeApi api;
+
+   private String resourceGroupName;
+   private String location;
+   private ImageApi imageApi;
+   private Image image;
+
+   private String group;
+
+   public ImageApiLiveTest() {
+      provider = "azurecompute-arm";
+      group = getClass().getSimpleName().toLowerCase();
+   }
+
    @Override
-   public void setup() {
-      super.setup();
-      createTestResourceGroup();
-      imageName = JCLOUDS_VM_IMAGE_PREFIX + RAND;
-      String vmName = "jclouds-vm-" + RAND;
+   protected Properties setupProperties() {
+      Properties properties = super.setupProperties();
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
+      checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
+      return properties;
+   }
 
-      virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(vmName, LOCATION, VirtualMachineProperties.builder().build(),
-              Collections.<String, String> emptyMap(), null);
+   @Override
+   protected void initializeContext() {
+      super.initializeContext();
+      resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
+      }, Names.named(TIMEOUT_RESOURCE_DELETED)));
+      resourceGroupMap = context.utils().injector()
+            .getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
+            }));
+      api = view.unwrapApi(AzureComputeApi.class);
+   }
+
+   @Override
+   @BeforeClass
+   public void setupContext() {
+      super.setupContext();
+      // Use the resource name conventions used in the abstraction
+      ResourceGroup resourceGroup = createResourceGroup();
+      resourceGroupName = resourceGroup.name();
+      location = resourceGroup.location();
+      imageApi = api.getVirtualMachineImageApi(resourceGroupName);
+   }
+
+   @Override
+   @AfterClass(alwaysRun = true)
+   protected void tearDownContext() {
+      try {
+         view.getComputeService().destroyNodesMatching(inGroup(group));
+      } finally {
+         try {
+            URI uri = api.getResourceGroupApi().delete(resourceGroupName);
+            assertResourceDeleted(uri);
+         } finally {
+            super.tearDownContext();
+         }
+      }
    }
 
    @Test
-   public void deleteImageResourceDoesNotExist() {
-      assertNull(api().delete(JCLOUDS_VM_IMAGE_PREFIX + UUID.randomUUID()));
+   public void testDeleteImageDoesNotExist() {
+      assertNull(imageApi.delete("notAnImage"));
    }
 
    @Test
-   public void CreateVirtualMachineImageFromExistingVM() {
-      String id = String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/myVM", getSubscriptionId(), resourceGroupName);
-      ImageProperties properties = ImageProperties.builder()
-              .sourceVirtualMachine(ImageProperties.SourceVirtualMachine.create(id))
-              .build();
-      Image image = api().createOrUpdate(imageName, LOCATION, properties);
-      assertTrue(waitUntilAvailable(imageName), "creation operation did not complete in the configured timeout");
-      assertTrue(id.equals(image.properties().sourceVirtualMachine().id()));
-   }
+   public void testCreateImage() throws RunNodesException {
+      NodeMetadata node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1));
+      IdReference vmIdRef = IdReference.create(node.getProviderId());
+      view.getComputeService().suspendNode(node.getId());
 
-   @Test(dependsOnMethods = "CreateVirtualMachineImageFromExistingVM")
-   public void getImage() {
-      Image image = api().get(imageName);
+      api.getVirtualMachineApi(resourceGroupName).generalize(node.getName());
+
+      image = imageApi.createOrUpdate(imageName, location, ImageProperties.builder()
+            .sourceVirtualMachine(vmIdRef).build());
       assertNotNull(image);
    }
 
-   @Test(dependsOnMethods = "CreateVirtualMachineImageFromExistingVM")
-   public void listImages() {
-      List<Image> images = api().list();
-      assertTrue(images.size() > 0);
-   }
-
-   @Test(dependsOnMethods = {"listImages", "getImage"}, alwaysRun = true)
-   public void deleteImage() {
-      URI uri = api().delete(imageName);
-      assertNotNull(uri);
-   }
-
-   private ImageApi api() {
-      return api.getVirtualMachineImageApi(resourceGroupName);
-   }
-   
-   private boolean waitUntilAvailable(final String name) {
-      return resourceAvailable.apply(new Supplier<Provisionable>() {
-         @Override public Provisionable get() {
-            Image image = api().get(name);
-            return image == null ? null : image.properties();
+   @Test(dependsOnMethods = "testCreateImage")
+   public void testListImages() {
+      // Check that the image we've just created exists
+      assertTrue(any(imageApi.list(), new Predicate<Image>() {
+         @Override
+         public boolean apply(Image input) {
+            return image.name().equals(input.name());
          }
-      });
+      }));
    }
-}
 
+   @Test(dependsOnMethods = "testCreateImage")
+   public void testGetImage() {
+      assertNotNull(imageApi.get(imageName));
+   }
+
+   @Test(dependsOnMethods = { "testCreateImage", "testListImages", "testGetImage" }, alwaysRun = true)
+   public void deleteImage() {
+      assertResourceDeleted(imageApi.delete(imageName));
+   }
+
+   private void assertResourceDeleted(final URI uri) {
+      if (uri != null) {
+         assertTrue(resourceDeleted.apply(uri),
+               String.format("Resource %s was not deleted in the configured timeout", uri));
+      }
+   }
+
+   private ResourceGroup createResourceGroup() {
+      Location location = view.getComputeService().templateBuilder().build().getLocation();
+      return resourceGroupMap.getUnchecked(location.getId());
+   }
+
+}
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java
new file mode 100644
index 0000000..cec0483
--- /dev/null
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/ImageApiMockTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jclouds.azurecompute.arm.domain.DataDisk;
+import org.jclouds.azurecompute.arm.domain.IdReference;
+import org.jclouds.azurecompute.arm.domain.Image;
+import org.jclouds.azurecompute.arm.domain.ImageProperties;
+import org.jclouds.azurecompute.arm.domain.OSDisk;
+import org.jclouds.azurecompute.arm.domain.StorageProfile;
+import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "unit", testName = "ImageApiMockTest", singleThreaded = true)
+public class ImageApiMockTest extends BaseAzureComputeApiMockTest {
+   private static final String subscriptionid = "SUBSCRIPTIONID";
+   private static final String resourcegroup = "myresourcegroup";
+   private static final String apiVersion = "api-version=2016-04-30-preview";
+   private static final String imageName = "testVirtualMachineImage";
+   private static final String location = "canadaeast";
+   
+   private static final String PATH = String
+         .format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/images/%s?%s", subscriptionid,
+               resourcegroup, imageName, apiVersion);
+
+   public void createVirtualMachineImage() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachineimagecreate.json"));
+
+      ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      Image result = imageApi.createOrUpdate(imageName, location, newVirtualMachineImage().properties());
+      
+      assertSent(server, "PUT", PATH, "{\"location\":\"" + location + "\","
+            + "\"properties\":{\"sourceVirtualMachine\":{\"id\":\"vmId\"},"
+            + "\"storageProfile\":{\"osDisk\":{\"osType\":\"Linux\",\"name\":\"Ubuntu\"},\"dataDisks\":[]},"
+            + "\"provisioningState\":\"Succeeded\"}}");
+
+      assertEquals(result.name(), imageName);
+      assertEquals(result.location(), location);
+   }
+
+   public void getVirtualMachineImage() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachineimageget.json"));
+
+      ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      Image result = imageApi.get(imageName);
+
+      assertSent(server, "GET", PATH);
+
+      assertEquals(result.name(), imageName);
+      assertEquals(result.location(), location);
+      assertNotNull(result.properties().sourceVirtualMachine());
+      assertNotNull(result.properties().storageProfile());
+   }
+
+   public void getVirtualMachineImageReturns404() throws InterruptedException {
+      server.enqueue(response404());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      Image result = imageApi.get(imageName);
+
+      assertSent(server, "GET", PATH);
+      
+      assertNull(result);
+   }
+
+   public void listVirtualMachineImages() throws InterruptedException {
+      server.enqueue(jsonResponse("/virtualmachineimagelist.json"));
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      List<Image> result = imageApi.list();
+
+      assertSent(server, "GET", String
+            .format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/images?%s", subscriptionid,
+                  resourcegroup, apiVersion));
+
+      assertNotNull(result);
+      assertTrue(result.size() > 0);
+   }
+
+   public void listVirtualMachineImagesReturns404() throws InterruptedException {
+      server.enqueue(response404());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      List<Image> result = imageApi.list();
+
+      assertSent(server, "GET", String
+            .format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Compute/images?%s", subscriptionid,
+                  resourcegroup, apiVersion));
+
+      assertTrue(isEmpty(result));
+   }
+
+   public void deleteVirtualMachineImage() throws InterruptedException {
+      server.enqueue(response202WithHeader());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      URI uri = imageApi.delete(imageName);
+
+      assertSent(server, "DELETE", PATH);
+
+      assertNotNull(uri);
+      assertTrue(uri.toString().contains("api-version"));
+      assertTrue(uri.toString().contains("operationresults"));
+   }
+
+   public void deleteVirtualMachineImageDoesNotExist() throws InterruptedException {
+      server.enqueue(response404());
+
+      final ImageApi imageApi = api.getVirtualMachineImageApi(resourcegroup);
+      URI uri = imageApi.delete(imageName);
+      assertNull(uri);
+
+      assertSent(server, "DELETE", PATH);
+   }
+
+   private Image newVirtualMachineImage() {
+      return Image
+            .builder()
+            .name(imageName)
+            .location(location)
+            .properties(
+                  ImageProperties
+                        .builder()
+                        .sourceVirtualMachine(IdReference.create("vmId"))
+                        .storageProfile(
+                              StorageProfile.create(null, OSDisk.builder().osType("Linux").name("Ubuntu").build(),
+                                    ImmutableList.<DataDisk> of())).provisioningState("Succeeded").build()).build();
+      
+   }
+}
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
index 69014a5..5799093 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/LoadBalancerApiLiveTest.java
@@ -116,7 +116,7 @@
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }
@@ -356,7 +356,7 @@
       // set
       AvailabilitySetProperties props = AvailabilitySetProperties.builder().platformUpdateDomainCount(count)
             .platformFaultDomainCount(count).build();
-      AvailabilitySet as = AvailabilitySet.builder().name(group).properties(props).build();
+      AvailabilitySet as = AvailabilitySet.managed().name(group).properties(props).build();
 
       Set<? extends NodeMetadata> nodes = view.getComputeService()
             .createNodesInGroup(group, count, availabilitySet(as));
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
index ccf1e70..cecdc01 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiLiveTest.java
@@ -16,6 +16,12 @@
  */
 package org.jclouds.azurecompute.arm.features;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -24,7 +30,6 @@
 import java.util.Map;
 
 import org.jclouds.azurecompute.arm.domain.DataDisk;
-import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.ImageReference;
@@ -37,6 +42,7 @@
 import org.jclouds.azurecompute.arm.domain.OSDisk;
 import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
+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.Subnet;
@@ -45,8 +51,8 @@
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.PowerState;
 import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
+import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
-import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -55,20 +61,12 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
 @Test(groups = "live", testName = "VirtualMachineApiLiveTest")
 public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
 
    private String subscriptionid;
-   private String storageServiceName;
    private String vmName;
    private String nicName;
-   private StorageService storageService;
    private String virtualNetworkName;
    private String subnetId;
 
@@ -81,9 +79,6 @@
       createTestResourceGroup();
       virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
 
-      storageServiceName = String.format("st%s%s", System.getProperty("user.name"), RAND);
-      storageService = createStorageService(resourceGroupName, storageServiceName, LOCATION);
-
       // Subnets belong to a virtual network so that needs to be created first
       assertNotNull(createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.2.0.0/16", LOCATION));
 
@@ -103,25 +98,10 @@
 
    @Test
    public void testCreate() {
-      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
-
-      VirtualMachine vm = api().createOrUpdate(vmName, LOCATION, getProperties(blob, nicName),
+      VirtualMachine vm = api().createOrUpdate(vmName, LOCATION, getProperties(nicName, null),
             Collections.<String, String> emptyMap(), null);
       assertTrue(!vm.name().isEmpty());
-
-      //Poll until resource is ready to be used
-      boolean jobDone = retry(new Predicate<String>() {
-         @Override
-         public boolean apply(String name) {
-            return !api().get(name).properties().provisioningState().equals(VirtualMachineProperties.ProvisioningState.CREATING);
-         }
-      }, 60 * 20 * 1000).apply(vmName);
-      assertTrue(jobDone, "createOrUpdate operation did not complete in the configured timeout");
-
-      VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
-      // Cannot be creating anymore. Should be succeeded or running but not failed.
-      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.CREATING);
-      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.FAILED);
+      waitUntilReady(vmName);
    }
 
    @Test(dependsOnMethods = "testCreate")
@@ -139,7 +119,7 @@
    @Test(dependsOnMethods = "testGet")
    public void testStart() {
       api().start(vmName);
-      assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.RUNNING), "start operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testStart")
@@ -147,15 +127,12 @@
       VirtualMachine vm = api().get(vmName);
       VirtualMachineProperties oldProperties = vm.properties();
       StorageProfile oldStorageProfile = oldProperties.storageProfile();
-
-      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
-      VHD vhd = VHD.create(blob + "vhds/" + vmName + "new-data-disk.vhd");
+      
       DataDisk newDataDisk = DataDisk.builder()
               .name(vmName + "new-data-disk")
               .diskSizeGB("1")
               .lun(1)
               .createOption(DataDisk.DiskCreateOptionTypes.EMPTY)
-              .vhd(vhd)
               .build();
       List<DataDisk> oldDataDisks = oldStorageProfile.dataDisks();
       assertEquals(oldDataDisks.size(), 1);
@@ -173,15 +150,15 @@
    @Test(dependsOnMethods = "testUpdate")
    public void testStop() {
       api().stop(vmName);
-      assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.STOPPED), "stop operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testStop")
    public void testRestart() {
       api().start(vmName);
-      assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.RUNNING), "start operation did not complete in the configured timeout");
       api().restart(vmName);
-      assertTrue(stateReached(PowerState.RUNNING), "restart operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.RUNNING), "restart operation did not complete in the configured timeout");
    }
 
    @Test(dependsOnMethods = "testCreate")
@@ -201,15 +178,31 @@
    @Test(dependsOnMethods = "testRestart")
    public void testGeneralize() throws IllegalStateException {
       api().stop(vmName);
-      assertTrue(stateReached(PowerState.STOPPED), "restart operation did not complete in the configured timeout");
+      assertTrue(stateReached(vmName, PowerState.STOPPED), "restart operation did not complete in the configured timeout");
       api().generalize(vmName);
    }
 
    @SuppressWarnings("unchecked")
-   @Test(dependsOnMethods = "testGeneralize")
+   @Test
    public void testCapture() throws IllegalStateException {
-      URI uri = api().capture(vmName, vmName, vmName);
-      if (uri == null) Assert.fail();
+      // Capture is only allowed for Blob based VMs, so let's create one VM for this test
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(resourceGroupName, "capture-nic-" + RAND, LOCATION, "ipConfig-" + RAND);
+      StorageService storageService = createStorageService(resourceGroupName, "capture" + RAND, LOCATION);
+      String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
+      
+      String captureVmName = "capture-" + RAND;
+      api().createOrUpdate(captureVmName, LOCATION, getProperties(nic.name(), blob),
+            Collections.<String, String> emptyMap(), null);
+      waitUntilReady(captureVmName);
+      
+      api().stop(captureVmName);
+      assertTrue(stateReached(captureVmName, PowerState.STOPPED),
+            "restart operation did not complete in the configured timeout");
+      api().generalize(captureVmName);
+      
+      URI uri = api().capture(captureVmName, captureVmName, captureVmName);
+      assertNotNull(uri);
+      
       if (imageAvailablePredicate.apply(uri)) {
          List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
          if (definitions != null) {
@@ -219,18 +212,13 @@
                Map<String, String> properties2 = (Map<String, String>) storageObject;
                Object osDiskObject = properties2.get("osDisk");
                Map<String, String> osProperties = (Map<String, String>) osDiskObject;
-               Object dataDisksObject = properties2.get("dataDisks");
-               List<Object> dataProperties = (List<Object>) dataDisksObject;
-               Map<String, String> datadiskObject = (Map<String, String>) dataProperties.get(0);
-
                assertNotNull(osProperties.get("name"));
-               assertNotNull(datadiskObject.get("name"));
             }
          }
       }
    }
 
-   @Test(dependsOnMethods = "testCapture", alwaysRun = true)
+   @Test(dependsOnMethods = "testGeneralize", alwaysRun = true)
    public void testDelete() throws Exception {
       URI uri = api().delete(vmName);
       assertResourceDeleted(uri);
@@ -240,22 +228,28 @@
       return api.getVirtualMachineApi(resourceGroupName);
    }
 
-   private VirtualMachineProperties getProperties(String blob, String nic) {
+   private VirtualMachineProperties getProperties(String nic, String blob) {
 
       HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
       ImageReference imgRef = ImageReference.builder().publisher("MicrosoftWindowsServerEssentials")
               .offer("WindowsServerEssentials").sku("WindowsServerEssentials").version("latest").build();
-      DataDisk dataDisk = DataDisk.builder().name("data").diskSizeGB("100").lun(0).createOption(DataDisk.DiskCreateOptionTypes.EMPTY).build();
-      List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      dataDisks.add(dataDisk);
-
-      OSDisk osDisk = OSDisk.builder()
+      
+      DataDisk.Builder dataDisk = DataDisk.builder().name("data").diskSizeGB("100").lun(0).createOption(DataDisk.DiskCreateOptionTypes.EMPTY);
+      
+      OSDisk.Builder osDisk = OSDisk.builder()
+              .name("os")
               .osType("Windows")
               .caching(DataDisk.CachingTypes.READ_WRITE.toString())
-              .createOption("FromImage")
-              .managedDiskParameters(ManagedDiskParameters.create(null, ManagedDiskParameters.StorageAccountTypes.STANDARD_LRS.toString()))
-              .build();
-      StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
+              .createOption("FromImage");
+      
+      if (blob == null) {
+         osDisk.managedDiskParameters(ManagedDiskParameters.create(null, StorageAccountType.STANDARD_LRS.toString()));
+      } else {
+         osDisk.vhd(VHD.create(blob + "vhds/" + vmName + ".vhd"));
+         dataDisk.vhd(VHD.create(blob + "vhds/" + vmName + "data.vhd"));
+      }
+      
+      StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk.build(), ImmutableList.of(dataDisk.build()));
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
               null);
       OSProfile osProfile = OSProfile.create(vmName, "azureuser", "RFe3&432dg", null, null, windowsConfig);
@@ -267,15 +261,12 @@
               new ArrayList<IdReference>();
       networkInterfaces.add(networkInterface);
       NetworkProfile networkProfile = NetworkProfile.create(networkInterfaces);
-      DiagnosticsProfile.BootDiagnostics bootDiagnostics =
-              DiagnosticsProfile.BootDiagnostics.create(true, blob);
-      DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
       VirtualMachineProperties properties = VirtualMachineProperties.create(null,
-              null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
+              null, null, hwProf, storageProfile, osProfile, networkProfile, null, VirtualMachineProperties.ProvisioningState.CREATING);
       return properties;
    }
 
-   protected NetworkInterfaceCard createNetworkInterfaceCard(final String resourceGroupName, String networkInterfaceCardName, String locationName, String ipConfigurationName) {
+   private NetworkInterfaceCard createNetworkInterfaceCard(final String resourceGroupName, String networkInterfaceCardName, String locationName, String ipConfigurationName) {
       //Create properties object
       final NetworkInterfaceCardProperties networkInterfaceCardProperties = NetworkInterfaceCardProperties
             .builder()
@@ -286,12 +277,46 @@
       final Map<String, String> tags = ImmutableMap.of("jclouds", "livetest");
       return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags);
    }
+   
+   private StorageService createStorageService(final String resourceGroupName, final String storageServiceName,
+         final String location) {
+      URI uri = api.getStorageAccountApi(resourceGroupName).create(storageServiceName, location,
+            ImmutableMap.of("property_name", "property_value"),
+            ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
+      if (uri != null) {
+         assertTrue(uri.toString().contains("api-version"));
+
+         boolean jobDone = retry(new Predicate<URI>() {
+            @Override
+            public boolean apply(final URI uri) {
+               return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
+            }
+         }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri);
+         assertTrue(jobDone, "create operation did not complete in the configured timeout");
+      }
+      return api.getStorageAccountApi(resourceGroupName).get(storageServiceName);
+   }
 
    private boolean waitForState(String name, final PowerState state) {
       return api().getInstanceDetails(name).powerState().equals(state);
    }
+   
+   private void waitUntilReady(String vmName) {
+      boolean ready = retry(new Predicate<String>() {
+         @Override
+         public boolean apply(String name) {
+            return !api().get(name).properties().provisioningState().equals(VirtualMachineProperties.ProvisioningState.CREATING);
+         }
+      }, 60 * 20 * 1000).apply(vmName);
+      assertTrue(ready, "createOrUpdate operation did not complete in the configured timeout");
 
-   private boolean stateReached(final PowerState state) {
+      VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
+      // Cannot be creating anymore. Should be succeeded or running but not failed.
+      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.CREATING);
+      assertThat(status).isNotEqualTo(VirtualMachineProperties.ProvisioningState.FAILED);
+   }
+
+   private boolean stateReached(String vmName, final PowerState state) {
       return retry(new Predicate<String>() {
          @Override
          public boolean apply(String name) {
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
index 34b59c3..27e6f6b 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/features/VirtualMachineApiMockTest.java
@@ -233,7 +233,7 @@
       assertNotNull(uri);
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
             + "/virtualMachines/vm/capture?api-version=2016-04-30-preview",
-            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
+            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\",\"overwriteVhds\":\"true\"}");
    }
 
    public void testCapture404() throws Exception {
@@ -244,7 +244,7 @@
       assertNull(uri);
       assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute"
             + "/virtualMachines/vm/capture?api-version=2016-04-30-preview",
-            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
+            "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\",\"overwriteVhds\":\"true\"}");
    }
 
    private VirtualMachineProperties getProperties() {
@@ -252,7 +252,7 @@
       ImageReference imgRef = ImageReference.builder().publisher("publisher").offer("offer").sku("sku").version("ver").build();
       VHD vhd = VHD.create("https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd");
       List<DataDisk> dataDisks = new ArrayList<DataDisk>();
-      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null);
+      OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null, null, null);
       StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
       OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
             null);
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
index 6006392..754f5fe 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
@@ -32,21 +32,20 @@
 
 public class AzureLiveTestUtils {
 
-    public static Properties defaultProperties(Properties properties) {
-       properties = properties == null ? new Properties() : properties;
-       properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
-       properties.put(PROPERTY_REGIONS, "westeurope");
-       properties.put(IMAGE_PUBLISHERS, "Canonical");
-       properties.put(RESOURCENAME_PREFIX, "jcloudstest");
-       
-       String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
-       properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
-       properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
-       properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
-       properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
-       properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
-       
-       return properties;
-    }
-}
+   public static Properties defaultProperties(Properties properties, String resourceNamePrefix) {
+      properties = properties == null ? new Properties() : properties;
+      properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
+      properties.put(PROPERTY_REGIONS, "westeurope");
+      properties.put(IMAGE_PUBLISHERS, "Canonical");
+      properties.put(RESOURCENAME_PREFIX, resourceNamePrefix);
 
+      String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
+      properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
+      properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
+      properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
+
+      return properties;
+   }
+}
diff --git a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
index 0633294..cf65462 100644
--- a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
+++ b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/BaseAzureComputeApiLiveTest.java
@@ -38,10 +38,8 @@
 import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
 import org.jclouds.azurecompute.arm.domain.Provisionable;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
-import org.jclouds.azurecompute.arm.domain.StorageService;
 import org.jclouds.azurecompute.arm.domain.Subnet;
 import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
-import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
 import org.testng.annotations.AfterClass;
 
 import com.google.common.base.Predicate;
@@ -99,7 +97,7 @@
    @Override protected Properties setupProperties() {
       Properties properties = super.setupProperties();
       // for oauth
-      AzureLiveTestUtils.defaultProperties(properties);
+      AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
       checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
       return properties;
    }
@@ -139,23 +137,6 @@
       return subnet;
    }
 
-   protected StorageService createStorageService(final String resourceGroupName, final String storageServiceName, final String location) {
-      URI uri = api.getStorageAccountApi(resourceGroupName).create(storageServiceName, location, ImmutableMap.of("property_name",
-              "property_value"), ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
-      if (uri != null) {
-         assertTrue(uri.toString().contains("api-version"));
-
-         boolean jobDone = retry(new Predicate<URI>() {
-            @Override
-            public boolean apply(final URI uri) {
-               return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
-            }
-         }, 60 * 1 * 1000 /* 1 minute timeout */).apply(uri);
-         assertTrue(jobDone, "create operation did not complete in the configured timeout");
-      }
-      return api.getStorageAccountApi(resourceGroupName).get(storageServiceName);
-   }
-
    protected void createTestResourceGroup() {
       String name = String.format("rg-%s-%s", this.getClass().getSimpleName().toLowerCase(),
             System.getProperty("user.name"));
diff --git a/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json b/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json
new file mode 100644
index 0000000..865012f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/virtualmachineimagecreate.json
@@ -0,0 +1,21 @@
+{
+  "type": "Microsoft.Compute/images",
+  "location": "canadaeast",
+  "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/images/testVirtualMachineImage",
+  "name": "testVirtualMachineImage",
+  "properties": {
+    "sourceVirtualMachine": {
+      "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/virtualMachines/vm2image"
+    },
+    "storageProfile": {
+      "osDisk": {
+        "osType": "Linux",
+        "osState": "Generalized",
+        "blobUri": "https://jcloudstestcanadaeast982.blob.core.windows.net/vhds/vm2image20170315140332.vhd",
+        "caching": "ReadWrite"
+      },
+      "dataDisks": []
+    },
+    "provisioningState": "Succeeded"
+  }
+}
\ No newline at end of file
diff --git a/azurecompute-arm/src/test/resources/virtualmachineimageget.json b/azurecompute-arm/src/test/resources/virtualmachineimageget.json
new file mode 100644
index 0000000..865012f
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/virtualmachineimageget.json
@@ -0,0 +1,21 @@
+{
+  "type": "Microsoft.Compute/images",
+  "location": "canadaeast",
+  "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/images/testVirtualMachineImage",
+  "name": "testVirtualMachineImage",
+  "properties": {
+    "sourceVirtualMachine": {
+      "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/virtualMachines/vm2image"
+    },
+    "storageProfile": {
+      "osDisk": {
+        "osType": "Linux",
+        "osState": "Generalized",
+        "blobUri": "https://jcloudstestcanadaeast982.blob.core.windows.net/vhds/vm2image20170315140332.vhd",
+        "caching": "ReadWrite"
+      },
+      "dataDisks": []
+    },
+    "provisioningState": "Succeeded"
+  }
+}
\ No newline at end of file
diff --git a/azurecompute-arm/src/test/resources/virtualmachineimagelist.json b/azurecompute-arm/src/test/resources/virtualmachineimagelist.json
new file mode 100644
index 0000000..cf4d3ea
--- /dev/null
+++ b/azurecompute-arm/src/test/resources/virtualmachineimagelist.json
@@ -0,0 +1,25 @@
+{
+  "value": [
+    {
+      "type": "Microsoft.Compute/images",
+      "location": "canadaeast",
+      "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/images/imageFromRest",
+      "name": "testVirtualMachineImage",
+      "properties": {
+        "sourceVirtualMachine": {
+          "id": "/subscriptions/bd81406c-6028-4037-9f03-9a3af4ff725d/resourceGroups/jcloudstest-canadaeast/providers/Microsoft.Compute/virtualMachines/vm2image"
+        },
+        "storageProfile": {
+          "osDisk": {
+            "osType": "Linux",
+            "osState": "Generalized",
+            "blobUri": "https://jcloudstestcanadaeast982.blob.core.windows.net/vhds/vm2image20170315140332.vhd",
+            "caching": "ReadWrite"
+          },
+          "dataDisks": []
+        },
+        "provisioningState": "Succeeded"
+      }
+    }
+  ]
+}
\ No newline at end of file