Repository: jclouds-labs
Updated Branches:
  refs/heads/master 2f1103873 -> f58f96b18


Create one resource group in each region


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

Branch: refs/heads/master
Commit: f58f96b18829c6dcf584872487e0f0fe5e72208f
Parents: 2f11038
Author: Ignasi Barrera <n...@apache.org>
Authored: Fri Oct 14 17:51:42 2016 +0200
Committer: Ignasi Barrera <n...@apache.org>
Committed: Mon Oct 17 13:24:57 2016 +0200

----------------------------------------------------------------------
 .../arm/AzureComputeProviderMetadata.java       |   6 +-
 .../arm/compute/AzureComputeServiceAdapter.java | 270 ++++++++++---------
 .../AzureComputeServiceContextModule.java       | 110 ++++----
 .../extensions/AzureComputeImageExtension.java  |  41 +--
 .../functions/LocationToResourceGroupName.java  |  46 ++++
 .../ResourceDefinitionToCustomImage.java        |  15 +-
 .../functions/VirtualMachineToNodeMetadata.java |  16 +-
 .../CreateResourceGroupThenCreateNodes.java     |  12 +-
 .../arm/config/AzureComputeProperties.java      |   2 -
 .../azurecompute/arm/domain/RegionAndId.java    |  50 ++++
 .../arm/functions/CleanupResources.java         |  38 +--
 .../compute/AzureComputeServiceLiveTest.java    |  23 +-
 .../compute/AzureTemplateBuilderLiveTest.java   |  14 +-
 .../AzureComputeImageExtensionLiveTest.java     |  23 +-
 .../arm/internal/AzureLiveTestUtils.java        |  25 +-
 15 files changed, 387 insertions(+), 304 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java
index a434079..beac925 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
@@ -25,12 +25,13 @@ import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_P
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
 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.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;
@@ -88,9 +89,10 @@ public class AzureComputeProviderMetadata extends 
BaseProviderMetadata {
       properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
       properties.put(RESOURCE, "https://management.azure.com/";);
       properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
-      properties.put(RESOURCE_GROUP_NAME, "jclouds");
       properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16");
       properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24");
+      properties.put(RESOURCENAME_PREFIX, "jclouds");
+      properties.put(RESOURCENAME_DELIMITER, "-");
       properties.put(DEFAULT_DATADISKSIZE, "100");
       properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat");
       // Default credentials for all images

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java
index 0e2ed64..434c92f 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
@@ -30,11 +30,12 @@ import java.util.List;
 import java.util.Set;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
+import 
org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.DataDisk;
 import org.jclouds.azurecompute.arm.domain.HardwareProfile;
@@ -51,6 +52,8 @@ import org.jclouds.azurecompute.arm.domain.OSProfile;
 import org.jclouds.azurecompute.arm.domain.Offer;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
 import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
+import org.jclouds.azurecompute.arm.domain.RegionAndId;
+import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
 import org.jclouds.azurecompute.arm.domain.SKU;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
@@ -86,63 +89,67 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
 /**
- * Defines the connection between the {@link AzureComputeApi} implementation 
and the jclouds
- * {@link org.jclouds.compute.ComputeService}.
+ * Defines the connection between the {@link AzureComputeApi} implementation 
and
+ * the jclouds {@link org.jclouds.compute.ComputeService}.
  */
 @Singleton
 public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {
 
-   private final String azureGroup;
    private final CleanupResources cleanupResources;
    private final AzureComputeApi api;
    private final AzureComputeConstants azureComputeConstants;
    private final Supplier<Set<String>> regionIds;
-   private final Predicate<String> publicIpAvailable;
+   private final PublicIpAvailablePredicateFactory publicIpAvailable;
+   private final LocationToResourceGroupName locationToResourceGroupName;
 
    @Inject
    AzureComputeServiceAdapter(final AzureComputeApi api, final 
AzureComputeConstants azureComputeConstants,
          CleanupResources cleanupResources, @Region Supplier<Set<String>> 
regionIds,
-         @Named("PublicIpAvailable") Predicate<String> publicIpAvailable) {
+         PublicIpAvailablePredicateFactory publicIpAvailable, 
LocationToResourceGroupName locationToResourceGroupName) {
       this.api = api;
       this.azureComputeConstants = azureComputeConstants;
-      this.azureGroup = azureComputeConstants.azureResourceGroup();
       this.cleanupResources = cleanupResources;
       this.regionIds = regionIds;
       this.publicIpAvailable = publicIpAvailable;
+      this.locationToResourceGroupName = locationToResourceGroupName;
    }
 
    @Override
-   public NodeAndInitialCredentials<VirtualMachine> 
createNodeWithGroupEncodedIntoName(
-           final String group, final String name, final Template template) {
+   public NodeAndInitialCredentials<VirtualMachine> 
createNodeWithGroupEncodedIntoName(final String group,
+         final String name, final Template template) {
 
       AzureTemplateOptions templateOptions = 
template.getOptions().as(AzureTemplateOptions.class);
+      String azureGroup = 
locationToResourceGroupName.apply(template.getLocation().getId());
 
-      // TODO Store group apart from the name to be able to identify nodes 
with custom names in the configured group
+      // TODO Store group apart from the name to be able to identify nodes with
+      // custom names in the configured group
       // TODO ARM specific options
       // TODO user metadata and tags
       // TODO network ids => create one nic in each network
       // TODO inbound ports
-      
+
       String locationName = template.getLocation().getId();
       String subnetId = templateOptions.getSubnetId();
-      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, 
locationName); 
+      NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, 
locationName, azureGroup);
       StorageProfile storageProfile = createStorageProfile(name, 
template.getImage(), templateOptions.getBlob());
       HardwareProfile hardwareProfile = 
HardwareProfile.builder().vmSize(template.getHardware().getId()).build();
       OSProfile osProfile = createOsProfile(name, template);
-      NetworkProfile networkProfile = 
NetworkProfile.builder().networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build();
+      NetworkProfile networkProfile = NetworkProfile.builder()
+            
.networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build();
       VirtualMachineProperties virtualMachineProperties = 
VirtualMachineProperties.builder()
-              .licenseType(null) // TODO
-              .availabilitySet(null) // TODO
-              .hardwareProfile(hardwareProfile)
-              .storageProfile(storageProfile)
-              .osProfile(osProfile)
-              .networkProfile(networkProfile)
-              .build();
-
-      VirtualMachine virtualMachine = 
api.getVirtualMachineApi(azureGroup).create(name, 
template.getLocation().getId(), virtualMachineProperties);
-
-      // Safe to pass null credentials here, as jclouds will default populate 
the node with the default credentials from the image, or the ones in the 
options, if provided.
-      return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, 
name, null);
+            .licenseType(null) // TODO
+            .availabilitySet(null) // TODO
+            
.hardwareProfile(hardwareProfile).storageProfile(storageProfile).osProfile(osProfile)
+            .networkProfile(networkProfile).build();
+
+      VirtualMachine virtualMachine = 
api.getVirtualMachineApi(azureGroup).create(name, 
template.getLocation().getId(),
+            virtualMachineProperties);
+
+      // Safe to pass null credentials here, as jclouds will default populate
+      // the node with the default credentials from the image, or the ones in
+      // the options, if provided.
+      RegionAndId regionAndId = 
RegionAndId.fromRegionAndId(template.getLocation().getId(), name);
+      return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, 
regionAndId.slashEncode(), null);
    }
 
    @Override
