[JCLOUDS-981,JCLOUDS-982] remove Optional from AzureComputeTemplateOptions

- fix reuse of existing storage service during deployment
- use AutoValue.Builder in DeployParams
- make network creation optional
- remove AzureComuteAdapterLiveTest b/c not meaningful
- fix DiskLiveTest
- fix OSImageApiLiveTest
- fix VMImageApiLiveTest
- fix VirtualMachineApiLiveTest
- fix NetworkSecurityGroupApiLiveTest
- fix AzureComputeServiceContextLiveTest.testListSizes
- simplify AzureComputeServiceContextModule
- add AdminUsername to DeploymentParamsToXML for Windows images
- fix NPE in DeploymentToNodeMetadata.status
- add check role status into deployment
- modify deployemtParamsToXml
- fix VM deletion
- fix DeploymentApiMockTest


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

Branch: refs/heads/1.9.x
Commit: a57446a1c4962f80d98e5b9728c66fea01a49c2f
Parents: ea2241d
Author: Andrea Turli <[email protected]>
Authored: Wed Aug 12 12:24:40 2015 +0200
Committer: Andrea Turli <[email protected]>
Committed: Thu Jan 21 11:20:05 2016 +0100

----------------------------------------------------------------------
 azurecompute/README.md                          |   4 +-
 azurecompute/pom.xml                            |   2 +-
 .../AzureComputeProviderMetadata.java           |   3 -
 .../binders/DeploymentParamsToXML.java          |  28 +-
 .../jclouds/azurecompute/binders/RoleToXML.java |   6 +-
 .../compute/AzureComputeServiceAdapter.java     | 221 +++++-----
 .../AzureComputeServiceContextModule.java       |   8 +-
 .../AzureComputeSecurityGroupExtension.java     | 129 +-----
 .../functions/DeploymentToNodeMetadata.java     |  11 +-
 .../compute/functions/RoleSizeToHardware.java   |  31 +-
 .../options/AzureComputeTemplateOptions.java    | 418 +++++++++++++++++++
 .../predicates/StorageServicePredicates.java    |  80 ++++
 ...ServiceAndVirtualNetworkThenCreateNodes.java | 198 ++-------
 .../AzureAdaptingComputeServiceStrategies.java  |  70 ----
 .../jclouds/azurecompute/domain/Deployment.java |   1 +
 .../azurecompute/domain/DeploymentParams.java   | 165 ++------
 .../features/VirtualMachineApi.java             |  13 +
 .../options/AzureComputeTemplateOptions.java    | 344 ---------------
 .../util/ConflictManagementPredicate.java       |   7 +-
 .../AzureComputeProviderMetadataLive.java       |  86 ----
 .../binders/DeploymentParamsToXMLTest.java      |  64 +++
 .../AzureComputeServiceAdapterLiveTest.java     | 177 --------
 .../AzureComputeServiceContextLiveTest.java     | 140 +++----
 .../compute/AzureComputeServiceLiveTest.java    |  30 +-
 .../features/DeploymentApiLiveTest.java         |  22 +-
 .../features/DeploymentApiMockTest.java         |  10 +-
 .../azurecompute/features/DiskApiLiveTest.java  |   3 +-
 .../NetworkSecurityGroupApiLiveTest.java        |  15 +-
 .../features/OSImageApiLiveTest.java            |  17 -
 .../features/VMImageApiLiveTest.java            |  33 +-
 .../features/VirtualMachineApiLiveTest.java     |  41 +-
 .../features/VirtualNetworkApiLiveTest.java     |  35 +-
 .../AbstractAzureComputeApiLiveTest.java        |  26 +-
 .../internal/BaseAzureComputeApiLiveTest.java   |   5 +-
 .../test/resources/deploymentparams-windows.xml |   2 +-
 .../src/test/resources/logback-test.xml         |  34 ++
 azurecompute/src/test/resources/logback.xml     |  34 --
 37 files changed, 1040 insertions(+), 1473 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/azurecompute/README.md
----------------------------------------------------------------------
diff --git a/azurecompute/README.md b/azurecompute/README.md
index 5deca6f..7d251d7 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.
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/azurecompute/pom.xml
----------------------------------------------------------------------
diff --git a/azurecompute/pom.xml b/azurecompute/pom.xml
index 693004b..6ec6d98 100644
--- a/azurecompute/pom.xml
+++ b/azurecompute/pom.xml
@@ -35,7 +35,7 @@
   <properties>
     
<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.endpoint>https://management.core.windows.net/${test.jclouds.azurecompute.subscription-id}</test.azurecompute.endpoint>
     <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>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/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 843e264..731b52f 100644
--- 
a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
@@ -21,8 +21,6 @@ import static 
org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_P
 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 static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
-
 import java.net.URI;
 import java.util.Properties;
 
