You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2015/03/12 11:39:28 UTC

[10/10] jclouds-labs git commit: [JCLOUDS-664] Fixing live test execution

[JCLOUDS-664] Fixing live test execution


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

Branch: refs/heads/master
Commit: c80d40a5cd4a0194e763f7f5b68a2e7a40bb6b72
Parents: e6305c2
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Mar 5 09:51:37 2015 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Mar 12 11:24:43 2015 +0100

----------------------------------------------------------------------
 azurecompute/README.md                          |  10 +-
 azurecompute/pom.xml                            |  37 +--
 .../AzureComputeProviderMetadata.java           |   1 +
 .../AzureManagementApiMetadata.java             |   3 +-
 .../binders/DeploymentParamsToXML.java          |   3 +-
 .../binders/NetworkConfigurationToXML.java      |   1 +
 .../binders/NetworkSecurityGroupToXML.java      |   1 +
 .../binders/OSImageParamsToXML.java             |   3 +-
 .../jclouds/azurecompute/binders/RoleToXML.java |   6 +-
 .../jclouds/azurecompute/binders/RuleToXML.java |   1 +
 .../binders/StorageServiceParamsToXML.java      |   3 +-
 .../compute/AzureComputeServiceAdapter.java     |  55 ++--
 .../AzureComputeServiceContextModule.java       |  13 +-
 .../AzureComputeSecurityGroupExtension.java     | 184 ++++++-----
 .../compute/functions/OSImageToImage.java       |   3 +-
 ...ServiceAndVirtualNetworkThenCreateNodes.java |   5 +-
 .../config/AzureComputeHttpApiModule.java       |   4 +-
 .../config/AzureComputeProperties.java          |   1 +
 .../jclouds/azurecompute/domain/Deployment.java |   8 +-
 .../domain/NetworkSecurityGroup.java            |   2 +-
 .../org/jclouds/azurecompute/domain/Role.java   |   1 +
 .../azurecompute/features/OSImageApi.java       |   3 +-
 .../features/StorageAccountApi.java             |   2 +-
 .../features/VirtualMachineApi.java             |   4 +-
 .../handlers/AzureComputeErrorHandler.java      |   8 -
 .../util/ConflictManagementPredicate.java       | 119 +++++++
 .../util/NetworkSecurityGroups.java             |   5 +-
 .../azurecompute/xml/DeploymentHandler.java     |   1 +
 .../AzureComputeProviderMetadataLive.java       |  82 +++++
 .../jclouds/azurecompute/AzureTestUtils.java    |  52 +++
 .../AzureComputeServiceAdapterLiveTest.java     | 106 ++++--
 .../AzureComputeServiceContextLiveTest.java     | 113 ++++++-
 ...reComputeSecurityGroupExtensionLiveTest.java |   2 +
 .../compute/functions/OSImageToImageTest.java   | 321 ++++++++++---------
 .../features/CloudServiceApiLiveTest.java       |  39 ++-
 .../features/CloudServiceApiMockTest.java       |  55 +++-
 .../features/DeploymentApiLiveTest.java         |  79 +++--
 .../azurecompute/features/DiskApiLiveTest.java  |  21 +-
 .../features/LocationApiLiveTest.java           |   7 +-
 .../features/OSImageApiLiveTest.java            |  41 ++-
 .../features/OSImageApiMockTest.java            |   4 +-
 .../features/OperationApiMockTest.java          |   6 +-
 .../features/SubscriptionApiLiveTest.java       |   3 +-
 .../features/VirtualMachineApiLiveTest.java     | 121 ++++---
 .../features/VirtualMachineApiMockTest.java     |  16 +-
 .../features/VirtualNetworkApiLiveTest.java     | 108 ++++---
 .../features/VirtualNetworkApiMockTest.java     |  15 +-
 .../internal/BaseAzureComputeApiLiveTest.java   | 201 +++++++-----
 .../internal/BaseAzureComputeApiMockTest.java   |  10 +-
 .../xml/CloudServiceHandlerTest.java            |  19 +-
 .../azurecompute/xml/DeploymentHandlerTest.java |  87 ++---
 .../azurecompute/xml/ErrorHandlerTest.java      |   2 +-
 .../xml/ListCloudServicesHandlerTest.java       |  45 +--
 .../ListDataVirtualHardDisksHandlerTest.java    |  34 +-
 .../azurecompute/xml/ListDisksHandlerTest.java  |  42 +--
 .../xml/ListLocationsHandlerTest.java           |  12 +-
 .../xml/ListOSImagesHandlerTest.java            | 240 +++++++-------
 .../xml/NetworkConfigurationHandlerTest.java    |  10 +-
 .../xml/NetworkSecurityGroupHandlerTest.java    |  31 +-
 .../src/test/resources/networksecuritygroup.xml |  12 +
 60 files changed, 1533 insertions(+), 890 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/README.md
----------------------------------------------------------------------
diff --git a/azurecompute/README.md b/azurecompute/README.md
index 9e44b67..5deca6f 100644
--- a/azurecompute/README.md
+++ b/azurecompute/README.md
@@ -1,8 +1,8 @@
-=== Annotation processing
+## Annotation processing ##
 In order for value object and service loader auto-generation, you will need to enable annotation processing in your IDE.
 If you notice any inconsistencies in your IDE after you enable annotation processing, try rerunning "Make Project".
 
-=== Setting up test credentials
+## Setting up test credentials ##
 
 Azure requests are signed by via SSL certificate. You need to upload one into your account in order to run tests.
 