@@ -150,16 +157,11 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
       final List<VMHardware> hwProfiles = Lists.newArrayList();
       for (Location location : listLocations()) {
          Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
-         for (VMSize vmSize : vmSizes){
-            VMHardware hwProfile = VMHardware.create(
-                    vmSize.name(),
-                    vmSize.numberOfCores(),
-                    vmSize.osDiskSizeInMB(),
-                    vmSize.resourceDiskSizeInMB(),
-                    vmSize.memoryInMB(),
-                    vmSize.maxDataDiskCount(),
-                    location.name(),
-                    false);
+         for (VMSize vmSize : vmSizes) {
+            VMHardware hwProfile = VMHardware
+                  .create(vmSize.name(), vmSize.numberOfCores(), 
vmSize.osDiskSizeInMB(),
+                        vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), 
vmSize.maxDataDiskCount(), location.name(),
+                        false);
             hwProfiles.add(hwProfile);
          }
       }
@@ -188,7 +190,8 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
 
    private List<VMImage> listImagesByLocation(String location) {
       final List<VMImage> osImages = Lists.newArrayList();
-      Iterable<String> publishers = 
Splitter.on(',').trimResults().omitEmptyStrings().split(this.azureComputeConstants.azureImagePublishers());
+      Iterable<String> publishers = 
Splitter.on(',').trimResults().omitEmptyStrings()
+            .split(this.azureComputeConstants.azureImagePublishers());
       for (String publisher : publishers) {
          osImages.addAll(getImagesFromPublisher(publisher, location));
       }
@@ -199,42 +202,50 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
    public Iterable<VMImage> listImages() {
       final List<VMImage> osImages = Lists.newArrayList();
 
-      for (Location location : listLocations()){
+      for (Location location : listLocations()) {
          osImages.addAll(listImagesByLocation(location.name()));
       }
+
       // list custom images
-      List<StorageService> storages = 
api.getStorageAccountApi(azureGroup).list();
-      for (StorageService storage : storages) {
-         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);
+      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
+         String azureGroup = resourceGroup.name();
+         List<StorageService> storages = 
api.getStorageAccountApi(azureGroup).list();
+
+         for (StorageService storage : storages) {
+            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);
+               }
             }
          }
       }
-      
+
       return osImages;
    }
 
    @Override
    public VMImage getImage(final String id) {
       VMImage image = decodeFieldsFromUniqueId(id);
+      String azureGroup = locationToResourceGroupName.apply(image.location());
+
       if (image.custom()) {
          VMImage customImage = null;
          StorageServiceKeys keys = 
api.getStorageAccountApi(azureGroup).getKeys(image.storage());
          if (keys == null) {
-            // If the storage account for the image does not exist, it means 
the image was deleted
+            // 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()) {
@@ -270,40 +281,38 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
    @Override
    public Iterable<Location> listLocations() {
       final Iterable<String> vmLocations = 
FluentIterable.from(api.getResourceProviderApi().get("Microsoft.Compute"))
-              .filter(new Predicate<ResourceProviderMetaData>() {
-                 @Override
-                 public boolean apply(ResourceProviderMetaData input) {
-                    return input.resourceType().equals("virtualMachines");
-                 }
-              })
-              .transformAndConcat(new Function<ResourceProviderMetaData, 
Iterable<String>>() {
-                 @Override
-                 public Iterable<String> apply(ResourceProviderMetaData 
resourceProviderMetaData) {
-                    return resourceProviderMetaData.locations();
-                 }
-              });
-
-      List<Location> locations = 
FluentIterable.from(api.getLocationApi().list())
-              .filter(new Predicate<Location>() {
-                 @Override
-                 public boolean apply(Location location) {
-                    return Iterables.contains(vmLocations, 
location.displayName());
-                 }
-              })
-              .filter(new Predicate<Location>() {
-                 @Override
-                 public boolean apply(Location location) {
-                    return regionIds.get().isEmpty() ? true : 
regionIds.get().contains(location.name());
-                 }
-              })
-              .toList();
+            .filter(new Predicate<ResourceProviderMetaData>() {
+               @Override
+               public boolean apply(ResourceProviderMetaData input) {
+                  return input.resourceType().equals("virtualMachines");
+               }
+            }).transformAndConcat(new Function<ResourceProviderMetaData, 
Iterable<String>>() {
+               @Override
+               public Iterable<String> apply(ResourceProviderMetaData 
resourceProviderMetaData) {
+                  return resourceProviderMetaData.locations();
+               }
+            });
+
+      List<Location> locations = 
FluentIterable.from(api.getLocationApi().list()).filter(new 
Predicate<Location>() {
+         @Override
+         public boolean apply(Location location) {
+            return Iterables.contains(vmLocations, location.displayName());
+         }
+      }).filter(new Predicate<Location>() {
+         @Override
+         public boolean apply(Location location) {
+            return regionIds.get().isEmpty() ? true : 
regionIds.get().contains(location.name());
+         }
+      }).toList();
 
       return locations;
    }
 
    @Override
    public VirtualMachine getNode(final String id) {
-      return api.getVirtualMachineApi(azureGroup).get(id);
+      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+      String azureGroup = 
locationToResourceGroupName.apply(regionAndId.region());
+      return api.getVirtualMachineApi(azureGroup).get(regionAndId.id());
    }
 
    @Override
@@ -313,22 +322,32 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
 
    @Override
    public void rebootNode(final String id) {
-      api.getVirtualMachineApi(azureGroup).restart(id);
+      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+      String azureGroup = 
locationToResourceGroupName.apply(regionAndId.region());
+      api.getVirtualMachineApi(azureGroup).restart(regionAndId.id());
    }
 
    @Override
    public void resumeNode(final String id) {
-      api.getVirtualMachineApi(azureGroup).start(id);
+      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+      String azureGroup = 
locationToResourceGroupName.apply(regionAndId.region());
+      api.getVirtualMachineApi(azureGroup).start(regionAndId.id());
    }
 
    @Override
    public void suspendNode(final String id) {
-      api.getVirtualMachineApi(azureGroup).stop(id);
+      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+      String azureGroup = 
locationToResourceGroupName.apply(regionAndId.region());
+      api.getVirtualMachineApi(azureGroup).stop(regionAndId.id());
    }
 
    @Override
    public Iterable<VirtualMachine> listNodes() {
-      return api.getVirtualMachineApi(azureGroup).list();
+      ImmutableList.Builder<VirtualMachine> nodes = ImmutableList.builder();
+      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
+         nodes.addAll(api.getVirtualMachineApi(resourceGroup.name()).list());
+      }
+      return nodes.build();
    }
 
    @Override
@@ -341,59 +360,54 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
       });
    }
 