@@ -50,7 +48,6 @@ public class AzureComputeProviderMetadata extends 
BaseProviderMetadata {
 
    public static Properties defaultProperties() {
       final Properties properties = 
AzureManagementApiMetadata.defaultProperties();
-      properties.setProperty(TEMPLATE, "osFamily=UBUNTU,loginUser=jclouds");
       properties.setProperty(OPERATION_TIMEOUT, "60000");
       properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "5");
       properties.setProperty(OPERATION_POLL_MAX_PERIOD, "15");

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/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 515a5d2..c220551 100644
--- 
a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java
@@ -29,7 +29,6 @@ import com.jamesmurty.utils.XMLBuilder;
 public final class DeploymentParamsToXML implements Binder {
 
    @Override
-   @SuppressWarnings("unchecked")
    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
       DeploymentParams params = DeploymentParams.class.cast(input);
 
@@ -60,6 +59,12 @@ public final class DeploymentParamsToXML implements Binder {
                     .e("JoinDomain").t(params.name()).up()
                     .up() // Domain Join
                     .e("StoredCertificateSettings").up()
+                    .e("WinRM")
+                    .e("Listeners")
+                    .e("Listener")
+                    .e("Protocol").t("http").up().up().up().up()
+                    .e("AdminUsername").t(params.username()).up()
+                    .e("AdminPassword").t(params.username()).up()
                     .up(); // Windows ConfigurationSet
          } else if (params.os() == OSImage.Type.LINUX) {
             XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Linux
@@ -90,12 +95,13 @@ public final class DeploymentParamsToXML implements Binder {
          }
 
          inputEndpoints.up();
-         //configBuilder.e("SubnetNames").up().up();
 
          XMLBuilder subnetNames = configBuilder.e("SubnetNames");
-         for (String subnetName : params.subnetNames()) {
-            subnetNames.e("SubnetName").t(subnetName).up()
-                    .up(); //subnetName
+         if (!params.subnetNames().isEmpty()) {
+            for (String subnetName : params.subnetNames()) {
+               subnetNames.e("SubnetName").t(subnetName).up()
+                       .up(); //subnetName
+            }
          }
 
          builder.up() //ConfigurationSets
@@ -105,21 +111,21 @@ public final class DeploymentParamsToXML implements 
Binder {
                  .e("HostCaching").t("ReadWrite").up()
                  .e("MediaLink").t(params.mediaLink().toASCIIString()).up()
                  // TODO
-                 /// If you are using a VM image, it must be specified as 
VMImageName for the role, 
+                 /// If you are using a VM image, it must be specified as 
VMImageName for the role,
                  // not as SourceImageNamefor 
OSVirtualHardDisk.</Message></Error>]
                  .e("SourceImageName").t(params.sourceImageName()).up()
                  .e("OS").t(params.os() == LINUX ? "Linux" : "Windows").up()
                  .up() //OSVirtualHardDisk
                  .e("RoleSize").t(params.size().getText()).up()
                  .up() //Role
-                 .up() //RoleList
-                 .e("VirtualNetworkName").t(params.virtualNetworkName()).up();
-         
+                 .up(); //RoleList
+         if (params.virtualNetworkName() != null) {
+            
builder.up().up().up().e("VirtualNetworkName").t(params.virtualNetworkName()).up();
+         }
          if (params.reservedIPName() != null) {
             
builder.up().up().up().e("ReservedIPName").t(params.reservedIPName()).up();
          }
-         
-         // TODO: Undeprecate this method as forcing users to wrap a String in 
guava's ByteSource is not great.
+
          return (R) request.toBuilder().payload(builder.asString()).build();
       } catch (Exception e) {
          throw propagate(e);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/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 25c9b11..e5f1b26 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java
@@ -52,8 +52,10 @@ public class RoleToXML implements Binder {
                           .up(); //InputEndpoint
                }
                XMLBuilder subnetNames = configBuilder.e("SubnetNames");
-               for (Role.ConfigurationSet.SubnetName subnetName : 
configurationSet.subnetNames()) {
-                  subnetNames.e("SubnetName").t(subnetName.name()).up();
+               if (!configurationSet.subnetNames().isEmpty()) {
+                  for (Role.ConfigurationSet.SubnetName subnetName : 
configurationSet.subnetNames()) {
+                     subnetNames.e("SubnetName").t(subnetName.name()).up();
+                  }
                }
                if (configurationSet.networkSecurityGroup() != null
                        && !configurationSet.networkSecurityGroup().isEmpty()) {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/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 a045674..ec605ea 100644
--- 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
@@ -16,11 +16,11 @@
  */
 package org.jclouds.azurecompute.compute;
 
+import static com.google.common.base.Objects.firstNonNull;
 import static com.google.common.base.Predicates.notNull;
 import static java.lang.String.format;
 import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.jclouds.util.Predicates2.retry;
-
 import java.net.URI;
 import java.util.List;
 import java.util.Set;
@@ -32,18 +32,19 @@ import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.AzureComputeApi;
 import 
org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
+import org.jclouds.azurecompute.compute.functions.OSImageToImage;
+import org.jclouds.azurecompute.compute.options.AzureComputeTemplateOptions;
 import org.jclouds.azurecompute.config.AzureComputeProperties;
 import org.jclouds.azurecompute.domain.CloudService;
 import org.jclouds.azurecompute.domain.Deployment;
+import org.jclouds.azurecompute.domain.Deployment.RoleInstance;
 import org.jclouds.azurecompute.domain.DeploymentParams;
 import org.jclouds.azurecompute.domain.DeploymentParams.ExternalEndpoint;
 import org.jclouds.azurecompute.domain.Location;
 import org.jclouds.azurecompute.domain.OSImage;
-import org.jclouds.azurecompute.domain.RoleSize;
-import org.jclouds.azurecompute.domain.Deployment.RoleInstance;
 import org.jclouds.azurecompute.domain.Role;
-import org.jclouds.azurecompute.compute.functions.OSImageToImage;
-import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
+import org.jclouds.azurecompute.domain.RoleSize;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.domain.Template;
@@ -59,7 +60,6 @@ import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import org.jclouds.azurecompute.util.ConflictManagementPredicate;
 
 /**
  * Defines the connection between the {@link AzureComputeApi} implementation 
and the jclouds
@@ -71,6 +71,7 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
    private static final String DEFAULT_LOGIN_USER = "jclouds";
 
    private static final String DEFAULT_LOGIN_PASSWORD = "Azur3Compute!";
+   public static final String POST_SHUTDOWN_ACTION = "StoppedDeallocated";
 
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@@ -98,35 +99,30 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
       // azure-specific options
       final AzureComputeTemplateOptions templateOptions = 
template.getOptions().as(AzureComputeTemplateOptions.class);
 
-      final String loginUser = templateOptions.getLoginUser() == null
-              ? DEFAULT_LOGIN_USER : templateOptions.getLoginUser();
-      final String loginPassword = templateOptions.getLoginPassword() == null
-              ? DEFAULT_LOGIN_PASSWORD : templateOptions.getLoginPassword();
+      final String loginUser = firstNonNull(templateOptions.getLoginUser(), 
DEFAULT_LOGIN_USER);
+      final String loginPassword = 
firstNonNull(templateOptions.getLoginPassword(), DEFAULT_LOGIN_PASSWORD);
       final String location = template.getLocation().getId();
       final int[] inboundPorts = template.getOptions().getInboundPorts();
 
-      final String storageAccountName = 
templateOptions.getStorageAccountName().get();
-      final String virtualNetworkName = 
templateOptions.getVirtualNetworkName().get();
-      final String reservedIPAddress = 
templateOptions.getReservedIPName().orNull();
-      final String subnetName = templateOptions.getSubnetName().get();
+      final String storageAccountName = 
templateOptions.getStorageAccountName();
 
-      logger.debug("Creating a cloud service with name '%s', label '%s' in 
location '%s'", name, name, location);
-      final String createCloudServiceRequestId
-              = api.getCloudServiceApi().createWithLabelInLocation(name, name, 
location);
+      String message = String.format("Creating a cloud service with name '%s', 
label '%s' in location '%s'", name, name, location);
+      logger.debug(message);
+      final String createCloudServiceRequestId = 
api.getCloudServiceApi().createWithLabelInLocation(name, name, location);
       if (!operationSucceededPredicate.apply(createCloudServiceRequestId)) {
-         final String message = generateIllegalStateExceptionMessage(
-                 createCloudServiceRequestId, 
azureComputeConstants.operationTimeout());
-         logger.warn(message);
-         throw new IllegalStateException(message);
+         final String exceptionMessage = 
generateIllegalStateExceptionMessage(message, createCloudServiceRequestId, 
azureComputeConstants.operationTimeout());
+         logger.warn(exceptionMessage);
+         throw new IllegalStateException(exceptionMessage);
       }
       logger.info("Cloud Service (%s) created with operation id: %s", name, 
createCloudServiceRequestId);
 
-      final OSImage.Type os = 
template.getImage().getOperatingSystem().getFamily() == OsFamily.WINDOWS
-              ? OSImage.Type.WINDOWS : OSImage.Type.LINUX;
+      final OSImage.Type os = 
template.getImage().getOperatingSystem().getFamily() == OsFamily.WINDOWS ?
+              OSImage.Type.WINDOWS : OSImage.Type.LINUX;
       final Set<ExternalEndpoint> externalEndpoints = Sets.newHashSet();
       for (int inboundPort : inboundPorts) {
          
externalEndpoints.add(ExternalEndpoint.inboundTcpToLocalPort(inboundPort, 
inboundPort));
       }
+
       final DeploymentParams params = DeploymentParams.builder()
               .name(name)
               .os(os)
@@ -136,12 +132,12 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
               .mediaLink(createMediaLink(storageAccountName, name))
               .size(RoleSize.Type.fromString(template.getHardware().getName()))
               .externalEndpoints(externalEndpoints)
-              .subnetName(subnetName)
-              .virtualNetworkName(virtualNetworkName)
-              .reservedIPName(reservedIPAddress)
+              .virtualNetworkName(templateOptions.getVirtualNetworkName())
+              .subnetNames(templateOptions.getSubnetNames())
               .build();
 
-      logger.debug("Creating a deployment with params '%s' ...", params);
+      message = String.format("Creating a deployment with params '%s' ...", 
params);
+      logger.debug(message);
 
       if (!new ConflictManagementPredicate(api) {
          @Override
@@ -149,13 +145,12 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
             return api.getDeploymentApiForService(name).create(params);
          }
       }.apply(name)) {
-         final String message = generateIllegalStateExceptionMessage(
-                 createCloudServiceRequestId, 
azureComputeConstants.operationTimeout());
-         logger.warn(message);
+         final String illegalStateExceptionMessage = 
generateIllegalStateExceptionMessage(message, createCloudServiceRequestId, 
azureComputeConstants.operationTimeout());
+         logger.warn(illegalStateExceptionMessage);
          logger.debug("Deleting cloud service (%s) ...", name);
          deleteCloudService(name);
          logger.debug("Cloud service (%s) deleted.", name);
-         throw new IllegalStateException(message);
+         throw new IllegalStateException(illegalStateExceptionMessage);
       }
 
       logger.info("Deployment created with name: %s", name);
@@ -170,26 +165,24 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
             }
             return !deployments.isEmpty();
          }
-      }, 30 * 60, 1, SECONDS).apply(name)) {
-         final String message = format("Deployment %s was not created within 
%sms so it will be destroyed.",
+      }, azureComputeConstants.operationTimeout(), 1, SECONDS).apply(name)) {
+         final String illegalStateExceptionMessage = format("Deployment %s was 
not created within %sms so it will be destroyed.",
                  name, azureComputeConstants.operationTimeout());
-         logger.warn(message);
+         logger.warn(illegalStateExceptionMessage);
 
          api.getDeploymentApiForService(name).delete(name);
          api.getCloudServiceApi().delete(name);
 
-         throw new IllegalStateException(message);
+         throw new IllegalStateException(illegalStateExceptionMessage);
       }
 
       final Deployment deployment = deployments.iterator().next();
-      return new NodeAndInitialCredentials<Deployment>(deployment, name,
-              
LoginCredentials.builder().user(loginUser).password(loginPassword).build());
-   }
 
-   public static String generateIllegalStateExceptionMessage(final String 
operationId, final long timeout) {
-      final String warnMessage = format("%s has not been completed within 
%sms.", operationId, timeout);
-      return format("%s. Please, try by increasing `%s` and try again",
-              warnMessage, AzureComputeProperties.OPERATION_TIMEOUT);
+      // check if the role inside the deployment is ready
+      checkRoleStatusInDeployment(name, deployment);
+
+      return new NodeAndInitialCredentials<Deployment>(deployment, name,
+              
LoginCredentials.builder().user(loginUser).password(loginPassword).authenticateSudo(true).build());
    }
 
    @Override
@@ -299,67 +292,33 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
    private void trackRequest(final String requestId) {
       if (!operationSucceededPredicate.apply(requestId)) {
          final String message = generateIllegalStateExceptionMessage(
-                 requestId, azureComputeConstants.operationTimeout());
+                 "tracking request", requestId, 
azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);
       }
    }
 
-   private List<CloudService> getCloudServicesForDeployment(final String id) {
-      return FluentIterable.from(api.getCloudServiceApi().list()).filter(new 
Predicate<CloudService>() {
-
-         @Override
-         public boolean apply(final CloudService input) {
-            final Deployment deployment
-                    = input.status() == CloudService.Status.DELETING || 
input.status() == CloudService.Status.DELETED
-                            ? null
-                            : 
api.getDeploymentApiForService(input.name()).get(id);
-            return deployment != null && deployment.status() != 
Deployment.Status.DELETING;
-         }
-      }).toList();
-   }
-
-   public Deployment internalDestroyNode(final String id) {
-      Deployment deployment = null;
-
-      for (CloudService cloudService : getCloudServicesForDeployment(id)) {
-         final List<Deployment> nodes = Lists.newArrayList();
-         retry(new Predicate<String>() {
-            @Override
-            public boolean apply(final String input) {
-               final Deployment deployment = getNode(id);
-               if (deployment != null) {
-                  nodes.add(deployment);
-               }
-               return !nodes.isEmpty();
-            }
-         }, 30 * 60, 1, SECONDS).apply(id);
+   public Deployment internalDestroyNode(final String nodeId) {
 
-         if (!nodes.isEmpty()) {
-            deployment = nodes.iterator().next();
-         }
+      Deployment deployment = getDeploymentFromNodeId(nodeId);
 
-         final String cloudServiceName = cloudService.name();
-         logger.debug("Deleting deployment(%s) of cloud service (%s)", id, 
cloudServiceName);
+      if (deployment == null) return null;
 
-         if (!new ConflictManagementPredicate(api, 
operationSucceededPredicate) {
+      final String deploymentName = deployment.name();
+      String message = String.format("Deleting deployment(%s) of cloud service 
(%s)", nodeId, deploymentName);
+      logger.debug(message);
 
-            @Override
-            protected String operation() {
-               return 
api.getDeploymentApiForService(cloudServiceName).delete(id);
+         if (deployment != null) {
+            for (Role role : deployment.roleList()) {
+               
trackRequest(api.getVirtualMachineApiForDeploymentInService(deploymentName, 
role.roleName()).shutdown(nodeId, POST_SHUTDOWN_ACTION));
             }
-         }.apply(id)) {
-            final String message = generateIllegalStateExceptionMessage(
-                    "Delete deployment", 
azureComputeConstants.operationTimeout());
-            logger.warn(message);
-            throw new IllegalStateException(message);
-         }
 
-         logger.debug("Deleting cloud service (%s) ...", cloudServiceName);
-         trackRequest(api.getCloudServiceApi().delete(cloudServiceName));
-         logger.debug("Cloud service (%s) deleted.", cloudServiceName);
+            deleteDeployment(deploymentName, nodeId);
+
+            logger.debug("Deleting cloud service (%s) ...", deploymentName);
+            trackRequest(api.getCloudServiceApi().delete(deploymentName));
+            logger.debug("Cloud service (%s) deleted.", deploymentName);
 
-         if (deployment != null) {
             for (Role role : deployment.roleList()) {
                final Role.OSVirtualHardDisk disk = role.osVirtualHardDisk();
                if (disk != null) {
@@ -369,22 +328,41 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
                      protected String operation() {
                         return api.getDiskApi().delete(disk.diskName());
                      }
-                  }.apply(id)) {
-                     final String message = 
generateIllegalStateExceptionMessage(
+                  }.apply(nodeId)) {
+                     final String illegalStateExceptionMessage = 
generateIllegalStateExceptionMessage("Delete disk " + disk.diskName(),
                              "Delete disk", 
azureComputeConstants.operationTimeout());
-                     logger.warn(message);
+                     logger.warn(illegalStateExceptionMessage);
                   }
                }
             }
          }
-      }
-
       return deployment;
    }
 
+   public Deployment getDeploymentFromNodeId(final String nodeId) {
+      final List<Deployment> nodes = Lists.newArrayList();
+      retry(new Predicate<String>() {
+         @Override
+         public boolean apply(final String input) {
+            final Deployment deployment = getNode(nodeId);
+            if (deployment != null) {
+               nodes.add(deployment);
+            }
+            return !nodes.isEmpty();
+         }
+      }, 30 * 60, 1, SECONDS).apply(nodeId);
+
+      return Iterables.getFirst(nodes, null);
+   }
+
    @Override
    public void destroyNode(final String id) {
-      internalDestroyNode(id);
+      logger.debug("Destroying %s ...", id);
+      if (internalDestroyNode(id) != null) {
+         logger.debug("Destroyed %s!", id);
+      } else {
+         logger.warn("Can't destroy %s!", id);
+      }
    }
 
    @Override
@@ -412,7 +390,7 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
       final CloudService cloudService = api.getCloudServiceApi().get(id);
       if (cloudService != null) {
          logger.debug("Suspending %s ...", id);
-         trackRequest(api.getVirtualMachineApiForDeploymentInService(id, 
cloudService.name()).shutdown(id));
+         trackRequest(api.getVirtualMachineApiForDeploymentInService(id, 
cloudService.name()).shutdown(id, POST_SHUTDOWN_ACTION));
          logger.debug("Suspended %s", id);
       }
    }
@@ -455,7 +433,7 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
          }
 
       }.apply(name)) {
-         final String deleteMessage = generateIllegalStateExceptionMessage(
+         final String deleteMessage = 
generateIllegalStateExceptionMessage("Delete cloud service " + name,
                  "CloudService delete", 
azureComputeConstants.operationTimeout());
          logger.warn(deleteMessage);
          throw new IllegalStateException(deleteMessage);
@@ -471,10 +449,53 @@ public class AzureComputeServiceAdapter implements 
ComputeServiceAdapter<Deploym
          }
 
       }.apply(id)) {
-         final String deleteMessage = generateIllegalStateExceptionMessage(
+         final String deleteMessage = 
generateIllegalStateExceptionMessage("Delete deployment " + cloudServiceName,
                  "Deployment delete", 
azureComputeConstants.operationTimeout());
          logger.warn(deleteMessage);
          throw new IllegalStateException(deleteMessage);
       }
    }
+
+
+   private void checkRoleStatusInDeployment(final String name, Deployment 
deployment) {
+      if (!retry(new Predicate<Deployment>() {
+
+         @Override
+         public boolean apply(Deployment deployment) {
+            deployment = 
api.getDeploymentApiForService(deployment.name()).get(name);
+            if (deployment.roleInstanceList() == null || 
deployment.roleInstanceList().isEmpty()) return false;
+            return Iterables.all(deployment.roleInstanceList(), new 
Predicate<RoleInstance>() {
+               @Override
+               public boolean apply(RoleInstance input) {
+                  if (input.instanceStatus() == 
Deployment.InstanceStatus.PROVISIONING_FAILED) {
+                     final String message = format("Deployment %s is in 
provisioning failed status, so it will be destroyed.", name);
+                     logger.warn(message);
+
+                     api.getDeploymentApiForService(name).delete(name);
+                     api.getCloudServiceApi().delete(name);
+
+                     throw new IllegalStateException(message);
+                  }
+                  return input.instanceStatus() == 
Deployment.InstanceStatus.READY_ROLE;
+               }
+            });
+         }
+      }, azureComputeConstants.operationTimeout(), 1, 
SECONDS).apply(deployment)) {
+         final String message = format("Role %s has not reached the READY_ROLE 
within %sms so it will be destroyed.",
+                 deployment.name(), azureComputeConstants.operationTimeout());
+         logger.warn(message);
+
+         api.getDeploymentApiForService(name).delete(name);
+         api.getCloudServiceApi().delete(name);
+
+         throw new IllegalStateException(message);
+      }
+   }
+
+   public static String generateIllegalStateExceptionMessage(String prefix, 
final String operationId, final long timeout) {
+      final String warnMessage = format("%s - %s has not been completed within 
%sms.", prefix, operationId, timeout);
+      return format("%s. Please, try by increasing `%s` and try again",
+              warnMessage, AzureComputeProperties.OPERATION_TIMEOUT);
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/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 1e07798..a8ae3a3 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
@@ -32,14 +32,14 @@ import 
org.jclouds.azurecompute.compute.functions.DeploymentToNodeMetadata;
 import org.jclouds.azurecompute.compute.functions.LocationToLocation;
 import org.jclouds.azurecompute.compute.functions.OSImageToImage;
 import org.jclouds.azurecompute.compute.functions.RoleSizeToHardware;
+import org.jclouds.azurecompute.compute.options.AzureComputeTemplateOptions;
 import 
org.jclouds.azurecompute.compute.strategy.GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes;
 import 
org.jclouds.azurecompute.compute.strategy.UseNodeCredentialsButOverrideFromTemplate;
-import 
org.jclouds.azurecompute.compute.strategy.impl.AzureAdaptingComputeServiceStrategies;
 import org.jclouds.azurecompute.domain.Deployment;
 import org.jclouds.azurecompute.domain.Location;
 import org.jclouds.azurecompute.domain.OSImage;
 import org.jclouds.azurecompute.domain.RoleSize;
-import org.jclouds.azurecompute.options.AzureComputeTemplateOptions;
+import org.jclouds.azurecompute.util.ConflictManagementPredicate;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
 import org.jclouds.compute.domain.Hardware;
@@ -47,7 +47,6 @@ import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
 import org.jclouds.compute.options.TemplateOptions;
 import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
-import org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies;
 import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
 
 import com.google.common.base.Function;
@@ -59,7 +58,6 @@ import com.google.inject.Provides;
 import com.google.inject.TypeLiteral;
 
 import java.util.concurrent.TimeUnit;
-import org.jclouds.azurecompute.util.ConflictManagementPredicate;
 
 public class AzureComputeServiceContextModule
         extends ComputeServiceAdapterContextModule<Deployment, RoleSize, 
OSImage, Location> {
@@ -76,8 +74,6 @@ public class AzureComputeServiceContextModule
       }).to(RoleSizeToHardware.class);
       bind(new TypeLiteral<Function<Deployment, NodeMetadata>>() {
       }).to(DeploymentToNodeMetadata.class);
-      bind(new TypeLiteral<AdaptingComputeServiceStrategies<Deployment, 
RoleSize, OSImage, Location>>() {
-      }).to(AzureAdaptingComputeServiceStrategies.class);
 
       
bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class);
       bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/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 8848127..f24c5fe 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,7 @@
 package org.jclouds.azurecompute.compute.extensions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-
+import static 
org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
 import java.util.List;
 import java.util.Set;
 
@@ -27,16 +27,14 @@ import javax.inject.Named;
 
 import org.jclouds.azurecompute.AzureComputeApi;
 import 
org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
-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.azurecompute.util.NetworkSecurityGroups;
 import org.jclouds.compute.domain.SecurityGroup;
 import org.jclouds.compute.domain.SecurityGroupBuilder;
 import org.jclouds.compute.extensions.SecurityGroupExtension;
@@ -48,12 +46,10 @@ import org.jclouds.net.domain.IpProtocol;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
 import com.google.common.base.Splitter;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
-import static 
org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage;
 
 /**
  * An extension to compute service to allow for the manipulation of {@link 
org.jclouds.compute.domain.SecurityGroup}s.
@@ -154,7 +150,7 @@ public class AzureComputeSecurityGroupExtension implements 
SecurityGroupExtensio
               name, name, location.getId(), null, null);
       final String createNSGRequestId = 
api.getNetworkSecurityGroupApi().create(networkSecurityGroup);
       if (!operationSucceededPredicate.apply(createNSGRequestId)) {
-         final String message = generateIllegalStateExceptionMessage(
+         final String message = generateIllegalStateExceptionMessage("Create 
NSG" + name,
                  createNSGRequestId, azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);
@@ -195,7 +191,7 @@ public class AzureComputeSecurityGroupExtension implements 
SecurityGroupExtensio
                                    virtualNetworkName, subnetName, id);
                         }
                      }.apply(id)) {
-                        final String message = 
generateIllegalStateExceptionMessage(
+                        final String message = 
generateIllegalStateExceptionMessage("Remove NSG" + id + " from subnet " + 
subnetName,
                                 "Remove security group from subnet", 
azureComputeConstants.operationTimeout());
                         logger.warn(message);
                         throw new IllegalStateException(message);
@@ -225,59 +221,6 @@ public class AzureComputeSecurityGroupExtension implements 
SecurityGroupExtensio
       // add rule to NSG
       addRuleToNetworkSecurityGroup(id, ruleName, priority, ipPermission);
 
-      // add endpoint to VM
-      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.roleList()) {
-                  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()));
-                     }
-                  }
-
-                  if (!new ConflictManagementPredicate(api, 
operationSucceededPredicate) {
-
-                     @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);
-                        }
-                     }
-                  }.apply(role.roleName())) {
-                     final String message = 
generateIllegalStateExceptionMessage(
-                             "Operation", 
azureComputeConstants.operationTimeout());
-                     logger.warn(message);
-                     throw new IllegalStateException(message);
-                  }
-               }
-            }
-         }
-      }
-
       return transformNetworkSecurityGroupToSecurityGroup(id);
    }
 
@@ -315,50 +258,6 @@ public class AzureComputeSecurityGroupExtension implements 
SecurityGroupExtensio
       // remove rule to NSG
       removeRuleFromNetworkSecurityGroup(id, ruleName);
 
-      // TODO remove endpoint from VM
-      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.roleList()) {
-                  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));
-                     }
-                  }
-
-                  if (!new ConflictManagementPredicate(api, 
operationSucceededPredicate) {
-                     @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);
-                        }
-                     }
-                  }.apply(role.roleName())) {
-                     final String message = 
generateIllegalStateExceptionMessage(
-                             "Operation", 
azureComputeConstants.operationTimeout());
-                     logger.warn(message);
-                     throw new IllegalStateException(message);
-                  }
-               }
-            }
-         }
-      }
-
       return transformNetworkSecurityGroupToSecurityGroup(id);
    }
 
@@ -473,7 +372,7 @@ public class AzureComputeSecurityGroupExtension implements 
SecurityGroupExtensio
                               destinationPortRange, // destinationPortRange
                               Rule.Protocol.fromString(protocol)));
       if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
-         final String message = generateIllegalStateExceptionMessage(
+         final String message = generateIllegalStateExceptionMessage("Add rule 
" + ruleName,
                  setRuleToNSGRequestId, 
azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);
@@ -483,27 +382,11 @@ public class AzureComputeSecurityGroupExtension 
implements SecurityGroupExtensio
    private void removeRuleFromNetworkSecurityGroup(final String id, final 
String ruleName) {
       String setRuleToNSGRequestId = 
api.getNetworkSecurityGroupApi().deleteRule(id, ruleName);
       if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) {
-         final String message = generateIllegalStateExceptionMessage(
+         final String message = generateIllegalStateExceptionMessage("Remove 
rule " + ruleName,
                  setRuleToNSGRequestId, 
azureComputeConstants.operationTimeout());
          logger.warn(message);
          throw new IllegalStateException(message);
       }
    }
 
-   private Role.ConfigurationSet.InputEndpoint createInputEndpoint(
-           final String ruleName, final String protocol, final String address, 
final int port) {
-
-      return Role.ConfigurationSet.InputEndpoint.create(
-              ruleName,
-              protocol,
-              port,
-              port,
-              address,
-              false, // enabledDirectServerReturn
-              null, // loadBalancerName
-              null, // loadBalancerProbe
-              null //idleTimeoutInMinutes
-      );
-   }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
index cfe1ece..b26532b 100644
--- 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.azurecompute.compute.functions;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import java.util.Map;
 import java.util.Set;
 
 import javax.inject.Inject;
 
 import org.jclouds.azurecompute.AzureComputeApi;
+import org.jclouds.azurecompute.domain.CloudService;
 import org.jclouds.azurecompute.domain.Deployment;
 import org.jclouds.azurecompute.domain.Deployment.RoleInstance;
-import org.jclouds.azurecompute.domain.CloudService;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.NodeMetadataBuilder;
@@ -35,7 +36,6 @@ import org.jclouds.location.predicates.LocationPredicates;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Supplier;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
@@ -53,6 +53,7 @@ public class DeploymentToNodeMetadata implements 
Function<Deployment, NodeMetada
            put(Deployment.InstanceStatus.FAILED_STARTING_ROLE, 
NodeMetadata.Status.ERROR).
            put(Deployment.InstanceStatus.FAILED_STARTING_VM, 
NodeMetadata.Status.ERROR).
            put(Deployment.InstanceStatus.PREPARING, 
NodeMetadata.Status.PENDING).
+           put(Deployment.InstanceStatus.PROVISIONING, 
NodeMetadata.Status.PENDING).
            put(Deployment.InstanceStatus.READY_ROLE, 
NodeMetadata.Status.RUNNING).
            put(Deployment.InstanceStatus.RESTARTING_ROLE, 
NodeMetadata.Status.PENDING).
            put(Deployment.InstanceStatus.STARTING_ROLE, 
NodeMetadata.Status.PENDING).
@@ -97,7 +98,7 @@ public class DeploymentToNodeMetadata implements 
Function<Deployment, NodeMetada
            RoleSizeToHardware roleSizeToHardware, Map<String, Credentials> 
credentialStore) {
 
       this.nodeNamingConvention = namingConvention.createWithoutPrefix();
-      this.locations = Preconditions.checkNotNull(locations, "locations");
+      this.locations = checkNotNull(locations, "locations");
       this.osImageToImage = osImageToImage;
       this.roleSizeToHardware = roleSizeToHardware;
       this.credentialStore = credentialStore;
@@ -135,11 +136,13 @@ public class DeploymentToNodeMetadata implements 
Function<Deployment, NodeMetada
        */
       if (from.status() != null) {
          final Optional<RoleInstance> roleInstance = 
tryFindFirstRoleInstanceInDeployment(from);
-         if (roleInstance.isPresent()) {
+         if (roleInstance.isPresent() && roleInstance.get().instanceStatus() 
!= null) {
             
builder.status(INSTANCESTATUS_TO_NODESTATUS.get(roleInstance.get().instanceStatus()));
          } else {
             builder.status(STATUS_TO_NODESTATUS.get(from.status()));
          }
+      } else {
+         builder.status(NodeMetadata.Status.UNRECOGNIZED);
       }
 
       final Set<String> publicIpAddresses = Sets.newLinkedHashSet();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
----------------------------------------------------------------------
diff --git 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
index fd844c4..5421531 100644
--- 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java
@@ -20,6 +20,8 @@ import org.jclouds.azurecompute.domain.RoleSize;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.HardwareBuilder;
 import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.VolumeBuilder;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
@@ -34,29 +36,12 @@ public class RoleSizeToHardware implements 
Function<RoleSize, Hardware> {
               hypervisor("Hyper-V").
               processors(ImmutableList.of(new Processor(from.cores(), 2))).
               ram(from.memoryInMb());
-
-      // TODO volumes
-               /*
-       * if (from.s() != null) {
-       * builder.volumes(
-       * FluentIterable.from(from.getVirtualGuestBlockDevices()).filter(new 
Predicate<VirtualGuestBlockDevice>() {
-       * @Override
-       * public boolean apply(VirtualGuestBlockDevice input) {
-       * return input.getMountType().equals("Disk");
-       * }
-       * })
-       * .transform(new Function<VirtualGuestBlockDevice, Volume>() {
-       * @Override
-       * public Volume apply(VirtualGuestBlockDevice item) {
-       * float volumeSize = item.getVirtualDiskImage().getCapacity();
-       * return new VolumeImpl(
-       * item.getId() + "",
-       * from.isLocalDiskFlag() ? Volume.Type.LOCAL : Volume.Type.SAN,
-       * volumeSize, null, item.getBootableFlag() == 1, false);
-       * }
-       * }).toSet());
-       * }
-       */
+      if (from.virtualMachineResourceDiskSizeInMb() != null) {
+         builder.volume(new VolumeBuilder()
+                 
.size(Float.valueOf(from.virtualMachineResourceDiskSizeInMb()))
+                 .type(Volume.Type.LOCAL)
+                 .build());
+      }
       return builder.build();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java
----------------------------------------------------------------------
diff --git 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java
 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java
new file mode 100644
index 0000000..ed31e71
--- /dev/null
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java
@@ -0,0 +1,418 @@
+/*
+ * 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.compute.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.scriptbuilder.domain.Statement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Contains options supported by the {@link 
org.jclouds.compute.ComputeService#createNodesInGroup(
+ * String, int, org.jclouds.compute.options.TemplateOptions)} operation.
+ *
+ * <h2>Usage</h2> The recommended way to instantiate a {@link 
AzureComputeTemplateOptions} object is to statically
+ * import {@code AzureComputeTemplateOptions.*} and invoke a static creation 
method followed by an instance mutator (if
+ * needed):
+ * <p>
+ *
+ * <pre>
+ * import static 
org.jclouds.compute.options.AzureComputeTemplateOptions.Builder.*;
+ * ComputeService client = // get connection
+ * templateBuilder.options(inboundPorts(22, 80, 8080, 443));
+ * Set&lt;? extends NodeMetadata&gt; set = client.createNodesInGroup(tag, 2, 
templateBuilder.build());
+ * </pre>
+ *
+ */
+public class AzureComputeTemplateOptions extends TemplateOptions implements 
Cloneable {
+
+   protected String virtualNetworkName;
+   protected List<String> subnetNames = ImmutableList.of();
+   protected String storageAccountName;
+   protected String storageAccountType;
+   protected String networkSecurityGroupName;
+   protected String reservedIPName;
+
+   @Override
+   public AzureComputeTemplateOptions clone() {
+      final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+      copyTo(options);
+      return options;
+   }
+
+   @Override
+   public void copyTo(final TemplateOptions to) {
+      super.copyTo(to);
+      if (to instanceof AzureComputeTemplateOptions) {
+         final AzureComputeTemplateOptions eTo = 
AzureComputeTemplateOptions.class.cast(to);
+         eTo.virtualNetworkName(virtualNetworkName);
+         if (!subnetNames.isEmpty()) {
+            eTo.subnetNames(subnetNames);
+         }
+         eTo.storageAccountName(storageAccountName);
+         eTo.storageAccountType(storageAccountType);
+         eTo.reservedIPName(reservedIPName);
+      }
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (!(o instanceof AzureComputeTemplateOptions)) return false;
+      if (!super.equals(o)) return false;
+
+      AzureComputeTemplateOptions that = (AzureComputeTemplateOptions) o;
+
+      if (networkSecurityGroupName != null ? 
!networkSecurityGroupName.equals(that.networkSecurityGroupName) : 
that.networkSecurityGroupName != null)
+         return false;
+      if (reservedIPName != null ? !reservedIPName.equals(that.reservedIPName) 
: that.reservedIPName != null) return false;
+      if (storageAccountName != null ? 
!storageAccountName.equals(that.storageAccountName) : that.storageAccountName 
!= null) return false;
+      if (storageAccountType != null ? 
!storageAccountType.equals(that.storageAccountType) : that.storageAccountType 
!= null) return false;
+      if (subnetNames != null ? !subnetNames.equals(that.subnetNames) : 
that.subnetNames != null) return false;
+      if (virtualNetworkName != null ? 
!virtualNetworkName.equals(that.virtualNetworkName) : that.virtualNetworkName 
!= null) return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      int result = super.hashCode();
+      result = 31 * result + (virtualNetworkName != null ? 
virtualNetworkName.hashCode() : 0);
+      result = 31 * result + (subnetNames != null ? subnetNames.hashCode() : 
0);
+      result = 31 * result + (storageAccountName != null ? 
storageAccountName.hashCode() : 0);
+      result = 31 * result + (storageAccountType != null ? 
storageAccountType.hashCode() : 0);
+      result = 31 * result + (networkSecurityGroupName != null ? 
networkSecurityGroupName.hashCode() : 0);
+      result = 31 * result + (reservedIPName != null ? 
reservedIPName.hashCode() : 0);
+      return result;
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this)
+              .add("virtualNetworkName", virtualNetworkName)
+              .add("subnetNames", subnetNames)
+              .add("storageAccountName", storageAccountName)
+              .add("storageAccountType", storageAccountType)
+              .add("networkSecurityGroupName", networkSecurityGroupName)
+              .add("reservedIPName", reservedIPName)
+              .toString();
+   }
+
+   public AzureComputeTemplateOptions virtualNetworkName(@Nullable String 
virtualNetworkName) {
+      this.virtualNetworkName = virtualNetworkName;
+      return this;
+   }
+
+   public AzureComputeTemplateOptions subnetNames(Iterable<String> 
subnetNames) {
+      this.subnetNames = ImmutableList.copyOf(checkNotNull(subnetNames, 
"subnetNames"));
+      return this;
+   }
+
+   public AzureComputeTemplateOptions subnetNames(String...subnetNames) {
+      return subnetNames(ImmutableList.copyOf(checkNotNull(subnetNames, 
"subnetNames")));
+   }
+
+
+   public AzureComputeTemplateOptions networkSecurityGroupName(@Nullable 
String networkSecurityGroupName) {
+      this.networkSecurityGroupName = networkSecurityGroupName;
+      return this;
+   }
+
+   public AzureComputeTemplateOptions storageAccountName(@Nullable String 
storageAccountName) {
+      this.storageAccountName = storageAccountName;
+      return this;
+   }
+
+   public AzureComputeTemplateOptions storageAccountType(@Nullable String 
storageAccountType) {
+      this.storageAccountType = storageAccountType;
+      return this;
+   }
+
+   public AzureComputeTemplateOptions reservedIPName(@Nullable String 
reservedIPName) {
+      this.reservedIPName = reservedIPName;
+      return this;
+   }
+
+   public String getVirtualNetworkName() {
+      return virtualNetworkName;
+   }
+
+   public List<String> getSubnetNames() {
+      return subnetNames;
+   }
+
+   public String getStorageAccountName() {
+      return storageAccountName;
+   }
+
+   public String getStorageAccountType() {
+      return storageAccountType;
+   }
+
+   public String getNetworkSecurityGroupName() {
+      return networkSecurityGroupName;
+   }
+
+   public String getReservedIPName() {
+      return reservedIPName;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see #virtualNetworkName
+       */
+      public static AzureComputeTemplateOptions virtualNetworkName(final 
String virtualNetworkName) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.virtualNetworkName(virtualNetworkName);
+      }
+
+      /**
+       * @see #subnetNames
+       */
+      public static AzureComputeTemplateOptions 
subnetNames(String...subnetNames) {
+         AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.subnetNames(subnetNames);
+      }
+
+      /**
+       * @see #subnetNames
+       */
+      public static AzureComputeTemplateOptions subnetNames(Iterable<String> 
subnetNames) {
+         AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.subnetNames(subnetNames);
+      }
+
+      /**
+       * @see #storageAccountName
+       */
+      public static AzureComputeTemplateOptions storageAccountName(final 
String storageAccountName) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.storageAccountName(storageAccountName);
+      }
+
+      /**
+       * @see #storageAccountType
+       */
+      public static AzureComputeTemplateOptions storageAccountType(final 
String storageAccountType) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.storageAccountType(storageAccountType);
+      }
+
+      /**
+       * @see org.jclouds.compute.options.TemplateOptions#inboundPorts(int...)
+       */
+      public static AzureComputeTemplateOptions inboundPorts(final int... 
ports) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.inboundPorts(ports);
+      }
+
+      /**
+       * @see org.jclouds.compute.options.TemplateOptions#blockOnPort(int, int)
+       */
+      public static AzureComputeTemplateOptions blockOnPort(final int port, 
final int seconds) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.blockOnPort(port, seconds);
+      }
+
+      /**
+       * @see 
org.jclouds.compute.options.TemplateOptions#userMetadata(java.util.Map)
+       */
+      public static AzureComputeTemplateOptions userMetadata(final Map<String, 
String> userMetadata) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.userMetadata(userMetadata);
+      }
+
+      /**
+       * @see org.jclouds.compute.options.TemplateOptions#userMetadata(String, 
String)
+       */
+      public static AzureComputeTemplateOptions userMetadata(final String key, 
final String value) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.userMetadata(key, value);
+      }
+
+      /**
+       * @see org.jclouds.compute.options.TemplateOptions#nodeNames(Iterable)
+       */
+      public static AzureComputeTemplateOptions nodeNames(final 
Iterable<String> nodeNames) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.nodeNames(nodeNames);
+      }
+
+      /**
+       * @see org.jclouds.compute.options.TemplateOptions#networks(Iterable)
+       */
+      public static AzureComputeTemplateOptions networks(final 
Iterable<String> networks) {
+         final AzureComputeTemplateOptions options = new 
AzureComputeTemplateOptions();
+         return options.networks(networks);
+      }
+   }
+
+   // methods that only facilitate returning the correct object type
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions blockOnPort(int port, int seconds) {
+      return AzureComputeTemplateOptions.class.cast(super.blockOnPort(port, 
seconds));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions inboundPorts(int... ports) {
+      return AzureComputeTemplateOptions.class.cast(super.inboundPorts(ports));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions authorizePublicKey(String publicKey) {
+      return 
AzureComputeTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions installPrivateKey(String privateKey) {
+      return 
AzureComputeTemplateOptions.class.cast(super.installPrivateKey(privateKey));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions blockUntilRunning(boolean 
blockUntilRunning) {
+      return 
AzureComputeTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions dontAuthorizePublicKey() {
+      return 
AzureComputeTemplateOptions.class.cast(super.dontAuthorizePublicKey());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions nameTask(String name) {
+      return AzureComputeTemplateOptions.class.cast(super.nameTask(name));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions runAsRoot(boolean runAsRoot) {
+      return 
AzureComputeTemplateOptions.class.cast(super.runAsRoot(runAsRoot));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions runScript(Statement script) {
+      return AzureComputeTemplateOptions.class.cast(super.runScript(script));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions 
overrideLoginCredentials(LoginCredentials overridingCredentials) {
+      return 
AzureComputeTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions overrideLoginPassword(String password) {
+      return 
AzureComputeTemplateOptions.class.cast(super.overrideLoginPassword(password));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions overrideLoginPrivateKey(String 
privateKey) {
+      return 
AzureComputeTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions overrideLoginUser(String loginUser) {
+      return 
AzureComputeTemplateOptions.class.cast(super.overrideLoginUser(loginUser));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions overrideAuthenticateSudo(boolean 
authenticateSudo) {
+      return 
AzureComputeTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions userMetadata(Map<String, String> 
userMetadata) {
+      return 
AzureComputeTemplateOptions.class.cast(super.userMetadata(userMetadata));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions userMetadata(String key, String value) {
+      return AzureComputeTemplateOptions.class.cast(super.userMetadata(key, 
value));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions nodeNames(Iterable<String> nodeNames) {
+      return 
AzureComputeTemplateOptions.class.cast(super.nodeNames(nodeNames));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public AzureComputeTemplateOptions networks(Iterable<String> networks) {
+      return AzureComputeTemplateOptions.class.cast(super.networks(networks));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a57446a1/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java
----------------------------------------------------------------------
diff --git 
a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java
 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java
new file mode 100644
index 0000000..4b8d3f2
--- /dev/null
+++ 
b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java
@@ -0,0 +1,80 @@
+/*
+ * 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.compute.predicates;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+
+import org.jclouds.azurecompute.domain.StorageService;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Predicates for working with {@link StorageService} collections.
+ */
+public class StorageServicePredicates {
+
+
+   public static Predicate<StorageService> sameLocation(final String location) 
{
+      checkNotNull(location, "location must be defined");
+
+      return new Predicate<StorageService>() {
+         @Override
+         public boolean apply(StorageService storageService) {
+            return 
storageService.storageServiceProperties().location().equals(location);
+         }
+
+         @Override
+         public String toString() {
+            return "sameLocation(" + location + ")";
+         }
+      };
+   }
+
+   public static Predicate<StorageService> status(final StorageService.Status 
status) {
+      checkNotNull(status, "status must be defined");
+
+      return new Predicate<StorageService>() {
+         @Override
+         public boolean apply(StorageService storageService) {
+            return storageService.storageServiceProperties().status() == 
status;
+         }
+
+         @Override
+         public String toString() {
+            return "status(" + status + ")";
+         }
+      };
+   }
+
+   public static Predicate<StorageService> matchesName(final String 
defaultStorageAccountPrefix) {
+      checkNotNull(defaultStorageAccountPrefix, "defaultStorageAccountPrefix 
must be defined");
+
+      return new Predicate<StorageService>() {
+         @Override
+         public boolean apply(StorageService storageService) {
+            return 
storageService.serviceName().matches(format("^%s[a-z]{10}$", 
defaultStorageAccountPrefix));
+         }
+
+         @Override
+         public String toString() {
+            return "matchesName(" + defaultStorageAccountPrefix + ")";
+         }
+      };
+   }
+
+}

Reply via email to