@@ -20,7 +20,7 @@ openssl x509 -inform pem -in $HOME/.jclouds/azure.pem -outform der -out $HOME/.j
 
 Once you do this, you will set the following to run the live tests.
 ```bash
-mvn -Plive -Dtest.azurecompute.endpoint=https://management.core.windows.net/12345678-abcd-dcba-abdc-ba0987654321
--Dtest.azurecompute.credential=P12_EXPORT_PASSWORD
+mvn -Plive -Dtest.azurecompute.endpoint=https://management.core.windows.net/12345678-abcd-dcba-abdc-ba0987654321 \
+-Dtest.azurecompute.credential=P12_EXPORT_PASSWORD \
 -Dtest.azurecompute.identity=$HOME/.jclouds/azure.p12
-```
+```
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute/pom.xml b/azurecompute/pom.xml
index 4231412..0f5820d 100644
--- a/azurecompute/pom.xml
+++ b/azurecompute/pom.xml
@@ -17,7 +17,8 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.jclouds.labs</groupId>
@@ -27,7 +28,7 @@
 
   <!-- TODO: when out of labs, switch to org.jclouds.provider -->
   <artifactId>azurecompute</artifactId>
-  <name>Apache jclouds :: Azure :: Compute API</name>
+  <name>jclouds azure compute API</name>
   <description>jclouds components to access an implementation of Azure's Compute Service</description>
   <packaging>bundle</packaging>
 
@@ -35,7 +36,7 @@
     <test.jclouds.azurecompute.subscription-id>FIXME_subscription-id</test.jclouds.azurecompute.subscription-id>
     <!-- note that there's no prefix of "test." in the url.  This is to ensure that jclouds inteprets the value, as opposed to maven -->
     <test.azurecompute.endpoint>https://management.core.windows.net/${jclouds.azurecompute.subscription-id}</test.azurecompute.endpoint>
-    <test.azurecompute.api-version>2014-06-01</test.azurecompute.api-version>
+    <test.azurecompute.api-version>2014-10-01</test.azurecompute.api-version>
     <test.azurecompute.build-version />
     <test.azurecompute.identity>/path/to/cert.p12</test.azurecompute.identity>
     <test.azurecompute.credential>password to cert</test.azurecompute.credential>
@@ -43,19 +44,6 @@
     <jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
   </properties>
 
-  <repositories>
-    <repository>
-      <id>apache-snapshots</id>
-      <url>https://repository.apache.org/content/repositories/snapshots</url>
-      <releases>
-        <enabled>false</enabled>
-      </releases>
-      <snapshots>
-        <enabled>true</enabled>
-      </snapshots>
-    </repository>
-  </repositories>
-
   <dependencies>
     <dependency>
       <groupId>com.jamesmurty.utils</groupId>
@@ -96,6 +84,13 @@
       <groupId>org.apache.jclouds.driver</groupId>
       <artifactId>jclouds-slf4j</artifactId>
       <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <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>
@@ -110,11 +105,6 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>com.squareup.okhttp</groupId>
       <artifactId>mockwebserver</artifactId>
       <scope>test</scope>
@@ -131,7 +121,10 @@
   <profiles>
     <profile>
       <id>live</id>
+      
       <build>
+        <defaultGoal>clean verify</defaultGoal>
+          
         <plugins>
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
@@ -161,4 +154,4 @@
     </profile>
   </profiles>
 
-</project>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
index 60e00d1..876a521 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
@@ -52,6 +52,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "" + 5);
       properties.setProperty(OPERATION_POLL_MAX_PERIOD, "" + 15);
       properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
+      properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
       return properties;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
index 8e5fa86..14f8089 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureManagementApiMetadata.java
@@ -48,8 +48,7 @@ public class AzureManagementApiMetadata extends BaseHttpApiMetadata<AzureCompute
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseHttpApiMetadata.defaultProperties();
-      return properties;
+      return BaseHttpApiMetadata.defaultProperties();
    }
 
    public static class Builder extends BaseHttpApiMetadata.Builder<AzureComputeApi, Builder> {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
index bc9f657..f557734 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
@@ -28,7 +28,8 @@ import com.jamesmurty.utils.XMLBuilder;
 
 public final class DeploymentParamsToXML implements Binder {
 
-   @Override public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+   @Override@SuppressWarnings("unchecked")
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       DeploymentParams params = DeploymentParams.class.cast(input);
 
       try {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
index 87ffb5e..3021ef4 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkConfigurationToXML.java
@@ -29,6 +29,7 @@ import com.jamesmurty.utils.XMLBuilder;
 public class NetworkConfigurationToXML implements Binder {
 
    @Override
+   @SuppressWarnings("unchecked")
    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       NetworkConfiguration networkConfiguration = NetworkConfiguration.class.cast(input);
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
index 6290df6..6ca0ecb 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/NetworkSecurityGroupToXML.java
@@ -26,6 +26,7 @@ import com.jamesmurty.utils.XMLBuilder;
 
 public class NetworkSecurityGroupToXML implements Binder {
    @Override
+   @SuppressWarnings("unchecked")
    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       NetworkSecurityGroup networkSecurityGroup = NetworkSecurityGroup.class.cast(input);
       try {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/OSImageParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/OSImageParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/OSImageParamsToXML.java
index 3d87c8f..cab54df 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/OSImageParamsToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/OSImageParamsToXML.java
@@ -26,7 +26,8 @@ import org.jclouds.rest.Binder;
 import com.jamesmurty.utils.XMLBuilder;
 
 public final class OSImageParamsToXML implements Binder {
-   @Override public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+   @Override@SuppressWarnings("unchecked")
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       OSImageParams params = OSImageParams.class.cast(input);
       try {
          String xml = XMLBuilder.create("OSImage", "http://schemas.microsoft.com/windowsazure")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
index 41c3a83..d5690e9 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
@@ -26,6 +26,7 @@ import com.jamesmurty.utils.XMLBuilder;
 
 public class RoleToXML implements Binder {
    @Override
+   @SuppressWarnings("unchecked")
    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       Role role = Role.class.cast(input);
 
@@ -53,7 +54,10 @@ public class RoleToXML implements Binder {
                for (Role.ConfigurationSet.SubnetName subnetName : configurationSet.subnetNames()) {
                   subnetNames.e("SubnetName").t(subnetName.name()).up();
                }
-               configBuilder.e("NetworkSecurityGroup").t(configurationSet.networkSecurityGroup()).up();
+               if (configurationSet.networkSecurityGroup() != null
+                            && !configurationSet.networkSecurityGroup().isEmpty()) {
+                  configBuilder.e("NetworkSecurityGroup").t(configurationSet.networkSecurityGroup()).up();
+               }
             }
          }
          builder.e("DataVirtualHardDisks").up()

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
index ec4a1f6..3a34b79 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RuleToXML.java
@@ -26,6 +26,7 @@ import com.jamesmurty.utils.XMLBuilder;
 
 public final class RuleToXML implements Binder {
    @Override
+   @SuppressWarnings("unchecked")
    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       Rule rule = Rule.class.cast(input);
       try {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
index f6a934e..2589a24 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/StorageServiceParamsToXML.java
@@ -27,7 +27,8 @@ import com.jamesmurty.utils.XMLBuilder;
 
 public final class StorageServiceParamsToXML implements Binder {
 
-   @Override public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+   @Override@SuppressWarnings("unchecked")
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       StorageServiceParams params = StorageServiceParams.class.cast(input);
 
       try {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
index aed8570..632e07d 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
@@ -108,7 +108,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
       }
       logger.info("Cloud Service (%s) created with operation id: %s", name, createCloudServiceRequestId);
 
-      final OSImage.Type os = template.getImage().getOperatingSystem().getFamily().equals(OsFamily.WINDOWS) ? OSImage.Type.WINDOWS : OSImage.Type.LINUX;
+      final OSImage.Type os = template.getImage().getOperatingSystem().getFamily() == OsFamily.WINDOWS 
+              ? OSImage.Type.WINDOWS : OSImage.Type.LINUX;
       Set<ExternalEndpoint> externalEndpoints = Sets.newHashSet();
       for (int inboundPort : inboundPorts) {
          externalEndpoints.add(ExternalEndpoint.inboundTcpToLocalPort(inboundPort, inboundPort));
@@ -118,7 +119,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
               .os(os)
               .username(loginUser)
               .password(loginPassword)
-              .sourceImageName(template.getImage().getId())
+              .sourceImageName(Splitter.on('/').split(template.getImage().getId()).iterator().next())
               .mediaLink(createMediaLink(storageAccountName, name))
               .size(RoleSize.Type.fromString(template.getHardware().getName()))
               .externalEndpoints(externalEndpoints)
@@ -138,6 +139,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
       logger.info("Deployment created with operation id: %s", createDeploymentRequestId);
 
       if (!retry(new Predicate<String>() {
+         @Override
          public boolean apply(String name) {
             return FluentIterable.from(api.getDeploymentApiForService(name).get(name).roleInstanceList())
                     .allMatch(new Predicate<RoleInstance>() {
@@ -160,7 +162,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
 
       Deployment deployment = api.getDeploymentApiForService(name).get(name);
 
-      return new NodeAndInitialCredentials(deployment, deployment.name(),
+      return new NodeAndInitialCredentials<Deployment>(deployment, deployment.name(),
               LoginCredentials.builder().user(loginUser).password(loginPassword).build());
    }
 
@@ -178,23 +180,38 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
    public Iterable<OSImage> listImages() {
       List<OSImage> osImages = Lists.newArrayList();
       for (OSImage osImage : api.getOSImageApi().list()) {
-         Iterable<String> locations = Splitter.on(";").split(osImage.location());
-         for (String location : locations) {
-            osImages.add(OSImage.create(
-                    osImage.name(),
-                    location,
-                    osImage.affinityGroup(),
-                    osImage.label(),
-                    osImage.description(),
-                    osImage.category(),
-                    osImage.os(),
-                    osImage.publisherName(),
-                    osImage.mediaLink(),
-                    osImage.logicalSizeInGB(),
-                    osImage.eula()
-            ));
+            if (osImage.location() == null) {
+                osImages.add(OSImage.create(
+                        osImage.name(),
+                        null,
+                        osImage.affinityGroup(),
+                        osImage.label(),
+                        osImage.description(),
+                        osImage.category(),
+                        osImage.os(),
+                        osImage.publisherName(),
+                        osImage.mediaLink(),
+                        osImage.logicalSizeInGB(),
+                        osImage.eula()
+                ));
+            } else {
+                for (String actualLocation : Splitter.on(';').split(osImage.location())) {
+                    osImages.add(OSImage.create(
+                            osImage.name() + "/" + actualLocation,
+                            actualLocation,
+                            osImage.affinityGroup(),
+                            osImage.label() + "/" + actualLocation,
+                            osImage.description(),
+                            osImage.category(),
+                            osImage.os(),
+                            osImage.publisherName(),
+                            osImage.mediaLink(),
+                            osImage.logicalSizeInGB(),
+                            osImage.eula()
+                    ));
+                }
+            }
          }
-      }
       return osImages;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
index 30e2569..ecdeb23 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java
@@ -21,6 +21,7 @@ import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_P
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_FORMAT;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_REGEXP;
 
 import javax.inject.Named;
 import javax.inject.Singleton;
@@ -50,7 +51,6 @@ import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
 import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
 import org.jclouds.util.Predicates2;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
@@ -100,8 +100,7 @@ public class AzureComputeServiceContextModule
               azureComputeConstants.operationPollMaxPeriod());
    }
 
-   @VisibleForTesting
-   static class OperationSucceededPredicate implements Predicate<String> {
+   public static class OperationSucceededPredicate implements Predicate<String> {
 
       private final AzureComputeApi api;
 
@@ -146,6 +145,10 @@ public class AzureComputeServiceContextModule
       @Inject
       private String tcpRuleFormatProperty;
 
+      @Named(TCP_RULE_REGEXP)
+      @Inject
+      private String tcpRuleRegexpProperty;
+
       public Long operationTimeout() {
          return Long.parseLong(operationTimeoutProperty);
       }
@@ -161,6 +164,10 @@ public class AzureComputeServiceContextModule
       public String tcpRuleFormat() {
          return tcpRuleFormatProperty;
       }
+      
+      public String tcpRuleRegexp() {
+         return tcpRuleRegexpProperty;
+      }
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
index d5e2db1..1a225d1 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java
@@ -17,7 +17,10 @@
 package org.jclouds.azurecompute.compute.extensions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
+import static org.jclouds.util.Predicates2.retry;
+
 import java.util.List;
 import java.util.Set;
 
@@ -27,15 +30,16 @@ import javax.inject.Named;
 
 import org.jclouds.azurecompute.AzureComputeApi;
 import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
-import org.jclouds.azurecompute.config.AzureComputeProperties;
 import org.jclouds.azurecompute.domain.CloudService;
 import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Deployment.Status;
 import org.jclouds.azurecompute.domain.NetworkConfiguration;
 import org.jclouds.azurecompute.domain.NetworkConfiguration.VirtualNetworkSite;
 import org.jclouds.azurecompute.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.domain.Role;
 import org.jclouds.azurecompute.domain.Rule;
 import org.jclouds.azurecompute.util.NetworkSecurityGroups;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
 import org.jclouds.compute.domain.SecurityGroup;
 import org.jclouds.compute.domain.SecurityGroupBuilder;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
@@ -145,7 +149,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
       final NetworkSecurityGroup networkSecurityGroup = NetworkSecurityGroup.create(name, name, location.getId(), null);
       String createNSGRequestId = api.getNetworkSecurityGroupApi().create(networkSecurityGroup);
-      if (operationSucceededPredicate.apply(createNSGRequestId)) {
+      if (!operationSucceededPredicate.apply(createNSGRequestId)) {
          final String message = generateIllegalStateExceptionMessage(createNSGRequestId, azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);
@@ -155,13 +159,13 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
    private SecurityGroup transformNetworkSecurityGroupToSecurityGroup(String name) {
       final NetworkSecurityGroup fullDetails = api.getNetworkSecurityGroupApi().getFullDetails(name);
-      if (fullDetails == null) return null;
-      return new NetworkSecurityGroupSecurityGroupFunction().apply(fullDetails);
+      return fullDetails == null
+              ? null
+              : new NetworkSecurityGroupSecurityGroupFunction().apply(fullDetails);
    }
 
    @Override
    public boolean removeSecurityGroup(String id) {
-
       final NetworkConfiguration networkConfiguration = api.getVirtualNetworkApi().getNetworkConfiguration();
       if (networkConfiguration != null) {
          for (VirtualNetworkSite virtualNetworkSite : networkConfiguration.virtualNetworkConfiguration().virtualNetworkSites()) {
@@ -177,7 +181,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
                         // remove existing nsg from subnet
                         String removeFromSubnetRequestId = api.getNetworkSecurityGroupApi().removeFromSubnet
                                 (virtualNetworkName, subnetName, networkSecurityGroupAppliedToSubnet.name());
-                        if (operationSucceededPredicate.apply(removeFromSubnetRequestId)) {
+                        if (!operationSucceededPredicate.apply(removeFromSubnetRequestId)) {
                            final String message = generateIllegalStateExceptionMessage(removeFromSubnetRequestId, azureComputeConstants.operationTimeout());
                            logger.warn(message);
                            throw new IllegalStateException(message);
@@ -196,54 +200,68 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
    public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) {
       checkNotNull(group, "group");
       checkNotNull(ipPermission, "ipPermission");
-      String id = checkNotNull(group.getId(), "group.getId()");
+      
+      final String id = checkNotNull(group.getId(), "group.getId()");
 
-      NetworkSecurityGroup networkSecurityGroup = api.getNetworkSecurityGroupApi().getFullDetails(group.getName());
-      List<Rule> filteredRules = NetworkSecurityGroups.getCustomRules(networkSecurityGroup);
-      int priority = NetworkSecurityGroups.getFirstAvailablePriority(filteredRules);
+      final int priority = NetworkSecurityGroups.getFirstAvailablePriority(
+              NetworkSecurityGroups.getCustomRules(api.getNetworkSecurityGroupApi().getFullDetails(group.getName())));
 
-      String ruleName = NetworkSecurityGroups.createRuleName(ipPermission.getFromPort(), ipPermission.getToPort());
+      final String ruleName = NetworkSecurityGroups.createRuleName(
+              azureComputeConstants.tcpRuleFormat(), ipPermission.getFromPort(), ipPermission.getToPort());
 
       // add rule to NSG
       addRuleToNetworkSecurityGroup(id, ruleName, priority, ipPermission);
 
       // add endpoint to VM
-      Set<Deployment> deployments = FluentIterable.from(api.getCloudServiceApi().list())
-              .transform(new Function<CloudService, Deployment>() {
-                 @Override
-                 public Deployment apply(CloudService cloudService) {
-                    return api.getDeploymentApiForService(cloudService.name()).get(cloudService.name());
-                 }
-              })
-              .filter(Predicates.notNull())
-              .toSet();
-      // TODO filter deployments
-      for (Deployment deployment : deployments) {
-         Deployment.VirtualIP virtualIP = Iterables.tryFind(deployment.virtualIPs(), Predicates.notNull()).orNull();
-         if (virtualIP == null) throw new IllegalStateException("Deployment doesn't contain virtual IPs");
-
-         for (Role role : deployment.roles()) {
-            for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
-               if (ipPermission.getFromPort() < ipPermission.getToPort()) {
-                  for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) {
-                     String name = String.format(AzureComputeProperties.TCP_RULE_FORMAT, i, i);
-                     configurationSet.inputEndpoints().add(createInputEndpoint(name, ipPermission.getIpProtocol().name(),
-                             virtualIP.address(), i));
+      for (final CloudService service : api.getCloudServiceApi().list()) {
+         // TODO filter deployments
+         final Deployment deployment = api.getDeploymentApiForService(service.name()).get(service.name());
+         if (deployment != null && deployment.status() != Status.DELETING) {
+            for (Deployment.VirtualIP vip : Iterables.filter(deployment.virtualIPs(), Predicates.notNull())) {
+               for (final Role role : deployment.roles()) {
+                  for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
+                     if (ipPermission.getFromPort() < ipPermission.getToPort()) {
+                        for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) {
+                           final String name = NetworkSecurityGroups.createRuleName(
+                                   azureComputeConstants.tcpRuleFormat(), i, i);
+                           configurationSet.inputEndpoints().add(createInputEndpoint(
+                                   name,
+                                   ipPermission.getIpProtocol().name(),
+                                   vip.address(),
+                                   i));
+                        }
+                     } else {
+                        configurationSet.inputEndpoints().add(createInputEndpoint(
+                                ruleName,
+                                ipPermission.getIpProtocol().name(),
+                                vip.address(),
+                                ipPermission.getToPort()));
+                     }
                   }
-               } else {
-                  configurationSet.inputEndpoints().add(createInputEndpoint(ruleName, ipPermission.getIpProtocol().name(),
-                          virtualIP.address(), ipPermission.getToPort()));
-               }
-               String updateRoleRequestId = api.getVirtualMachineApiForDeploymentInService(deployment.name(), deployment.name()).updateRole(role.roleName(), role);
-               if (operationSucceededPredicate.apply(updateRoleRequestId)) {
-                  final String message = generateIllegalStateExceptionMessage(updateRoleRequestId, azureComputeConstants.operationTimeout());
-                  logger.warn(message);
-                  throw new IllegalStateException(message);
+
+                  retry(new ConflictManagementPredicate(
+                          operationSucceededPredicate,
+                          azureComputeConstants.operationTimeout()) {
+
+                             @Override
+                             protected String operation() {
+                                // Check for deployment validity
+                                final Deployment deployment = api.getDeploymentApiForService(
+                                        service.name()).get(service.name());
+                                if (deployment == null || deployment.status() == Status.DELETING) {
+                                   return null;
+                                } else {
+                                   return api.getVirtualMachineApiForDeploymentInService(
+                                           deployment.name(), deployment.name()).
+                                   updateRole(role.roleName(), role);
+                                }
+                             }
+                          }, 600, 30, 30, SECONDS).apply(role.roleName());
                }
             }
          }
-
       }
+      
       return transformNetworkSecurityGroupToSecurityGroup(id);
    }
 
@@ -267,43 +285,58 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
    public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) {
       checkNotNull(group, "group");
       checkNotNull(ipPermission, "ipPermission");
-      String id = checkNotNull(group.getId(), "group.getId()");
+      
+      final String id = checkNotNull(group.getId(), "group.getId()");
 
-      String ruleName = NetworkSecurityGroups.createRuleName(ipPermission.getFromPort(), ipPermission.getToPort());
+      final String ruleName = NetworkSecurityGroups.createRuleName(
+              azureComputeConstants.tcpRuleFormat(), ipPermission.getFromPort(), ipPermission.getToPort());
+      
       // remove rule to NSG
       removeRuleFromNetworkSecurityGroup(id, ruleName);
 
       // TODO remove endpoint from VM
-      Set<Deployment> deployments = FluentIterable.from(api.getCloudServiceApi().list())
-              .transform(new Function<CloudService, Deployment>() {
-                 @Override
-                 public Deployment apply(CloudService cloudService) {
-                    return api.getDeploymentApiForService(cloudService.name()).get(cloudService.name());
-                 }
-              })
-              .filter(Predicates.notNull())
-              .toSet();
-      // TODO filter deployments
-      for (Deployment deployment : deployments) {
-         Deployment.VirtualIP virtualIP = Iterables.tryFind(deployment.virtualIPs(), Predicates.notNull()).orNull();
-         if (virtualIP == null) throw new IllegalStateException("");
-
-         for (Role role : deployment.roles()) {
-            for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
-               for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) {
-                  String name = String.format(AzureComputeProperties.TCP_RULE_FORMAT, i, i);
-                  configurationSet.inputEndpoints().remove(createInputEndpoint(name, ipPermission.getIpProtocol()
-                          .name().toLowerCase(), virtualIP.address(), i));
-               }
-               String updateRoleRequestId = api.getVirtualMachineApiForDeploymentInService(deployment.name(), deployment.name()).updateRole(role.roleName(), role);
-               if (operationSucceededPredicate.apply(updateRoleRequestId)) {
-                  final String message = generateIllegalStateExceptionMessage(updateRoleRequestId, azureComputeConstants.operationTimeout());
-                  logger.warn(message);
-                  throw new IllegalStateException(message);
+      for (final CloudService service : api.getCloudServiceApi().list()) {
+         // TODO remove endpoint from VM
+         final Deployment deployment = api.getDeploymentApiForService(service.name()).get(service.name());
+         if (deployment != null && deployment.status() != Status.DELETING) {
+            for (Deployment.VirtualIP vip : Iterables.filter(deployment.virtualIPs(), Predicates.notNull())) {
+               for (final Role role : deployment.roles()) {
+                  for (Role.ConfigurationSet configurationSet : role.configurationSets()) {
+                     for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) {
+                        final String name = NetworkSecurityGroups.createRuleName(
+                                azureComputeConstants.tcpRuleFormat(), i, i);
+                        configurationSet.inputEndpoints().remove(createInputEndpoint(
+                                name,
+                                ipPermission.
+                                getIpProtocol().name().toLowerCase(),
+                                vip.address(),
+                                i));
+                     }
+                  }
+
+                  retry(new ConflictManagementPredicate(
+                          operationSucceededPredicate,
+                          azureComputeConstants.operationTimeout()) {
+
+                             @Override
+                             protected String operation() {
+                                // Check for deployment validity
+                                final Deployment deployment = api.getDeploymentApiForService(
+                                        service.name()).get(service.name());
+                                if (deployment == null || deployment.status() == Status.DELETING) {
+                                   return null;
+                                } else {
+                                   return api.getVirtualMachineApiForDeploymentInService(
+                                           deployment.name(), deployment.name()).
+                                   updateRole(role.roleName(), role);
+                                }
+                             }
+                          }, 600, 30, 30, SECONDS).apply(role.roleName());
                }
             }
          }
       }
+      
       return transformNetworkSecurityGroupToSecurityGroup(id);
    }
 
@@ -348,12 +381,12 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
       return false;
    }
 
-   public static class RuleToIpPermission implements Function<Rule, IpPermission> {
+   private class RuleToIpPermission implements Function<Rule, IpPermission> {
 
       @Override
       public IpPermission apply(Rule rule) {
          IpPermission.Builder builder = IpPermission.builder();
-         if (rule.name().matches("tcp_\\d{1,5}-\\d{1,5}")) {
+         if (rule.name().matches(azureComputeConstants.tcpRuleRegexp())) {
             builder.fromPort(extractPort(rule.name(), 0))
                     .toPort(extractPort(rule.name(), 1));
          }
@@ -372,7 +405,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
       }
    }
 
-   private static class NetworkSecurityGroupSecurityGroupFunction implements Function<NetworkSecurityGroup, SecurityGroup> {
+   private class NetworkSecurityGroupSecurityGroupFunction implements Function<NetworkSecurityGroup, SecurityGroup> {
       @Override
       public SecurityGroup apply(NetworkSecurityGroup networkSecurityGroup) {
          SecurityGroupBuilder securityGroupBuilder = new SecurityGroupBuilder()
@@ -380,7 +413,6 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
                  .providerId(networkSecurityGroup.label())
                  .name(networkSecurityGroup.name());
          if (networkSecurityGroup.rules() != null) {
-
             List<Rule> filteredRules = NetworkSecurityGroups.getCustomRules(networkSecurityGroup);
 
             Iterable<IpPermission> permissions = Iterables.transform(filteredRules, new RuleToIpPermission());
@@ -416,7 +448,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
                       "Active", // state
                       true // isDefault
               ));
-      if (operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
+      if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
          final String message = generateIllegalStateExceptionMessage(setRuleToNSGRequestId, azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);
@@ -425,7 +457,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
 
    private void removeRuleFromNetworkSecurityGroup(String id, String ruleName) {
       String setRuleToNSGRequestId = api.getNetworkSecurityGroupApi().deleteRule(id, ruleName);
-      if (operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
+      if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
          final String message = generateIllegalStateExceptionMessage(setRuleToNSGRequestId, azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
index c08aeed..325c41b 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
@@ -122,7 +122,8 @@ public class OSImageToImage implements Function<OSImage, Image> {
             if (family != OsFamily.UNRECOGNIZED) {
                return OperatingSystem.builder().family(family).version(version)
                      .description(image.description() + "");
-            } else if (family == OsFamily.UNRECOGNIZED && image.os() == OSImage.Type.WINDOWS) {
+            }
+            if (image.os() == OSImage.Type.WINDOWS) {
                return OperatingSystem.builder().family(OsFamily.WINDOWS).version(version)
                      .description(image.description() + "");
             }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
index 1520509..e0a5b27 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java
@@ -164,9 +164,10 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes extends C
     */
    private StorageService tryFindExistingStorageServiceAccountOrCreate(AzureComputeApi api, String location, final String name, final String type) {
       final List<StorageService> storageServices = api.getStorageAccountApi().list();
-      Predicate<StorageService> storageServicePredicate;
       logger.debug("Looking for a suitable existing storage account ...");
-      storageServicePredicate = and(notNull(), new SameLocationAndCreatedStorageServicePredicate(location), new Predicate<StorageService>() {
+
+      @SuppressWarnings("unchecked")
+      final Predicate<StorageService> storageServicePredicate = and(notNull(), new SameLocationAndCreatedStorageServicePredicate(location), new Predicate<StorageService>() {
          @Override
          public boolean apply(StorageService input) {
             return input.serviceName().matches(format("^%s[a-z]{10}$", DEFAULT_STORAGE_ACCOUNT_PREFIX));

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
index 96bdd50..9dbaf1e 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeHttpApiModule.java
@@ -30,7 +30,7 @@ import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
 import org.jclouds.location.config.LocationModule;
 import org.jclouds.location.suppliers.ImplicitLocationSupplier;
-import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone;
+import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstRegionOptionallyMatchingRegionId;
 import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
 
@@ -51,7 +51,7 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
    @Override
    protected void installLocations() {
       install(new LocationModule());
-      bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Scopes.SINGLETON);
+      bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstRegionOptionallyMatchingRegionId.class).in(Scopes.SINGLETON);
    }
    
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
index 44ec8aa..ccdc61a 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/config/AzureComputeProperties.java
@@ -30,4 +30,5 @@ public class AzureComputeProperties {
 
    public static final String TCP_RULE_FORMAT = "jclouds.azurecompute.tcp.rule.format";
 
+   public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.tcp.rule.regexp";
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
index 7d71965..9dc25a6 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Deployment.java
@@ -93,12 +93,16 @@ public abstract class Deployment {
 
       public abstract InstanceStatus instanceStatus();
 
+      @Nullable // null value in case of StoppedDeallocated
       public abstract int instanceUpgradeDomain();
 
+      @Nullable // null value in case of StoppedDeallocated
       public abstract int instanceFaultDomain();
 
+      @Nullable // null value in case of StoppedDeallocated
       public abstract RoleSize.Type instanceSize();
 
+      @Nullable // null value in case of StoppedDeallocated
       public abstract String ipAddress();
 
       @Nullable public abstract String hostname();
@@ -111,7 +115,7 @@ public abstract class Deployment {
       public static RoleInstance create(String roleName, String instanceName, InstanceStatus instanceStatus, int instanceUpgradeDomain,
                                         int instanceFaultDomain, RoleSize.Type instanceSize, String ipAddress, String hostname, List<InstanceEndpoint> instanceEndpoints) {
          return new AutoValue_Deployment_RoleInstance(roleName, instanceName, instanceStatus, instanceUpgradeDomain,
-                 instanceFaultDomain, instanceSize, ipAddress, hostname, copyOf(instanceEndpoints));
+                 instanceFaultDomain, instanceSize, ipAddress, hostname, instanceEndpoints == null ? null : copyOf(instanceEndpoints));
       }
    }
 
@@ -175,6 +179,6 @@ public abstract class Deployment {
    public static Deployment create(String name, Slot slot, Status status, String label, String instanceStateDetails, String instanceErrorCode,
                                    List<VirtualIP> virtualIPs, List<RoleInstance> roleInstanceList, List<Role> roles, String virtualNetworkName) {
       return new AutoValue_Deployment(name, slot, status, label, instanceStateDetails,
-              instanceErrorCode, copyOf(virtualIPs), copyOf(roleInstanceList), copyOf(roles), virtualNetworkName);
+              instanceErrorCode, copyOf(virtualIPs), copyOf(roleInstanceList), roles == null ? null : copyOf(roles), virtualNetworkName);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
index 4343452..756634e 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/NetworkSecurityGroup.java
@@ -37,7 +37,7 @@ public abstract class NetworkSecurityGroup {
    @Nullable public abstract List<Rule> rules();
 
    public static NetworkSecurityGroup create(String name, String label, String location, List<Rule> rules) {
-      return new AutoValue_NetworkSecurityGroup(name, label, location, copyOf(rules));
+      return new AutoValue_NetworkSecurityGroup(name, label, location, rules == null ? null : copyOf(rules));
    }
 }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Role.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Role.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Role.java
index bb387ef..5aa94fe 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Role.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Role.java
@@ -61,6 +61,7 @@ public abstract class Role {
 
          public abstract String protocol();
 
+         @Nullable
          public abstract String vip();
 
          public abstract Boolean enableDirectServerReturn();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/features/OSImageApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/OSImageApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/OSImageApi.java
index 42c58a0..a4c7c3b 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/OSImageApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/OSImageApi.java
@@ -61,6 +61,7 @@ public interface OSImageApi {
     */
    @Named("ListImages")
    @GET
+   @Produces(APPLICATION_XML)
    @XMLResponseParser(ListOSImagesHandler.class)
    @Fallback(EmptyListOnNotFoundOr404.class)
    List<OSImage> list();
@@ -71,7 +72,6 @@ public interface OSImageApi {
     */
    @Named("AddImage")
    @POST
-   @Produces(APPLICATION_XML)
    @ResponseParser(ParseRequestIdHeader.class)
    String add(@BinderParam(OSImageParamsToXML.class) OSImageParams params);
 
@@ -81,7 +81,6 @@ public interface OSImageApi {
    @Named("UpdateImage")
    @PUT
    @Path("/{imageName}")
-   @Produces(APPLICATION_XML)
    @ResponseParser(ParseRequestIdHeader.class)
    String update(@PathParam("imageName") @ParamParser(OSImageParamsName.class)
                @BinderParam(OSImageParamsToXML.class) OSImageParams params);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/features/StorageAccountApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/StorageAccountApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/StorageAccountApi.java
index 0a5837c..e60cbcc 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/StorageAccountApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/StorageAccountApi.java
@@ -92,6 +92,6 @@ public interface StorageAccountApi {
    @DELETE
    @Path("/{serviceName}")
    @ResponseParser(ParseRequestIdHeader.class)
-   String delete(String serviceName);
+   String delete(@PathParam("serviceName") String serviceName);
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
index 468b488..5db9b04 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/VirtualMachineApi.java
@@ -31,12 +31,14 @@ import javax.ws.rs.core.MediaType;
 import org.jclouds.azurecompute.binders.RoleToXML;
 import org.jclouds.azurecompute.domain.Role;
 import org.jclouds.azurecompute.functions.ParseRequestIdHeader;
+import org.jclouds.azurecompute.xml.RoleHandler;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.XMLResponseParser;
 
 /**
  * The Service Management API includes operations for managing the virtual
@@ -101,7 +103,7 @@ public interface VirtualMachineApi {
    @GET
    @Path("/roles/{roleName}")
    @Produces(MediaType.APPLICATION_XML)
-   @ResponseParser(ParseRequestIdHeader.class)
+   @XMLResponseParser(RoleHandler.class)
    @Fallback(NullOnNotFoundOr404.class)
    Role getRole(@PathParam("roleName") String roleName);
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/handlers/AzureComputeErrorHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/handlers/AzureComputeErrorHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/handlers/AzureComputeErrorHandler.java
index 1ce14bf..b27d8cd 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/handlers/AzureComputeErrorHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/handlers/AzureComputeErrorHandler.java
@@ -29,8 +29,6 @@ import org.jclouds.rest.ResourceNotFoundException;
 import org.jclouds.util.Closeables2;
 import org.jclouds.util.Strings2;
 
-import com.google.common.base.Throwables;
-
 /**
  * This will parse and set an appropriate exception on the command object.
  */
@@ -72,12 +70,6 @@ public class AzureComputeErrorHandler implements HttpErrorHandler {
          return Strings2.toStringAndClose(response.getPayload().openStream());
       } catch (IOException e) {
          throw new RuntimeException(e);
-      } finally {
-         try {
-            response.getPayload().getInput().close();
-         } catch (IOException e) {
-            Throwables.propagate(e);
-         }
       }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java b/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
new file mode 100644
index 0000000..422072c
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/util/ConflictManagementPredicate.java
@@ -0,0 +1,119 @@
+/*
+ * 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.util;
+
+import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
+
+import com.google.common.base.Predicate;
+import javax.annotation.Resource;
+import javax.inject.Named;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.logging.Logger;
+
+/**
+ * Conflict errors (409 response status code) management predicate.
+ */
+public abstract class ConflictManagementPredicate implements Predicate<String> {
+
+   protected final Predicate<String> operationSucceeded;
+
+   private Long timeout = null;
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private boolean raiseException = false;
+
+   /**
+    * Constructor.
+    *
+    * @param operationSucceeded predicate to be applied to the requestId.
+    */
+   public ConflictManagementPredicate(final Predicate<String> operationSucceeded) {
+      this.operationSucceeded = operationSucceeded;
+   }
+
+   /**
+    * Constructor to be used to raise an IllegalStateException in case of the given predicate evaluation is false.
+    *
+    * @param operationSucceeded predicate to be applied to the requestId.
+    * @param timeout timeout of the predicate.
+    */
+   public ConflictManagementPredicate(
+           final Predicate<String> operationSucceeded,
+           final Long timeout) {
+
+      this.operationSucceeded = operationSucceeded;
+      this.timeout = timeout;
+      this.raiseException = true;
+   }
+
+   /**
+    * Operation to be executed.
+    *
+    * @return requestId.
+    */
+   protected abstract String operation();
+
+   /**
+    * {@inheritDoc }
+    *
+    * @param name interested object/operaton descripton.
+    * @return predicate evaluation.
+    */
+   @Override
+   public final boolean apply(final String name) {
+      try {
+         final String requestId = operation();
+         logger.info("Executed operation on {0}", name);
+
+         if (requestId == null) {
+            return true;
+         }
+
+         final boolean res = operationSucceeded.apply(requestId);
+         if (!res && raiseException) {
+            final String message = generateIllegalStateExceptionMessage(requestId, timeout);
+            logger.warn(message);
+            throw new IllegalStateException(message);
+         } else {
+            return res;
+         }
+      } catch (RuntimeException e) {
+         final HttpResponseException re = (e instanceof HttpResponseException)
+                 ? HttpResponseException.class.cast(e) : (e.getCause() instanceof HttpResponseException)
+                         ? HttpResponseException.class.cast(e.getCause())
+                         : null;
+         if (re == null) {
+            throw e;
+         } else {
+            final HttpResponse res = re.getResponse();
+            logger.info("[{0} (core: {1})] while performing operation on {2}",
+                    new Object[]{res.getStatusLine(), res.getStatusCode(), name});
+            if (res.getStatusCode() == 409) {
+               logger.info("[{0}] Retry operation on {1}", new Object[]{e.getMessage(), name});
+               return false;
+            } else {
+               throw re;
+            }
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/util/NetworkSecurityGroups.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/util/NetworkSecurityGroups.java b/azurecompute/src/main/java/org/jclouds/azurecompute/util/NetworkSecurityGroups.java
index 687da7e..4d81754 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/util/NetworkSecurityGroups.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/util/NetworkSecurityGroups.java
@@ -20,7 +20,6 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
-import org.jclouds.azurecompute.config.AzureComputeProperties;
 import org.jclouds.azurecompute.domain.NetworkSecurityGroup;
 import org.jclouds.azurecompute.domain.Rule;
 
@@ -66,8 +65,8 @@ public class NetworkSecurityGroups {
       return priority;
    }
 
-   public static String createRuleName(int fromPort, int toPort) {
-      return String.format(AzureComputeProperties.TCP_RULE_FORMAT, fromPort, toPort);
+   public static String createRuleName(String format, int fromPort, int toPort) {
+      return String.format(format, fromPort, toPort);
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
index 4c93ece..e8dd075 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/DeploymentHandler.java
@@ -102,6 +102,7 @@ public final class DeploymentHandler extends ParseSax.HandlerForGeneratedRequest
          roleHandler.endElement(ignoredUri, ignoredName, qName);
       } else if (qName.equals("VirtualIPs")) {
          inListVirtualIPs = false;
+      } else if (qName.equals("VirtualIP")) {
          virtualIPs.add(virtualIPHandler.getResult());
       } else if (inListVirtualIPs) {
          virtualIPHandler.endElement(ignoredUri, ignoredName, qName);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java b/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
new file mode 100644
index 0000000..180c0af
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+
+import com.google.auto.service.AutoService;
+import java.net.URI;
+import java.util.Properties;
+import org.jclouds.azurecompute.config.AzureComputeProperties;
+import org.jclouds.providers.ProviderMetadata;
+
+@AutoService(ProviderMetadata.class)
+public class AzureComputeProviderMetadataLive extends AzureComputeProviderMetadata {
+
+   @Override
+   public Builder toBuilder() {
+      return new Builder().fromProviderMetadata(this);
+   }
+
+   public AzureComputeProviderMetadataLive() {
+      super(new Builder());
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = AzureManagementApiMetadata.defaultProperties();
+      properties.setProperty(TEMPLATE, "osFamily=UBUNTU,loginUser=jclouds");
+      properties.setProperty(OPERATION_TIMEOUT, "" + 600 * 1000);
+      properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "" + 5);
+      properties.setProperty(OPERATION_POLL_MAX_PERIOD, "" + 15);
+      properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
+      properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
+      return properties;
+   }
+
+   public AzureComputeProviderMetadataLive(final Builder builder) {
+      super(builder);
+   }
+
+   public static class Builder extends AzureComputeProviderMetadata.Builder {
+
+      protected Builder() {
+         id("azurecompute")
+                 .name("Microsoft Azure Service Management Service")
+                 .apiMetadata(new AzureManagementApiMetadata())
+                 .endpoint("https://management.core.windows.net/SUBSCRIPTION_ID")
+                 .homepage(URI.create("https://www.windowsazure.com/"))
+                 .console(URI.create("https://windows.azure.com/default.aspx"))
+                 .linkedServices("azureblob", "azurequeue", "azuretable")
+                 .iso3166Codes("US-TX", "US-IL", "IE-D", "SG", "NL-NH", "HK")
+                 .defaultProperties(AzureComputeProviderMetadataLive.defaultProperties());
+      }
+
+      @Override
+      public AzureComputeProviderMetadataLive build() {
+         return new AzureComputeProviderMetadataLive(this);
+      }
+
+      @Override
+      public Builder fromProviderMetadata(final ProviderMetadata in) {
+         super.fromProviderMetadata(in);
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/test/java/org/jclouds/azurecompute/AzureTestUtils.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/AzureTestUtils.java b/azurecompute/src/test/java/org/jclouds/azurecompute/AzureTestUtils.java
new file mode 100644
index 0000000..029c6d2
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/AzureTestUtils.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+import com.google.common.base.Predicate;
+import java.util.ArrayList;
+import java.util.List;
+import org.jclouds.azurecompute.domain.NetworkConfiguration;
+import org.jclouds.azurecompute.features.VirtualNetworkApi;
+
+public class AzureTestUtils {
+
+   public static List<NetworkConfiguration.VirtualNetworkSite> getVirtualNetworkSite(AzureComputeApi api) {
+      final VirtualNetworkApi vnapi = api.getVirtualNetworkApi();
+      final NetworkConfiguration netConf = vnapi.getNetworkConfiguration();
+
+      return netConf == null
+              ? new ArrayList<NetworkConfiguration.VirtualNetworkSite>()
+              : new ArrayList<NetworkConfiguration.VirtualNetworkSite>(netConf.virtualNetworkConfiguration().
+                      virtualNetworkSites());
+
+   }
+
+   public static class SameVirtualNetworkSiteNamePredicate
+           implements Predicate<NetworkConfiguration.VirtualNetworkSite> {
+
+      private final String virtualNetworkSiteName;
+
+      public SameVirtualNetworkSiteNamePredicate(final String virtualNetworkSiteName) {
+         this.virtualNetworkSiteName = virtualNetworkSiteName;
+      }
+
+      @Override
+      public boolean apply(final NetworkConfiguration.VirtualNetworkSite input) {
+         return input.name().equals(virtualNetworkSiteName);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c80d40a5/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
index 71eb6a6..8d347e6 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapterLiveTest.java
@@ -16,29 +16,32 @@
  */
 package org.jclouds.azurecompute.compute;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.util.Predicates2.retry;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
 import java.util.Properties;
 import java.util.Random;
 
 import org.jclouds.azurecompute.AzureComputeApi;
 import org.jclouds.azurecompute.domain.Deployment;
-import org.jclouds.azurecompute.domain.Location;
 import org.jclouds.azurecompute.domain.RoleSize;
 import org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest;
 import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
 import org.jclouds.compute.domain.ExecResponse;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.domain.TemplateBuilder;
-import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
-import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
-import org.jclouds.domain.LoginCredentials;
 import org.jclouds.ssh.SshClient;
 import org.jclouds.ssh.SshClient.Factory;
 import org.jclouds.sshj.config.SshjSshClientModule;
-import org.testng.annotations.AfterGroups;
+import org.jclouds.azurecompute.domain.Role;
+import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
+
 import org.testng.annotations.Test;
+import org.testng.annotations.AfterGroups;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -46,18 +49,21 @@ import com.google.common.net.HostAndPort;
 import com.google.common.net.InetAddresses;
 import com.google.inject.Injector;
 import com.google.inject.Module;
+import java.util.Arrays;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
 
 @Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceAdapterLiveTest")
 public class AzureComputeServiceAdapterLiveTest extends BaseAzureComputeApiLiveTest {
 
    private AzureComputeServiceAdapter adapter;
+
    private TemplateBuilder templateBuilder;
+
    private Factory sshFactory;
-   private NodeAndInitialCredentials<Deployment> deployment;
 
    @Override
-   protected AzureComputeApi create(Properties props, Iterable<Module> modules) {
-      Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
+   protected AzureComputeApi create(final Properties props, final Iterable<Module> modules) {
+      final Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
       adapter = injector.getInstance(AzureComputeServiceAdapter.class);
       templateBuilder = injector.getInstance(TemplateBuilder.class);
       sshFactory = injector.getInstance(SshClient.Factory.class);
@@ -66,8 +72,7 @@ public class AzureComputeServiceAdapterLiveTest extends BaseAzureComputeApiLiveT
 
    @Test
    public void testListLocations() {
-      Iterable<Location> locations = adapter.listLocations();
-      assertFalse(Iterables.isEmpty(locations), "locations must not be empty");
+      assertFalse(Iterables.isEmpty(adapter.listLocations()), "locations must not be empty");
    }
 
    @Test
@@ -75,32 +80,65 @@ public class AzureComputeServiceAdapterLiveTest extends BaseAzureComputeApiLiveT
       assertFalse(Iterables.isEmpty(adapter.listImages()), "images must not be empty");
    }
 
-   private static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate(
-         new DefaultCredentialsFromImageOrOverridingCredentials());
-
+   /**
+    * Functionally equivalent to {@link AzureComputeServiceContextLiveTest#testLaunchNode()}.
+    */
    @Test
    public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
-      String group = "foo";
-      String name = "node" + new Random().nextInt();
-
-      Template template = templateBuilder.build();
-
-      deployment = adapter.createNodeWithGroupEncodedIntoName(group, name, template);
-      assertEquals(deployment.getNode().name(), name);
-      assertEquals(deployment.getNodeId(), deployment.getNode().name());
-      assert InetAddresses.isInetAddress(deployment.getNode().virtualIPs().get(0).address()) : deployment;
-      doConnectViaSsh(deployment.getNode(), prioritizeCredentialsFromTemplate.apply(template, deployment.getCredentials()));
-   }
-
-   protected void doConnectViaSsh(Deployment deployment, LoginCredentials creds) {
-      SshClient ssh = sshFactory.create(HostAndPort.fromParts(deployment.virtualIPs().get(0).address(), 22), creds);
+      final String groupName = String.format("%s%d-group-acsalt",
+              System.getProperty("user.name"),
+              new Random(999).nextLong());
+
+      final String name = String.format("%1.5s%dacsalt", System.getProperty("user.name"), new Random(999).nextInt());
+
+      templateBuilder.imageId(BaseAzureComputeApiLiveTest.IMAGE_NAME);
+      templateBuilder.hardwareId("BASIC_A0");
+      templateBuilder.locationId(BaseAzureComputeApiLiveTest.LOCATION);
+      final Template template = templateBuilder.build();
+
+      // test passing custom options
+      final AzureComputeTemplateOptions options = template.getOptions().as(AzureComputeTemplateOptions.class);
+      options.inboundPorts(22);
+      options.storageAccountName(getStorageServiceName());
+      options.virtualNetworkName(VIRTUAL_NETWORK_NAME);
+      options.subnetName(DEFAULT_SUBNET_NAME);
+      options.addressSpaceAddressPrefix(DEFAULT_ADDRESS_SPACE);
+      options.subnetAddressPrefix(DEFAULT_SUBNET_ADDRESS_SPACE);
+      options.nodeNames(Arrays.asList(name));
+
+      NodeAndInitialCredentials<Deployment> deployment = null;
       try {
-         ssh.connect();
-         ExecResponse hello = ssh.exec("echo hello");
+         deployment = adapter.createNodeWithGroupEncodedIntoName(groupName, name, template);
+         assertEquals(deployment.getNode().name(), name);
+         assertEquals(deployment.getNodeId(), deployment.getNode().name());
+         assert InetAddresses.isInetAddress(deployment.getNode().virtualIPs().get(0).address()) : deployment;
+
+         SshClient client = sshFactory.create(
+                 HostAndPort.fromParts(deployment.getNode().virtualIPs().get(0).address(), 22),
+                 deployment.getCredentials());
+         client.connect();
+         ExecResponse hello = client.exec("echo hello");
          assertEquals(hello.getOutput().trim(), "hello");
       } finally {
-         if (ssh != null)
-            ssh.disconnect();
+         if (deployment != null) {
+            final List<Role> roles = api.getDeploymentApiForService(deployment.getNodeId()).
+                    get(deployment.getNodeId()).roles();
+
+            adapter.destroyNode(deployment.getNodeId());
+
+            for (Role role : roles) {
+               final Role.OSVirtualHardDisk disk = role.osVirtualHardDisk();
+               if (disk != null) {
+                  retry(new ConflictManagementPredicate(operationSucceeded) {
+
+                     @Override
+                     protected String operation() {
+                        return api.getDiskApi().delete(disk.diskName());
+                     }
+                  }, 600, 30, 30, SECONDS).apply(disk.diskName());
+               }
+            }
+         }
       }
    }
 
@@ -115,16 +153,14 @@ public class AzureComputeServiceAdapterLiveTest extends BaseAzureComputeApiLiveT
    }
 
    @AfterGroups(groups = "live", alwaysRun = true)
+   @Override
    protected void tearDown() {
-      if (deployment != null) {
-         adapter.destroyNode(deployment.getNodeId());
-      }
       super.tearDown();
    }
 
    @Override
    protected Iterable<Module> setupModules() {
-      return ImmutableSet.<Module> of(getLoggingModule(), new SshjSshClientModule());
+      return ImmutableSet.<Module>of(getLoggingModule(), new SshjSshClientModule());
    }
 
 }