-
    private OSProfile createOsProfile(String computerName, Template template) {
       String defaultLoginUser = 
template.getImage().getDefaultCredentials().getUser();
       String defaultLoginPassword = 
template.getImage().getDefaultCredentials().getOptionalPassword().get();
       String adminUsername = 
Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
       String adminPassword = 
Objects.firstNonNull(template.getOptions().getLoginPassword(), 
defaultLoginPassword);
-      OSProfile.Builder builder = 
OSProfile.builder().adminUsername(adminUsername).computerName(computerName);
-      // prefer public key over password
-      if (template.getOptions().getPublicKey() != null) {
+      OSProfile.Builder builder = 
OSProfile.builder().adminUsername(adminUsername).adminPassword(adminPassword)
+            .computerName(computerName);
+
+      if (template.getOptions().getPublicKey() != null
+            && OsFamily.WINDOWS != 
template.getImage().getOperatingSystem().getFamily()) {
          OSProfile.LinuxConfiguration linuxConfiguration = 
OSProfile.LinuxConfiguration.create("true",
-                 OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of(
-                         OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
-                                 
String.format("/home/%s/.ssh/authorized_keys", adminUsername),
-                                 template.getOptions().getPublicKey())
-                 ))
-         );
+               
OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of(OSProfile.LinuxConfiguration.SSH.SSHPublicKey
+                     .create(String.format("/home/%s/.ssh/authorized_keys", 
adminUsername), template.getOptions()
+                           .getPublicKey()))));
          builder.linuxConfiguration(linuxConfiguration);
-      } else {
-         builder.adminPassword(adminPassword);
       }
+
       return builder.build();
    }
 
-   private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, 
String name, String locationName) {
+   private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, 
String name, String locationName,
+         String azureGroup) {
       final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup);
 
-      PublicIPAddressProperties properties =
-              PublicIPAddressProperties.builder()
-                      .publicIPAllocationMethod("Static")
-                      .idleTimeoutInMinutes(4)
-                      .build();
+      PublicIPAddressProperties properties = 
PublicIPAddressProperties.builder().publicIPAllocationMethod("Static")
+            .idleTimeoutInMinutes(4).build();
 
       String publicIpAddressName = "public-address-" + name;
-      PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, 
locationName, ImmutableMap.of("jclouds", name), properties);
-      
-      checkState(publicIpAvailable.apply(publicIpAddressName),
+      PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, 
locationName, ImmutableMap.of("jclouds", name),
+            properties);
+
+      
checkState(publicIpAvailable.create(azureGroup).apply(publicIpAddressName),
             "Public IP was not provisioned in the configured timeout");
 
-      final NetworkInterfaceCardProperties networkInterfaceCardProperties =
-              NetworkInterfaceCardProperties.builder()
-                      .ipConfigurations(ImmutableList.of(
-                              IpConfiguration.builder()
-                                      .name("ipConfig-" + name)
-                                      
.properties(IpConfigurationProperties.builder()
-                                              
.privateIPAllocationMethod("Dynamic")
-                                              
.publicIPAddress(IdReference.create(ip.id()))
-                                              
.subnet(IdReference.create(subnetId))
-                                              .build())
-                                      .build()))
-                      .build();
+      final NetworkInterfaceCardProperties networkInterfaceCardProperties = 
NetworkInterfaceCardProperties
+            .builder()
+            .ipConfigurations(
+                  ImmutableList.of(IpConfiguration
+                        .builder()
+                        .name("ipConfig-" + name)
+                        .properties(
+                              
IpConfigurationProperties.builder().privateIPAllocationMethod("Dynamic")
+                                    
.publicIPAddress(IdReference.create(ip.id())).subnet(IdReference.create(subnetId))
+                                    .build()).build())).build();
 
       String networkInterfaceCardName = "jc-nic-" + name;
-      return 
api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName,
 locationName, networkInterfaceCardProperties, ImmutableMap.of("jclouds", 
name));
+      return 
api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName,
 locationName,
+            networkInterfaceCardProperties, ImmutableMap.of("jclouds", name));
    }
 
    private StorageProfile createStorageProfile(String name, Image image, 
String blob) {
@@ -401,14 +415,10 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
       ImageReference imageReference = null;
       VHD sourceImage = null;
       String osType = null;
-      
+
       if (!imageRef.custom()) {
-         imageReference = ImageReference.builder()
-               .publisher(image.getProviderId())
-               .offer(image.getName())
-               .sku(image.getVersion())
-               .version("latest")
-               .build();
+         imageReference = 
ImageReference.builder().publisher(image.getProviderId()).offer(image.getName())
+               .sku(image.getVersion()).version("latest").build();
       } else {
          sourceImage = VHD.create(image.getProviderId());
 
@@ -416,10 +426,10 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Virtual
          OsFamily osFamily = image.getOperatingSystem().getFamily();
          osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
       }
-      
+
       VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd");
       OSDisk osDisk = OSDisk.create(osType, name, vhd, "ReadWrite", 
"FromImage", sourceImage);
-      
-      return StorageProfile.create(imageReference, osDisk, 
ImmutableList.<DataDisk>of());
+
+      return StorageProfile.create(imageReference, osDisk, 
ImmutableList.<DataDisk> of());
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java
index 24f02ea..34a5160 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
@@ -24,7 +24,6 @@ import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_P
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
 import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
@@ -137,10 +136,6 @@ public class AzureComputeServiceContextModule
       @Inject
       private String tcpRuleRegexpProperty;
 
-      @Named(RESOURCE_GROUP_NAME)
-      @Inject
-      private String azureResourceGroupProperty;
-
       @Named(IMAGE_PUBLISHERS)
       @Inject
       private String azureImagePublishersProperty;
@@ -161,10 +156,6 @@ public class AzureComputeServiceContextModule
          return Long.parseLong(operationTimeoutProperty);
       }
 
-      public String azureResourceGroup() {
-         return azureResourceGroupProperty;
-      }
-
       public String azureImagePublishers() {
          return azureImagePublishersProperty;
       }
@@ -199,11 +190,11 @@ public class AzureComputeServiceContextModule
    }
 
    @Provides
-   @com.google.inject.name.Named(TIMEOUT_NODE_RUNNING)
-   protected Predicate<String> provideVirtualMachineRunningPredicate(final 
AzureComputeApi api, final 
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, 
Timeouts timeouts, PollPeriod pollPeriod) {
-      String azureGroup = azureComputeConstants.azureResourceGroup();
-      return retry(new VirtualMachineInStatePredicate(api, azureGroup, 
PowerState.RUNNING), timeouts.nodeRunning,
-              pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+   @Named(TIMEOUT_NODE_RUNNING)
+   protected VirtualMachineInStatePredicateFactory 
provideVirtualMachineRunningPredicate(final AzureComputeApi api,
+         Timeouts timeouts, PollPeriod pollPeriod) {
+      return new VirtualMachineInStatePredicateFactory(api, 
PowerState.RUNNING, timeouts.nodeRunning,
+            pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
    }
    
    @Provides
@@ -229,19 +220,17 @@ public class AzureComputeServiceContextModule
 
    @Provides
    @Named(TIMEOUT_NODE_SUSPENDED)
-   protected Predicate<String> provideNodeSuspendedPredicate(final 
AzureComputeApi api, final 
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
-                                                             Timeouts 
timeouts, PollPeriod pollPeriod) {
-      String azureGroup = azureComputeConstants.azureResourceGroup();
-      return retry(new VirtualMachineInStatePredicate(api, azureGroup, 
PowerState.STOPPED), timeouts.nodeTerminated,
-              pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+   protected VirtualMachineInStatePredicateFactory 
provideNodeSuspendedPredicate(final AzureComputeApi api,
+         Timeouts timeouts, PollPeriod pollPeriod) {
+      return new VirtualMachineInStatePredicateFactory(api, 
PowerState.STOPPED, timeouts.nodeTerminated,
+            pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
    }
    
    @Provides
-   @Named("PublicIpAvailable")
-   protected Predicate<String> providePublicIpAvailablePredicate(final 
AzureComputeApi api, final 
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
-                                                             Timeouts 
timeouts, PollPeriod pollPeriod) {
-      String azureGroup = azureComputeConstants.azureResourceGroup();
-      return retry(new PublicIpAvailablePredicate(api, azureGroup), 
azureComputeConstants.operationTimeout(),
+   protected PublicIpAvailablePredicateFactory 
providePublicIpAvailablePredicate(final AzureComputeApi api,
+         final AzureComputeServiceContextModule.AzureComputeConstants 
azureComputeConstants, Timeouts timeouts,
+         PollPeriod pollPeriod) {
+      return new PublicIpAvailablePredicateFactory(api, 
azureComputeConstants.operationTimeout(),
             azureComputeConstants.operationPollInitialPeriod(), 
azureComputeConstants.operationPollMaxPeriod());
    }
 
@@ -280,45 +269,62 @@ public class AzureComputeServiceContextModule
       }
    }
 
-   @VisibleForTesting
-   static class VirtualMachineInStatePredicate implements Predicate<String> {
+   public static class VirtualMachineInStatePredicateFactory {
 
       private final AzureComputeApi api;
-      private final String azureGroup;
       private final PowerState powerState;
-
-      public VirtualMachineInStatePredicate(AzureComputeApi api, String 
azureGroup, PowerState powerState) {
-         this.api = checkNotNull(api, "api must not be null");
-         this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be 
null");
-         this.powerState = checkNotNull(powerState, "powerState must not be 
null");
+      private final long timeout;
+      private final long period;
+      private final long maxPeriod;
+
+      VirtualMachineInStatePredicateFactory(AzureComputeApi api, PowerState 
powerState, long timeout,
+            long period, long maxPeriod) {
+         this.api = checkNotNull(api, "api cannot be null");
+         this.powerState = checkNotNull(powerState, "powerState cannot be 
null");
+         this.timeout = timeout;
+         this.period = period;
+         this.maxPeriod = maxPeriod;
       }
 
-      @Override
-      public boolean apply(String name) {
-         checkNotNull(name, "name cannot be null");
-         VirtualMachineInstance vmInstance = 
api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name);
-         if (vmInstance == null) return false;
-         return powerState == vmInstance.powerState();
+      public Predicate<String> create(final String azureGroup) {
+         return retry(new Predicate<String>() {
+            @Override
+            public boolean apply(String name) {
+               checkNotNull(name, "name cannot be null");
+               VirtualMachineInstance vmInstance = 
api.getVirtualMachineApi(azureGroup).getInstanceDetails(name);
+               if (vmInstance == null)
+                  return false;
+               return powerState == vmInstance.powerState();
+            }
+         }, timeout, period, maxPeriod);
       }
    }
    
-   @VisibleForTesting
-   static class PublicIpAvailablePredicate implements Predicate<String> {
+   public static class PublicIpAvailablePredicateFactory {
 
       private final AzureComputeApi api;
-      private final String azureGroup;
-
-      public PublicIpAvailablePredicate(AzureComputeApi api, String 
azureGroup) {
-         this.api = checkNotNull(api, "api must not be null");
-         this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be 
null");
+      private final long timeout;
+      private final long period;
+      private final long maxPeriod;
+
+      PublicIpAvailablePredicateFactory(AzureComputeApi api, long timeout,
+            long period, long maxPeriod) {
+         this.api = checkNotNull(api, "api cannot be null");
+         this.timeout = timeout;
+         this.period = period;
+         this.maxPeriod = maxPeriod;
       }
-
-      @Override
-      public boolean apply(String name) {
-         checkNotNull(name, "name cannot be null");
-         PublicIPAddress publicIp = 
api.getPublicIPAddressApi(azureGroup).get(name);
-         if (publicIp == null) return false;
-         return 
publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded");
+      
+      public Predicate<String> create(final String azureGroup) {
+         return retry(new Predicate<String>() {
+            @Override
+            public boolean apply(String name) {
+               checkNotNull(name, "name cannot be null");
+               PublicIPAddress publicIp = 
api.getPublicIPAddressApi(azureGroup).get(name);
+               if (publicIp == null) return false;
+               return 
publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded");
+            }
+         }, timeout, period, maxPeriod);
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java
index 99c9c6c..1e57899 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
@@ -31,8 +31,10 @@ import javax.annotation.Resource;
 
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
+import 
org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName;
 import 
org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
+import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMImage;
@@ -61,27 +63,27 @@ public class AzureComputeImageExtension implements 
ImageExtension {
    protected Logger logger = Logger.NULL;
 
    private final AzureComputeApi api;
-   private final String group;
    private final ListeningExecutorService userExecutor;
    private final Predicate<URI> imageAvailablePredicate;
-   private final Predicate<String> nodeSuspendedPredicate;
+   private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate;
    private final ResourceDefinitionToCustomImage.Factory 
resourceDefinitionToImage;
    private final CleanupResources cleanupResources;
+   private final LocationToResourceGroupName locationToResourceGroupName;
 
    @Inject
    AzureComputeImageExtension(AzureComputeApi api,
          @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> 
imageAvailablePredicate,
-         @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> 
nodeSuspendedPredicate,
-         AzureComputeConstants azureComputeConstants,
+         @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory 
nodeSuspendedPredicate,
          @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService 
userExecutor,
-         ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, 
CleanupResources cleanupResources) {
+         ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, 
CleanupResources cleanupResources,
+         LocationToResourceGroupName locationToResourceGroupName) {
       this.api = api;
       this.imageAvailablePredicate = imageAvailablePredicate;
       this.nodeSuspendedPredicate = nodeSuspendedPredicate;
-      this.group = azureComputeConstants.azureResourceGroup();
       this.userExecutor = userExecutor;
       this.resourceDefinitionToImage = resourceDefinitionToImage;
       this.cleanupResources = cleanupResources;
+      this.locationToResourceGroupName = locationToResourceGroupName;
    }
 
    @Override
@@ -92,21 +94,23 @@ public class AzureComputeImageExtension implements 
ImageExtension {
    @Override
    public ListenableFuture<Image> createImage(ImageTemplate template) {
       final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
-      final String id = cloneTemplate.getSourceNodeId();
-      final String name = cloneTemplate.getName();
+      
+      final RegionAndId regionAndId = 
RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId());
+      final String group = 
locationToResourceGroupName.apply(regionAndId.region());
 
-      logger.debug(">> stopping node %s...", id);
-      api.getVirtualMachineApi(group).stop(id);
-      checkState(nodeSuspendedPredicate.apply(id), "Node %s was not suspended 
within the configured time limit", id);
+      logger.debug(">> stopping node %s...", regionAndId.slashEncode());
+      api.getVirtualMachineApi(group).stop(regionAndId.id());
+      checkState(nodeSuspendedPredicate.create(group).apply(regionAndId.id()),
+            "Node %s was not suspended within the configured time limit", 
regionAndId.slashEncode());
 
       return userExecutor.submit(new Callable<Image>() {
          @Override
          public Image call() throws Exception {
-            logger.debug(">> generalizing virtal machine %s...", id);
-            api.getVirtualMachineApi(group).generalize(id);
+            logger.debug(">> generalizing virtal machine %s...", 
regionAndId.id());
+            api.getVirtualMachineApi(group).generalize(regionAndId.id());
 
-            logger.debug(">> capturing virtual machine %s to container %s...", 
id, CONTAINER_NAME);
-            URI uri = api.getVirtualMachineApi(group).capture(id, 
cloneTemplate.getName(), CONTAINER_NAME);
+            logger.debug(">> capturing virtual machine %s to container %s...", 
regionAndId.id(), CONTAINER_NAME);
+            URI uri = 
api.getVirtualMachineApi(group).capture(regionAndId.id(), 
cloneTemplate.getName(), CONTAINER_NAME);
             checkState(uri != null && imageAvailablePredicate.apply(uri),
                   "Image %s was not created within the configured time limit", 
cloneTemplate.getName());
 
@@ -114,7 +118,8 @@ public class AzureComputeImageExtension implements 
ImageExtension {
             checkState(definitions.size() == 1,
                   "Expected one resource definition after creating the image 
but %s were returned", definitions.size());
 
-            Image image = resourceDefinitionToImage.create(id, 
name).apply(definitions.get(0));
+            Image image = 
resourceDefinitionToImage.create(cloneTemplate.getSourceNodeId(), 
cloneTemplate.getName())
+                  .apply(definitions.get(0));
             logger.debug(">> created %s", image);
             return image;
          }
@@ -130,7 +135,7 @@ public class AzureComputeImageExtension implements 
ImageExtension {
 
       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

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java
new file mode 100644
index 0000000..c97850a
--- /dev/null
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java
@@ -0,0 +1,46 @@
+/*
+ * 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.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import com.google.common.base.Function;
+
+/**
+ * Returns the name of the resource group for the current location.
+ */
+public class LocationToResourceGroupName implements Function<String, String> {
+
+   private final String prefix;
+   private final char delimiter;
+
+   @Inject
+   LocationToResourceGroupName(@Named(RESOURCENAME_PREFIX) String prefix, 
@Named(RESOURCENAME_DELIMITER) char delimiter) {
+      this.prefix = prefix;
+      this.delimiter = delimiter;
+   }
+
+   @Override
+   public String apply(String input) {
+      return String.format("%s%s%s", prefix, delimiter, input);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java
index cce6b50..02fb0f4 100644
--- 
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
@@ -23,7 +23,7 @@ import java.util.Map;
 import javax.inject.Inject;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
-import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
 import org.jclouds.azurecompute.arm.domain.VMImage;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
@@ -39,21 +39,24 @@ public class ResourceDefinitionToCustomImage implements 
Function<ResourceDefinit
       ResourceDefinitionToCustomImage create(@Assisted("nodeId") String 
nodeId, @Assisted("imageName") String imageName);
    }
 
-   private final String resourceGroup;
    private final Function<VMImage, Image> vmImageToImage;
    private final String imageName;
    private final String storageAccountName;
    private final VirtualMachine vm;
+   private final String resourceGroup;
 
    @Inject
-   ResourceDefinitionToCustomImage(AzureComputeApi api, AzureComputeConstants 
azureComputeConstants,
+   ResourceDefinitionToCustomImage(AzureComputeApi api,
          StorageProfileToStorageAccountName storageProfileToStorageAccountName,
-         Function<VMImage, Image> vmImageToImage, @Assisted("nodeId") String 
nodeId,
+         Function<VMImage, Image> vmImageToImage, LocationToResourceGroupName 
locationToResourceGroupName,
+         @Assisted("nodeId") String nodeId,
          @Assisted("imageName") String imageName) {
       this.vmImageToImage = vmImageToImage;
-      this.resourceGroup = azureComputeConstants.azureResourceGroup();
       this.imageName = imageName;
-      this.vm = api.getVirtualMachineApi(resourceGroup).get(nodeId);
+      
+      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId);
+      this.resourceGroup = 
locationToResourceGroupName.apply(regionAndId.region());
+      this.vm = 
api.getVirtualMachineApi(this.resourceGroup).get(regionAndId.id());
       this.storageAccountName = 
storageProfileToStorageAccountName.apply(vm.properties().storageProfile());
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java
index e151a4a..1f90870 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
@@ -38,6 +38,7 @@ import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextMod
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
+import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.StorageProfile;
 import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VMImage;
@@ -110,7 +111,6 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
                      .put(PowerState.UNRECOGNIZED, 
NodeMetadata.Status.UNRECOGNIZED).build(),
                NodeMetadata.Status.UNRECOGNIZED);
 
-   private final String azureGroup;
    private final AzureComputeApi api;
    private final GroupNamingConvention nodeNamingConvention;
    private final Supplier<Map<String, ? extends Image>> images;
@@ -119,28 +119,32 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
    private final Map<String, Credentials> credentialStore;
    private final Function<VMImage, Image> vmImageToImge;
    private final StorageProfileToStorageAccountName 
storageProfileToStorageAccountName;
+   private final LocationToResourceGroupName locationToResourceGroupName;
 
    @Inject
    VirtualMachineToNodeMetadata(AzureComputeApi api, 
GroupNamingConvention.Factory namingConvention,
          Supplier<Map<String, ? extends Image>> images, Supplier<Map<String, ? 
extends Hardware>> hardwares,
          @Memoized Supplier<Set<? extends Location>> locations, Map<String, 
Credentials> credentialStore,
          final AzureComputeConstants azureComputeConstants, Function<VMImage, 
Image> vmImageToImge,
-         StorageProfileToStorageAccountName 
storageProfileToStorageAccountName) {
+         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
+         LocationToResourceGroupName locationToResourceGroupName) {
       this.api = api;
       this.nodeNamingConvention = namingConvention.createWithoutPrefix();
       this.images = checkNotNull(images, "images cannot be null");
       this.locations = checkNotNull(locations, "locations cannot be null");
       this.hardwares = checkNotNull(hardwares, "hardwares cannot be null");
       this.credentialStore = credentialStore;
-      this.azureGroup = azureComputeConstants.azureResourceGroup();
       this.vmImageToImge = vmImageToImge;
       this.storageProfileToStorageAccountName = 
storageProfileToStorageAccountName;
+      this.locationToResourceGroupName = locationToResourceGroupName;
    }
 
    @Override
    public NodeMetadata apply(VirtualMachine virtualMachine) {
+      String azureGroup = 
locationToResourceGroupName.apply(virtualMachine.location());
+      
       NodeMetadataBuilder builder = new NodeMetadataBuilder();
-      builder.id(virtualMachine.name());
+      builder.id(RegionAndId.fromRegionAndId(virtualMachine.location(), 
virtualMachine.name()).slashEncode());
       builder.providerId(virtualMachine.id());
       builder.name(virtualMachine.name());
       builder.hostname(virtualMachine.name());
@@ -180,7 +184,7 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
       String locationName = virtualMachine.location();
       builder.location(getLocation(locationName));
 
-      Optional<? extends Image> image = 
findImage(virtualMachine.properties().storageProfile(), locationName);
+      Optional<? extends Image> image = 
findImage(virtualMachine.properties().storageProfile(), locationName, 
azureGroup);
       if (image.isPresent()) {
          builder.imageId(image.get().getId());
          builder.operatingSystem(image.get().getOperatingSystem());
@@ -239,7 +243,7 @@ public class VirtualMachineToNodeMetadata implements 
Function<VirtualMachine, No
       }, null);
    }
 
-   protected Optional<? extends Image> findImage(final StorageProfile 
storageProfile, String locatioName) {
+   protected Optional<? extends Image> findImage(final StorageProfile 
storageProfile, String locatioName, String azureGroup) {
       if (storageProfile.imageReference() != null) {
          return Optional.fromNullable(images.get().get(
                encodeFieldsToUniqueId(false, locatioName, 
storageProfile.imageReference())));

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
index 99528fd..024204b 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java
@@ -35,6 +35,7 @@ import javax.inject.Singleton;
 import org.jclouds.Constants;
 import org.jclouds.azurecompute.arm.AzureComputeApi;
 import 
org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
+import 
org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName;
 import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
 import org.jclouds.azurecompute.arm.domain.ResourceGroup;
 import org.jclouds.azurecompute.arm.domain.StorageService;
@@ -73,20 +74,23 @@ public class CreateResourceGroupThenCreateNodes extends 
CreateNodesWithGroupEnco
 
    private final AzureComputeApi api;
    private final AzureComputeServiceContextModule.AzureComputeConstants 
azureComputeConstants;
+   private final LocationToResourceGroupName locationToResourceGroupName;
 
    @Inject
    protected CreateResourceGroupThenCreateNodes(
            CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
            ListNodesStrategy listNodesStrategy,
            GroupNamingConvention.Factory namingConvention,
-           @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService 
userExecutor,
-           CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory 
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
-           AzureComputeApi api, 
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
+         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService 
userExecutor,
+         CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory 
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
+         AzureComputeApi api, 
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
+         LocationToResourceGroupName locationToResourceGroupName) {
       super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, 
userExecutor,
               customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
       this.api = checkNotNull(api, "api cannot be null");
       checkNotNull(userExecutor, "userExecutor cannot be null");
       this.azureComputeConstants = azureComputeConstants;
+      this.locationToResourceGroupName = locationToResourceGroupName;
    }
 
    @Override
@@ -100,7 +104,7 @@ public class CreateResourceGroupThenCreateNodes extends 
CreateNodesWithGroupEnco
          logger.warn(">> a runScript was configured but no SSH key has been 
provided. " +
                  "Authentication will delegate to the ssh-agent");
       }
-      String azureGroupName = this.azureComputeConstants.azureResourceGroup();
+      String azureGroupName = 
locationToResourceGroupName.apply(template.getLocation().getId());
 
       AzureTemplateOptions options = 
template.getOptions().as(AzureTemplateOptions.class);
       // create resource group for jclouds group if it does not already exist

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
index 8f945d9..2a15e4b 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java
@@ -34,8 +34,6 @@ public class AzureComputeProperties {
 
    public static final String TCP_RULE_REGEXP = 
"jclouds.azurecompute.arm.tcp.rule.regexp";
 
-   public static final String RESOURCE_GROUP_NAME = 
"jclouds.azurecompute.arm.operation.resourcegroup";
-
    public static final String IMAGE_PUBLISHERS = 
"jclouds.azurecompute.arm.publishers";
 
    public static final String DEFAULT_IMAGE_LOGIN = 
"jclouds.azurecompute.arm.defaultimagelogin";

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
new file mode 100644
index 0000000..233109a
--- /dev/null
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+@AutoValue
+public abstract class RegionAndId {
+
+   public abstract String region();
+   public abstract String id();
+   
+   RegionAndId() {
+      
+   }
+   
+   public static RegionAndId fromSlashEncoded(String id) {
+      Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+      checkArgument(Iterables.size(parts) == 2, "id must be in format 
regionId/id");
+      return new AutoValue_RegionAndId(Iterables.get(parts, 0), 
Iterables.get(parts, 1));
+   }
+
+   public static RegionAndId fromRegionAndId(String region, String id) {
+      return new AutoValue_RegionAndId(region, id);
+   }
+
+   public String slashEncode() {
+      return region() + "/" + id();
+   }
+   
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
index 39cc32c..ead676a 100644
--- 
a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
+++ 
b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java
@@ -16,7 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.functions;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Predicates.notNull;
 import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
@@ -25,7 +24,6 @@ import static org.jclouds.util.Closeables2.closeQuietly;
 
 import java.net.URI;
 import java.util.List;
-import java.util.Map;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
@@ -33,10 +31,11 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.arm.AzureComputeApi;
+import 
org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName;
 import org.jclouds.azurecompute.arm.domain.IdReference;
 import org.jclouds.azurecompute.arm.domain.IpConfiguration;
 import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
-import org.jclouds.azurecompute.arm.domain.ResourceGroup;
+import org.jclouds.azurecompute.arm.domain.RegionAndId;
 import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
 import org.jclouds.azurecompute.arm.domain.VirtualMachine;
 import org.jclouds.azurecompute.arm.util.BlobHelper;
@@ -46,10 +45,8 @@ import org.jclouds.logging.Logger;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 
 @Singleton
 public class CleanupResources implements Function<String, Boolean> {
@@ -61,28 +58,29 @@ public class CleanupResources implements Function<String, 
Boolean> {
    protected final AzureComputeApi api;
    private final Predicate<URI> resourceDeleted;
    private final StorageProfileToStorageAccountName 
storageProfileToStorageAccountName;
+   private final LocationToResourceGroupName locationToResourceGroupName;
 
    @Inject
    CleanupResources(AzureComputeApi azureComputeApi, 
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
-         StorageProfileToStorageAccountName 
storageProfileToStorageAccountName) {
+         StorageProfileToStorageAccountName storageProfileToStorageAccountName,
+         LocationToResourceGroupName locationToResourceGroupName) {
       this.api = azureComputeApi;
       this.resourceDeleted = resourceDeleted;
       this.storageProfileToStorageAccountName = 
storageProfileToStorageAccountName;
+      this.locationToResourceGroupName = locationToResourceGroupName;
    }
 
    @Override
    public Boolean apply(final String id) {
-      logger.debug(">> destroying %s ...", id);
-
-      Map<String, VirtualMachine> resourceGroupNamesAndVirtualMachines = 
getResourceGroupNamesAndVirtualMachines(id);
-      if (resourceGroupNamesAndVirtualMachines.isEmpty())
+      RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+      String group = locationToResourceGroupName.apply(regionAndId.region());
+      
+      VirtualMachine virtualMachine = 
api.getVirtualMachineApi(group).get(regionAndId.id());
+      if (virtualMachine == null) {
          return true;
+      }
 
-      String group = 
checkNotNull(resourceGroupNamesAndVirtualMachines.entrySet().iterator().next().getKey(),
-            "resourceGroup name must not be null");
-      VirtualMachine virtualMachine = 
checkNotNull(resourceGroupNamesAndVirtualMachines.get(group),
-            "virtualMachine must not be null");
-
+      logger.debug(">> destroying %s ...", regionAndId.slashEncode());
       boolean vmDeleted = deleteVirtualMachine(group, virtualMachine);
       
       // We don't delete the network here, as it is global to the resource
@@ -163,14 +161,4 @@ public class CleanupResources implements Function<String, 
Boolean> {
       return 
resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name()));
    }
 
-   private Map<String, VirtualMachine> 
getResourceGroupNamesAndVirtualMachines(String id) {
-      for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
-         String group = resourceGroup.name();
-         VirtualMachine virtualMachine = 
api.getVirtualMachineApi(group).get(id);
-         if (virtualMachine != null) {
-            return ImmutableMap.of(group, virtualMachine);
-         }
-      }
-      return Maps.newHashMap();
-   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java
----------------------------------------------------------------------
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 c338954..c59509f 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,19 +16,9 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
 import static 
org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
-import static 
org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
 
 import java.util.Properties;
-import java.util.concurrent.TimeUnit;
 
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
@@ -78,19 +68,8 @@ public class AzureComputeServiceLiveTest extends 
BaseComputeServiceLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      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);
-      properties.put(RESOURCE_GROUP_NAME, "jc");
-      properties.put(PROPERTY_REGIONS, "eastus");
-      properties.put(IMAGE_PUBLISHERS, "Canonical");
-
       AzureLiveTestUtils.defaultProperties(properties);
-      checkNotNull(setIfTestSystemPropertyPresent(properties, 
"oauth.endpoint"), "test.oauth.endpoint");
-
+      setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java
----------------------------------------------------------------------
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 c20655b..56200c4 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
@@ -16,8 +16,6 @@
  */
 package org.jclouds.azurecompute.arm.compute;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
 import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
@@ -58,25 +56,23 @@ public class AzureTemplateBuilderLiveTest extends 
BaseTemplateBuilderLiveTest {
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      properties.put(RESOURCE_GROUP_NAME, "jc");
-
       AzureLiveTestUtils.defaultProperties(properties);
-      checkNotNull(setIfTestSystemPropertyPresent(properties, 
"oauth.endpoint"), "test.oauth.endpoint");
-
+      setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
-   
+
    @Override
    @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: " + 
defaultTemplate.getImage().getOperatingSystem().getVersion());
+            "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);
       assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
    }
-   
+
    @Override
    protected Set<String> getIso3166Codes() {
       return Region.iso3166Codes();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
----------------------------------------------------------------------
diff --git 
a/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
 
b/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java
index de44668..c8a9259 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
@@ -16,20 +16,10 @@
  */
 package org.jclouds.azurecompute.arm.compute.extensions;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
-import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
-import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
 import static 
org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
-import static 
org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
 
 import java.util.Map;
 import java.util.Properties;
-import java.util.concurrent.TimeUnit;
 
 import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
 import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
@@ -63,19 +53,8 @@ public class AzureComputeImageExtensionLiveTest extends 
BaseImageExtensionLiveTe
    @Override
    protected Properties setupProperties() {
       Properties properties = super.setupProperties();
-      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);
-      properties.put(RESOURCE_GROUP_NAME, "jc");
-      properties.put(PROPERTY_REGIONS, "eastus");
-      properties.put(IMAGE_PUBLISHERS, "Canonical");
-
       AzureLiveTestUtils.defaultProperties(properties);
-      checkNotNull(setIfTestSystemPropertyPresent(properties, 
"oauth.endpoint"), "test.oauth.endpoint");
-
+      setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f58f96b1/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java
----------------------------------------------------------------------
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 3f69e59..125e11a 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
@@ -16,21 +16,34 @@
  */
 package org.jclouds.azurecompute.arm.internal;
 
-import java.util.Properties;
-
+import static 
org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
 import static 
org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
 import static 
org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
 import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
 
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
 public class AzureLiveTestUtils {
 
     public static Properties defaultProperties(Properties properties) {
        properties = properties == null ? new Properties() : properties;
-       properties.put("oauth.identity", "foo");
-       properties.put("oauth.credential", "password");
-       properties.put("oauth.endpoint", 
"https://login.microsoftonline.com/oauth2/token";);
        properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
-       properties.put(PROPERTY_REGIONS, "northeurope");
+       properties.put(PROPERTY_REGIONS, "eastus");
+       properties.put(IMAGE_PUBLISHERS, "Canonical");
+       
+       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;
     }
 }

Reply via email to