Refactored Azure ARM to not use Deployments * Simplified ImageExtension * Fixed access to deployed VMS * Made api-version configurable for all apis" * Fixed all feature live tests * Fixed the AzureComputeServiceLiveTest * Fixed the AzureTemplateBuilderLiveTest * Fixed the AzureComputeImageExtensionLiveTest
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/2f110387 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/2f110387 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/2f110387 Branch: refs/heads/master Commit: 2f110387381c4778c68c2287f616193d6474bd5f Parents: 5742745 Author: Andrea Turli <andrea.tu...@gmail.com> Authored: Wed Sep 28 18:20:26 2016 +0200 Committer: Ignasi Barrera <n...@apache.org> Committed: Fri Oct 14 11:43:00 2016 +0200 ---------------------------------------------------------------------- azurecompute-arm/README.md | 6 +- azurecompute-arm/pom.xml | 7 +- .../azurecompute/arm/AzureComputeApi.java | 17 +- .../arm/AzureComputeProviderMetadata.java | 68 ++- .../arm/compute/AzureComputeServiceAdapter.java | 348 ++++++----- .../AzureComputeServiceContextModule.java | 143 +++-- .../extensions/AzureComputeImageExtension.java | 178 +++--- .../functions/DeploymentToNodeMetadata.java | 244 -------- .../functions/DeploymentToVMDeployment.java | 121 ---- .../ResourceDefinitionToCustomImage.java | 78 +++ .../arm/compute/functions/VMImageToImage.java | 76 +-- .../functions/VirtualMachineToNodeMetadata.java | 279 +++++++++ .../compute/options/AzureTemplateOptions.java | 54 +- .../predicates/IsDeploymentInRegions.java | 1 + ...DefaultLoginCredentialsForImageStrategy.java | 43 -- .../CreateResourceGroupThenCreateNodes.java | 97 +++- .../arm/config/AzureComputeHttpApiModule.java | 3 - .../arm/config/AzureComputeProperties.java | 9 +- .../azurecompute/arm/domain/VMDeployment.java | 38 +- .../azurecompute/arm/domain/VMImage.java | 43 +- .../azurecompute/arm/domain/VirtualMachine.java | 7 +- .../arm/domain/VirtualMachineInstance.java | 51 +- .../arm/domain/VirtualMachineProperties.java | 27 +- .../arm/features/DeploymentApi.java | 5 +- .../azurecompute/arm/features/JobApi.java | 7 +- .../azurecompute/arm/features/LocationApi.java | 7 +- .../arm/features/NetworkInterfaceCardApi.java | 31 +- .../arm/features/NetworkSecurityGroupApi.java | 46 +- .../arm/features/NetworkSecurityRuleApi.java | 38 +- .../azurecompute/arm/features/OSImageApi.java | 5 +- .../arm/features/PublicIPAddressApi.java | 29 +- .../arm/features/ResourceGroupApi.java | 19 +- .../arm/features/ResourceProviderApi.java | 24 +- .../arm/features/StorageAccountApi.java | 35 +- .../azurecompute/arm/features/SubnetApi.java | 33 +- .../azurecompute/arm/features/VMSizeApi.java | 20 +- .../arm/features/VirtualMachineApi.java | 35 +- .../arm/features/VirtualNetworkApi.java | 35 +- .../arm/filters/ApiVersionFilter.java | 90 +++ .../arm/functions/CleanupResources.java | 210 ++++--- .../StorageProfileToStorageAccountName.java | 38 ++ .../azurecompute/arm/util/BlobHelper.java | 86 ++- .../arm/util/DeploymentTemplateBuilder.java | 573 ------------------- .../azurecompute/arm/util/GetEnumValue.java | 1 - .../compute/AzureComputeServiceLiveTest.java | 76 ++- .../compute/AzureTemplateBuilderLiveTest.java | 49 +- .../AzureComputeImageExtensionLiveTest.java | 69 +-- .../arm/features/DeploymentApiLiveTest.java | 92 ++- .../features/DeploymentTemplateBuilderTest.java | 287 ---------- .../NetworkSecurityGroupApiMockTest.java | 2 - .../features/PublicIPAddressApiMockTest.java | 3 +- .../features/ResourceProviderAPIMockTest.java | 1 - .../arm/features/StorageAccountApiMockTest.java | 35 -- .../arm/features/SubnetApiMockTest.java | 17 +- .../TemplateToDeploymentTemplateLiveTest.java | 281 --------- .../arm/features/VirtualMachineApiLiveTest.java | 71 +-- .../arm/features/VirtualMachineApiMockTest.java | 47 +- .../arm/features/VirtualNetworkApiMockTest.java | 2 +- .../arm/filters/ApiVersionFilterTest.java | 129 +++++ .../internal/BaseAzureComputeApiMockTest.java | 19 +- 60 files changed, 1881 insertions(+), 2604 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/README.md ---------------------------------------------------------------------- diff --git a/azurecompute-arm/README.md b/azurecompute-arm/README.md index b1c0916..a5a9956 100644 --- a/azurecompute-arm/README.md +++ b/azurecompute-arm/README.md @@ -32,8 +32,7 @@ azure ad app create --name <name> --password <password> --home-page <home-page> # Create a Service Principal azure ad sp create <Application-id> -# Output will include a value for `Object Id` - +# Output will include a value for `Object Id`, to be used in the next step ``` Run the following commands to assign roles to the service principal @@ -58,7 +57,8 @@ mvn -Dtest=<name of the live test> \ -Dtest.azurecompute-arm.identity="<Application-id>" \ -Dtest.azurecompute-arm.credential="<password>" \ -Dtest.azurecompute-arm.endpoint="https://management.azure.com/subscriptions/<Subscription-id>" \ - -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test + -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" + integration-test -Plive ``` http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/pom.xml ---------------------------------------------------------------------- diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml index df5b835..824e552 100644 --- a/azurecompute-arm/pom.xml +++ b/azurecompute-arm/pom.xml @@ -46,7 +46,7 @@ <dependency> <groupId>org.apache.jclouds</groupId> <artifactId>jclouds-compute</artifactId> - <version>${project.parent.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>com.google.auto.service</groupId> @@ -80,11 +80,6 @@ <groupId>org.apache.jclouds</groupId> <artifactId>jclouds-compute</artifactId> <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.jclouds</groupId> - <artifactId>jclouds-compute</artifactId> - <version>${project.version}</version> <type>test-jar</type> <scope>test</scope> </dependency> http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java index 42749cf..c0c0994 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeApi.java @@ -16,28 +16,27 @@ */ package org.jclouds.azurecompute.arm; +import java.io.Closeable; + +import javax.ws.rs.PathParam; + import org.jclouds.azurecompute.arm.features.DeploymentApi; -import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder; import org.jclouds.azurecompute.arm.features.JobApi; import org.jclouds.azurecompute.arm.features.LocationApi; import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi; +import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; +import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi; import org.jclouds.azurecompute.arm.features.OSImageApi; import org.jclouds.azurecompute.arm.features.PublicIPAddressApi; import org.jclouds.azurecompute.arm.features.ResourceGroupApi; import org.jclouds.azurecompute.arm.features.ResourceProviderApi; import org.jclouds.azurecompute.arm.features.StorageAccountApi; import org.jclouds.azurecompute.arm.features.SubnetApi; +import org.jclouds.azurecompute.arm.features.VMSizeApi; import org.jclouds.azurecompute.arm.features.VirtualMachineApi; import org.jclouds.azurecompute.arm.features.VirtualNetworkApi; -import org.jclouds.azurecompute.arm.features.VMSizeApi; -import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; -import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi; import org.jclouds.rest.annotations.Delegate; -import com.google.inject.Provides; -import javax.ws.rs.PathParam; -import java.io.Closeable; - /** * The Azure Resource Manager API is a REST API for managing your services and deployments. * <p> @@ -165,6 +164,4 @@ public interface AzureComputeApi extends Closeable { @Delegate ResourceProviderApi getResourceProviderApi(); - @Provides - DeploymentTemplateBuilder.Factory deploymentTemplateFactory(); } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java index 460df67..a434079 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java @@ -17,31 +17,47 @@ package org.jclouds.azurecompute.arm; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; - -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN; - +import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO; +import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER; +import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET; -import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE; import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; +import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE; import java.net.URI; import java.util.Properties; + import org.jclouds.azurecompute.arm.domain.Region; +import org.jclouds.azurecompute.arm.features.DeploymentApi; +import org.jclouds.azurecompute.arm.features.LocationApi; +import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi; +import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; +import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi; +import org.jclouds.azurecompute.arm.features.OSImageApi; +import org.jclouds.azurecompute.arm.features.PublicIPAddressApi; +import org.jclouds.azurecompute.arm.features.ResourceGroupApi; +import org.jclouds.azurecompute.arm.features.ResourceProviderApi; +import org.jclouds.azurecompute.arm.features.StorageAccountApi; +import org.jclouds.azurecompute.arm.features.SubnetApi; +import org.jclouds.azurecompute.arm.features.VMSizeApi; +import org.jclouds.azurecompute.arm.features.VirtualMachineApi; +import org.jclouds.azurecompute.arm.features.VirtualNetworkApi; +import org.jclouds.compute.config.ComputeServiceProperties; import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.internal.BaseProviderMetadata; -import org.jclouds.compute.config.ComputeServiceProperties; - -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import com.google.auto.service.AutoService; @@ -72,13 +88,37 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata { properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}"); properties.put(RESOURCE, "https://management.azure.com/"); properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); - properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup"); + properties.put(RESOURCE_GROUP_NAME, "jclouds"); properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16"); properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24"); properties.put(DEFAULT_DATADISKSIZE, "100"); properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat"); - properties.put(DEFAULT_IMAGE_LOGIN, "jclouds:Password1!"); + // Default credentials for all images + properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!"); + properties.put(IMAGE_AUTHENTICATE_SUDO, "true"); + properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS"); properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000); + // Api versions used in each API + properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01"); + properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01"); + properties.put(API_VERSION_PREFIX + NetworkInterfaceCardApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + NetworkSecurityGroupApi.class.getSimpleName(), "2016-03-30"); + properties.put(API_VERSION_PREFIX + NetworkSecurityRuleApi.class.getSimpleName(), "2016-03-30"); + properties.put(API_VERSION_PREFIX + OSImageApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + PublicIPAddressApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + ResourceGroupApi.class.getSimpleName(), "2015-01-01"); + properties.put(API_VERSION_PREFIX + ResourceProviderApi.class.getSimpleName(), "2015-01-01"); + properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), STORAGE_API_VERSION); + properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2015-06-15"); + properties.put(API_VERSION_PREFIX + "GetVirtualMachine", "2016-03-30"); + properties.put(API_VERSION_PREFIX + "GetVirtualMachineInstance", "2016-03-30"); + properties.put(API_VERSION_PREFIX + "CreateVirtualMachine", "2016-03-30"); + properties.put(API_VERSION_PREFIX + "ListVirtualMachines", "2015-06-15"); + properties.put(API_VERSION_PREFIX + "DeleteVirtualMachine", "2016-03-30"); + return properties; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java index 61807a9..0e2ed64 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java @@ -17,164 +17,139 @@ package org.jclouds.azurecompute.arm.compute; import static com.google.common.base.Preconditions.checkState; -import static java.lang.String.format; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.jclouds.util.Predicates2.retry; +import static com.google.common.collect.Iterables.contains; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.find; +import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME; +import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER; +import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId; +import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom; +import static org.jclouds.util.Closeables2.closeQuietly; -import java.util.Collection; import java.util.List; import java.util.Set; -import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; -import org.jclouds.azurecompute.arm.compute.functions.DeploymentToVMDeployment; -import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; -import org.jclouds.azurecompute.arm.compute.predicates.IsDeploymentInRegions; -import org.jclouds.azurecompute.arm.domain.Deployment; -import org.jclouds.azurecompute.arm.domain.DeploymentBody; -import org.jclouds.azurecompute.arm.domain.DeploymentProperties; +import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; +import org.jclouds.azurecompute.arm.domain.DataDisk; +import org.jclouds.azurecompute.arm.domain.HardwareProfile; +import org.jclouds.azurecompute.arm.domain.IdReference; +import org.jclouds.azurecompute.arm.domain.ImageReference; +import org.jclouds.azurecompute.arm.domain.IpConfiguration; +import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties; import org.jclouds.azurecompute.arm.domain.Location; +import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; +import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties; +import org.jclouds.azurecompute.arm.domain.NetworkProfile; +import org.jclouds.azurecompute.arm.domain.OSDisk; +import org.jclouds.azurecompute.arm.domain.OSProfile; import org.jclouds.azurecompute.arm.domain.Offer; +import org.jclouds.azurecompute.arm.domain.PublicIPAddress; +import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties; import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.SKU; +import org.jclouds.azurecompute.arm.domain.StorageProfile; import org.jclouds.azurecompute.arm.domain.StorageService; -import org.jclouds.azurecompute.arm.domain.VMDeployment; +import org.jclouds.azurecompute.arm.domain.StorageService.Status; +import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; +import org.jclouds.azurecompute.arm.domain.VHD; import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMSize; -import org.jclouds.azurecompute.arm.domain.Value; import org.jclouds.azurecompute.arm.domain.Version; -import org.jclouds.azurecompute.arm.features.DeploymentApi; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; +import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.features.OSImageApi; +import org.jclouds.azurecompute.arm.features.PublicIPAddressApi; import org.jclouds.azurecompute.arm.functions.CleanupResources; import org.jclouds.azurecompute.arm.util.BlobHelper; -import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder; import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.domain.LoginCredentials; import org.jclouds.location.Region; -import org.jclouds.logging.Logger; import com.google.common.base.Function; +import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import com.google.common.net.UrlEscapers; /** * Defines the connection between the {@link AzureComputeApi} implementation and the jclouds * {@link org.jclouds.compute.ComputeService}. */ @Singleton -public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location> { +public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> { - private String azureGroup; - protected final CleanupResources cleanupResources; - - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - private Logger logger = Logger.NULL; + private final String azureGroup; + private final CleanupResources cleanupResources; private final AzureComputeApi api; private final AzureComputeConstants azureComputeConstants; private final Supplier<Set<String>> regionIds; - private final IsDeploymentInRegions isDeploymentInRegions; - private final DeploymentToVMDeployment deploymentToVMDeployment; + private final Predicate<String> publicIpAvailable; @Inject AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants, CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds, - IsDeploymentInRegions isDeploymentInRegions, DeploymentToVMDeployment deploymentToVMDeployment) { + @Named("PublicIpAvailable") Predicate<String> publicIpAvailable) { this.api = api; this.azureComputeConstants = azureComputeConstants; this.azureGroup = azureComputeConstants.azureResourceGroup(); - - logger.debug("AzureComputeServiceAdapter set azuregroup to: " + azureGroup); - this.cleanupResources = cleanupResources; this.regionIds = regionIds; - this.isDeploymentInRegions = isDeploymentInRegions; - this.deploymentToVMDeployment = deploymentToVMDeployment; + this.publicIpAvailable = publicIpAvailable; } @Override - public NodeAndInitialCredentials<VMDeployment> createNodeWithGroupEncodedIntoName( + public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName( final String group, final String name, final Template template) { - DeploymentTemplateBuilder deploymentTemplateBuilder = api.deploymentTemplateFactory().create(group, name, template); - - final String loginUser = DeploymentTemplateBuilder.getLoginUserUsername(); - final String loginPassword = DeploymentTemplateBuilder.getLoginPassword(); - - DeploymentBody deploymentTemplateBody = deploymentTemplateBuilder.getDeploymentTemplate(); - - DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody); - - final String deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplateBuilder.getDeploymentTemplateJson(properties)); - - logger.debug("Deployment created with name: %s group: %s", name, group); - - - final Set<VMDeployment> deployments = Sets.newHashSet(); - - final DeploymentApi deploymentApi = api.getDeploymentApi(azureGroup); - - if (!retry(new Predicate<String>() { - @Override - public boolean apply(final String name) { - Deployment deployment = deploymentApi.create(name, deploymentTemplate); - - if (deployment != null) { - VMDeployment vmDeployment = VMDeployment.create(deployment); - deployments.add(vmDeployment); - } else { - logger.debug("Failed to create deployment!"); - } - return !deployments.isEmpty(); - } - }, 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(illegalStateExceptionMessage); - destroyNode(name); - throw new IllegalStateException(illegalStateExceptionMessage); - } - final VMDeployment deployment = deployments.iterator().next(); - NodeAndInitialCredentials<VMDeployment> credential; - if (template.getOptions().getPublicKey() != null){ - String privateKey = template.getOptions().getPrivateKey(); - credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name, - LoginCredentials.builder().user(loginUser).privateKey(privateKey).authenticateSudo(true).build()); - } else { - credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name, - LoginCredentials.builder().user(loginUser).password(loginPassword).authenticateSudo(true).build()); - } - return credential; + AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class); + + // TODO Store group apart from the name to be able to identify nodes with custom names in the configured group + // TODO ARM specific options + // TODO user metadata and tags + // TODO network ids => create one nic in each network + // TODO inbound ports + + String locationName = template.getLocation().getId(); + String subnetId = templateOptions.getSubnetId(); + NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName); + StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob()); + HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build(); + OSProfile osProfile = createOsProfile(name, template); + NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build(); + VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder() + .licenseType(null) // TODO + .availabilitySet(null) // TODO + .hardwareProfile(hardwareProfile) + .storageProfile(storageProfile) + .osProfile(osProfile) + .networkProfile(networkProfile) + .build(); + + VirtualMachine virtualMachine = api.getVirtualMachineApi(azureGroup).create(name, template.getLocation().getId(), virtualMachineProperties); + + // Safe to pass null credentials here, as jclouds will default populate the node with the default credentials from the image, or the ones in the options, if provided. + return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, name, null); } @Override public Iterable<VMHardware> listHardwareProfiles() { - final List<VMHardware> hwProfiles = Lists.newArrayList(); - final List<String> locationIds = Lists.newArrayList(); - - Iterable<Location> locations = listLocations(); - for (Location location : locations){ - locationIds.add(location.name()); - + for (Location location : listLocations()) { Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list(); - for (VMSize vmSize : vmSizes){ VMHardware hwProfile = VMHardware.create( vmSize.name(), @@ -188,22 +163,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo hwProfiles.add(hwProfile); } } - - checkAndSetHwAvailability(hwProfiles, Sets.newHashSet(locationIds)); - return hwProfiles; } - private void checkAndSetHwAvailability(List<VMHardware> hwProfiles, Collection<String> locations) { - Multimap<String, String> hwMap = ArrayListMultimap.create(); - for (VMHardware hw : hwProfiles) { - hwMap.put(hw.name(), hw.location()); - } - - /// TODO - // for (VMHardware hw : hwProfiles) { - // hw.globallyAvailable() = hwMap.get(hw.name()).containsAll(locations); - // } - } private List<VMImage> getImagesFromPublisher(String publisherName, String location) { List<VMImage> osImagesRef = Lists.newArrayList(); @@ -216,7 +177,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo for (SKU sku : skuList) { Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name()); for (Version version : versionList) { - VMImage vmImage = VMImage.create(publisherName, offer.name(), sku.name(), version.name(), location); + VMImage vmImage = VMImage.azureImage().publisher(publisherName).offer(offer.name()).sku(sku.name()) + .version(version.name()).location(location).build(); osImagesRef.add(vmImage); } } @@ -235,7 +197,6 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo @Override public Iterable<VMImage> listImages() { - final List<VMImage> osImages = Lists.newArrayList(); for (Location location : listLocations()){ @@ -245,24 +206,51 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo List<StorageService> storages = api.getStorageAccountApi(azureGroup).list(); for (StorageService storage : storages) { String name = storage.name(); - String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1(); - List<VMImage> images = BlobHelper.getImages("jclouds", azureGroup, storage.name(), key, - "custom", storage.location()); - osImages.addAll(images); + StorageService storageService = api.getStorageAccountApi(azureGroup).get(name); + if (storageService != null + && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) { + String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1(); + BlobHelper blobHelper = new BlobHelper(storage.name(), key); + try { + List<VMImage> images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER, + storage.location()); + osImages.addAll(images); + } finally { + closeQuietly(blobHelper); + } + } } + return osImages; } @Override public VMImage getImage(final String id) { - VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id); + VMImage image = decodeFieldsFromUniqueId(id); if (image.custom()) { - String key = api.getStorageAccountApi(azureGroup).getKeys(image.storage()).key1(); - if (BlobHelper.customImageExists(image.storage(), key)) - return image; - else + VMImage customImage = null; + StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(image.storage()); + if (keys == null) { + // If the storage account for the image does not exist, it means the image was deleted return null; - + } + + BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1()); + try { + if (blobHelper.customImageExists()) { + List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup, + CUSTOM_IMAGE_OFFER, image.location()); + customImage = find(customImagesInStorage, new Predicate<VMImage>() { + @Override + public boolean apply(VMImage input) { + return id.equals(encodeFieldsToUniqueIdCustom(input)); + } + }, null); + } + } finally { + closeQuietly(blobHelper); + } + return customImage; } String location = image.location(); @@ -273,7 +261,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo OSImageApi osImageApi = api.getOSImageApi(location); List<Version> versions = osImageApi.listVersions(publisher, offer, sku); if (!versions.isEmpty()) { - return VMImage.create(publisher, offer, sku, versions.get(0).name(), location); + return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(versions.get(0).name()) + .location(location).build(); } return null; } @@ -313,13 +302,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } @Override - public VMDeployment getNode(final String id) { - Deployment deployment = api.getDeploymentApi(azureGroup).get(id); - if (deployment == null) return null; - if (isDeploymentInRegions.apply(deployment)) { - return deploymentToVMDeployment.apply(deployment); - } - return null; + public VirtualMachine getNode(final String id) { + return api.getVirtualMachineApi(azureGroup).get(id); } @Override @@ -343,29 +327,99 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } @Override - public Iterable<VMDeployment> listNodes() { - return FluentIterable.from(api.getDeploymentApi(azureGroup).list()) - .filter(isDeploymentInRegions) - .filter(new Predicate<Deployment>() { - @Override - public boolean apply(Deployment deployment) { - Value storageAccountNameValue = deployment.properties().parameters().get("storageAccountName"); - String storageAccountName = storageAccountNameValue.value(); - String key = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName).key1(); - return !BlobHelper.customImageExists(storageAccountName, key); - } - }) - .transform(deploymentToVMDeployment) - .toList(); + public Iterable<VirtualMachine> listNodes() { + return api.getVirtualMachineApi(azureGroup).list(); } @Override - public Iterable<VMDeployment> listNodesByIds(final Iterable<String> ids) { - return Iterables.filter(listNodes(), new Predicate<VMDeployment>() { + public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) { + return filter(listNodes(), new Predicate<VirtualMachine>() { @Override - public boolean apply(final VMDeployment input) { - return Iterables.contains(ids, input.deployment().name()); + public boolean apply(VirtualMachine virtualMachine) { + return contains(ids, virtualMachine.id()); } }); } + + + private OSProfile createOsProfile(String computerName, Template template) { + String defaultLoginUser = template.getImage().getDefaultCredentials().getUser(); + String defaultLoginPassword = template.getImage().getDefaultCredentials().getOptionalPassword().get(); + String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser); + String adminPassword = Objects.firstNonNull(template.getOptions().getLoginPassword(), defaultLoginPassword); + OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).computerName(computerName); + // prefer public key over password + if (template.getOptions().getPublicKey() != null) { + OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true", + OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of( + OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create( + String.format("/home/%s/.ssh/authorized_keys", adminUsername), + template.getOptions().getPublicKey()) + )) + ); + builder.linuxConfiguration(linuxConfiguration); + } else { + builder.adminPassword(adminPassword); + } + return builder.build(); + } + + private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, String name, String locationName) { + final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup); + + PublicIPAddressProperties properties = + PublicIPAddressProperties.builder() + .publicIPAllocationMethod("Static") + .idleTimeoutInMinutes(4) + .build(); + + String publicIpAddressName = "public-address-" + name; + PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("jclouds", name), properties); + + checkState(publicIpAvailable.apply(publicIpAddressName), + "Public IP was not provisioned in the configured timeout"); + + final NetworkInterfaceCardProperties networkInterfaceCardProperties = + NetworkInterfaceCardProperties.builder() + .ipConfigurations(ImmutableList.of( + IpConfiguration.builder() + .name("ipConfig-" + name) + .properties(IpConfigurationProperties.builder() + .privateIPAllocationMethod("Dynamic") + .publicIPAddress(IdReference.create(ip.id())) + .subnet(IdReference.create(subnetId)) + .build()) + .build())) + .build(); + + String networkInterfaceCardName = "jc-nic-" + name; + return api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, ImmutableMap.of("jclouds", name)); + } + + private StorageProfile createStorageProfile(String name, Image image, String blob) { + VMImage imageRef = decodeFieldsFromUniqueId(image.getId()); + ImageReference imageReference = null; + VHD sourceImage = null; + String osType = null; + + if (!imageRef.custom()) { + imageReference = ImageReference.builder() + .publisher(image.getProviderId()) + .offer(image.getName()) + .sku(image.getVersion()) + .version("latest") + .build(); + } else { + sourceImage = VHD.create(image.getProviderId()); + + // TODO: read the ostype from the image blob + OsFamily osFamily = image.getOperatingSystem().getFamily(); + osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux"; + } + + VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd"); + OSDisk osDisk = OSDisk.create(osType, name, vhd, "ReadWrite", "FromImage", sourceImage); + + return StorageProfile.create(imageReference, osDisk, ImmutableList.<DataDisk>of()); + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java index 6033f42..24f02ea 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java @@ -16,10 +16,27 @@ */ package org.jclouds.azurecompute.arm.compute.config; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; +import static org.jclouds.util.Predicates2.retry; + import java.net.URI; import java.util.List; -import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Singleton; @@ -27,19 +44,21 @@ import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.AzureComputeService; import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter; import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension; -import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata; import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation; +import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage; import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware; import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; +import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; -import org.jclouds.azurecompute.arm.compute.strategy.AzurePopulateDefaultLoginCredentialsForImageStrategy; import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes; import org.jclouds.azurecompute.arm.domain.Location; +import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; -import org.jclouds.azurecompute.arm.domain.VMDeployment; import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMImage; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; +import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState; import org.jclouds.azurecompute.arm.functions.ParseJobStatus; import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceAdapter; @@ -47,13 +66,12 @@ import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement; +import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey; import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; -import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; -import org.jclouds.logging.Logger; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -61,53 +79,37 @@ import com.google.common.base.Predicate; import com.google.inject.Inject; import com.google.inject.Provides; import com.google.inject.TypeLiteral; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; -import static org.jclouds.util.Predicates2.retry; +import com.google.inject.assistedinject.FactoryModuleBuilder; public class AzureComputeServiceContextModule - extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> { - - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; + extends ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, Location> { @Override protected void configure() { super.configure(); - bind(new TypeLiteral<ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location>>() { + + bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location>>() { }).to(AzureComputeServiceAdapter.class); + bind(new TypeLiteral<Function<VMImage, org.jclouds.compute.domain.Image>>() { }).to(VMImageToImage.class); bind(new TypeLiteral<Function<VMHardware, Hardware>>() { }).to(VMHardwareToHardware.class); - bind(new TypeLiteral<Function<VMDeployment, NodeMetadata>>() { - }).to(DeploymentToNodeMetadata.class); + bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() { + }).to(VirtualMachineToNodeMetadata.class); bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() { }).to(LocationToLocation.class); bind(ComputeService.class).to(AzureComputeService.class); - install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() { + + install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VMHardware, VMImage, Location>() { }); + + install(new FactoryModuleBuilder().build(ResourceDefinitionToCustomImage.Factory.class)); bind(TemplateOptions.class).to(AzureTemplateOptions.class); - bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(AzurePopulateDefaultLoginCredentialsForImageStrategy.class); - //bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class); + bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class); bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class); + bind(new TypeLiteral<ImageExtension>() { }).to(AzureComputeImageExtension.class); } @@ -143,10 +145,6 @@ public class AzureComputeServiceContextModule @Inject private String azureImagePublishersProperty; - @Named(DEFAULT_IMAGE_LOGIN) - @Inject - private String azureDefaultImageLoginProperty; - @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) @Inject private String azureDefaultVnetAddressPrefixProperty; @@ -171,10 +169,6 @@ public class AzureComputeServiceContextModule return azureImagePublishersProperty; } - public String azureDefaultImageLogin() { - return azureDefaultImageLoginProperty; - } - public String azureDefaultVnetAddressPrefixProperty() { return azureDefaultVnetAddressPrefixProperty; } @@ -205,6 +199,14 @@ public class AzureComputeServiceContextModule } @Provides + @com.google.inject.name.Named(TIMEOUT_NODE_RUNNING) + protected Predicate<String> provideVirtualMachineRunningPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, PollPeriod pollPeriod) { + String azureGroup = azureComputeConstants.azureResourceGroup(); + return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.RUNNING), timeouts.nodeRunning, + pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); + } + + @Provides @Named(TIMEOUT_NODE_TERMINATED) protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, Timeouts timeouts, PollPeriod pollPeriod) { return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod, @@ -230,7 +232,17 @@ public class AzureComputeServiceContextModule protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, PollPeriod pollPeriod) { String azureGroup = azureComputeConstants.azureResourceGroup(); - return retry(new NodeSuspendedPredicate(api, azureGroup), timeouts.nodeSuspended, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); + return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.STOPPED), timeouts.nodeTerminated, + pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); + } + + @Provides + @Named("PublicIpAvailable") + protected Predicate<String> providePublicIpAvailablePredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, + Timeouts timeouts, PollPeriod pollPeriod) { + String azureGroup = azureComputeConstants.azureResourceGroup(); + return retry(new PublicIpAvailablePredicate(api, azureGroup), azureComputeConstants.operationTimeout(), + azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod()); } @VisibleForTesting @@ -269,30 +281,45 @@ public class AzureComputeServiceContextModule } @VisibleForTesting - static class NodeSuspendedPredicate implements Predicate<String> { + static class VirtualMachineInStatePredicate implements Predicate<String> { private final AzureComputeApi api; private final String azureGroup; + private final PowerState powerState; - public NodeSuspendedPredicate(AzureComputeApi api, String azureGroup) { + public VirtualMachineInStatePredicate(AzureComputeApi api, String azureGroup, PowerState powerState) { this.api = checkNotNull(api, "api must not be null"); this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null"); + this.powerState = checkNotNull(powerState, "powerState must not be null"); } @Override public boolean apply(String name) { checkNotNull(name, "name cannot be null"); - String status = ""; - VirtualMachineInstance virtualMachineInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name); - if (virtualMachineInstance == null) return false; - List<VirtualMachineInstance.VirtualMachineStatus> statuses = virtualMachineInstance.statuses(); - for (int c = 0; c < statuses.size(); c++) { - if (statuses.get(c).code().substring(0, 10).equals("PowerState")) { - status = statuses.get(c).displayStatus(); - break; - } - } - return status.equals("VM stopped"); + VirtualMachineInstance vmInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name); + if (vmInstance == null) return false; + return powerState == vmInstance.powerState(); } } + + @VisibleForTesting + static class PublicIpAvailablePredicate implements Predicate<String> { + + private final AzureComputeApi api; + private final String azureGroup; + + public PublicIpAvailablePredicate(AzureComputeApi api, String azureGroup) { + this.api = checkNotNull(api, "api must not be null"); + this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null"); + } + + @Override + public boolean apply(String name) { + checkNotNull(name, "name cannot be null"); + PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name); + if (publicIp == null) return false; + return publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded"); + } + } + } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java index 786c17a..99c9c6c 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java @@ -16,141 +16,137 @@ */ package org.jclouds.azurecompute.arm.compute.extensions; -import com.google.common.base.Predicate; -import com.google.common.base.Supplier; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.UncheckedTimeoutException; -import com.google.gson.internal.LinkedTreeMap; -import com.google.inject.Inject; -import com.google.inject.name.Named; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; +import static org.jclouds.util.Closeables2.closeQuietly; + +import java.net.URI; +import java.util.List; +import java.util.concurrent.Callable; + +import javax.annotation.Resource; + import org.jclouds.Constants; -import org.jclouds.View; import org.jclouds.azurecompute.arm.AzureComputeApi; -import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; -import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; +import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; +import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.VMImage; -import org.jclouds.azurecompute.arm.domain.VirtualMachine; -import static java.lang.String.format; +import org.jclouds.azurecompute.arm.functions.CleanupResources; import org.jclouds.azurecompute.arm.util.BlobHelper; import org.jclouds.compute.domain.CloneImageTemplate; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.ImageTemplate; import org.jclouds.compute.domain.ImageTemplateBuilder; import org.jclouds.compute.extensions.ImageExtension; -import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; +import com.google.common.base.Predicate; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.inject.Inject; +import com.google.inject.name.Named; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; +public class AzureComputeImageExtension implements ImageExtension { + public static final String CONTAINER_NAME = "jclouds"; + public static final String CUSTOM_IMAGE_OFFER = "custom"; + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; -public class AzureComputeImageExtension implements ImageExtension { private final AzureComputeApi api; - private final ListeningExecutorService userExecutor; - private final Supplier<View> blobstore = null; private final String group; + private final ListeningExecutorService userExecutor; private final Predicate<URI> imageAvailablePredicate; private final Predicate<String> nodeSuspendedPredicate; - private final AzureComputeConstants azureComputeConstants; - private final VMImageToImage imageReferenceToImage; - public static final String CONTAINER_NAME = "jclouds"; - public static final String CUSTOM_IMAGE_PREFIX = "#"; + private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage; + private final CleanupResources cleanupResources; @Inject AzureComputeImageExtension(AzureComputeApi api, - @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate, - @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate, - final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, - @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, - VMImageToImage imageReferenceToImage) { - this.userExecutor = userExecutor; - this.group = azureComputeConstants.azureResourceGroup(); - this.imageReferenceToImage = imageReferenceToImage; + @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate, + @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate, + AzureComputeConstants azureComputeConstants, + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, + ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources) { + this.api = api; this.imageAvailablePredicate = imageAvailablePredicate; this.nodeSuspendedPredicate = nodeSuspendedPredicate; - this.azureComputeConstants = azureComputeConstants; - this.api = api; + this.group = azureComputeConstants.azureResourceGroup(); + this.userExecutor = userExecutor; + this.resourceDefinitionToImage = resourceDefinitionToImage; + this.cleanupResources = cleanupResources; } @Override public ImageTemplate buildImageTemplateFromNode(String name, String id) { - String nameLowerCase = name.toLowerCase(); - return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(nameLowerCase).build(); + return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name.toLowerCase()).build(); } @Override public ListenableFuture<Image> createImage(ImageTemplate template) { - - final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; final String id = cloneTemplate.getSourceNodeId(); final String name = cloneTemplate.getName(); - final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor"; + logger.debug(">> stopping node %s...", id); api.getVirtualMachineApi(group).stop(id); - if (nodeSuspendedPredicate.apply(id)) { - return userExecutor.submit(new Callable<Image>() { - @Override - public Image call() throws Exception { - api.getVirtualMachineApi(group).generalize(id); - - final String[] disks = new String[2]; - URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME); - if (uri != null) { - if (imageAvailablePredicate.apply(uri)) { - List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri); - if (definitions != null) { - for (ResourceDefinition definition : definitions) { - LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties(); - Object storageObject = properties.get("storageProfile"); - LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject; - Object osDiskObject = properties2.get("osDisk"); - LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject; - Object dataDisksObject = properties2.get("dataDisks"); - ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject; - LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0); - - disks[0] = osProperties.get("name"); - disks[1] = datadiskObject.get("name"); - - VirtualMachine vm = api.getVirtualMachineApi(group).get(id); - final VMImage ref = VMImage.create(group, storageAccountName, disks[0], disks[1], name, "custom", vm.location()); - return imageReferenceToImage.apply(ref); - } - } - } - } - throw new UncheckedTimeoutException("Image was not created within the time limit: " - + cloneTemplate.getName()); - } - }); - } else { - final String illegalStateExceptionMessage = format("Node %s was not suspended within %sms.", - id, azureComputeConstants.operationTimeout()); - throw new IllegalStateException(illegalStateExceptionMessage); - } + checkState(nodeSuspendedPredicate.apply(id), "Node %s was not suspended within the configured time limit", id); + + return userExecutor.submit(new Callable<Image>() { + @Override + public Image call() throws Exception { + logger.debug(">> generalizing virtal machine %s...", id); + api.getVirtualMachineApi(group).generalize(id); + + logger.debug(">> capturing virtual machine %s to container %s...", id, CONTAINER_NAME); + URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME); + checkState(uri != null && imageAvailablePredicate.apply(uri), + "Image %s was not created within the configured time limit", cloneTemplate.getName()); + + List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri); + checkState(definitions.size() == 1, + "Expected one resource definition after creating the image but %s were returned", definitions.size()); + + Image image = resourceDefinitionToImage.create(id, name).apply(definitions.get(0)); + logger.debug(">> created %s", image); + return image; + } + }); } @Override public boolean deleteImage(String id) { + VMImage image = decodeFieldsFromUniqueId(id); + checkArgument(image.custom(), "Only custom images can be deleted"); - VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id); - if (image.custom()) { - StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage()); + logger.debug(">> deleting image %s", id); - // This removes now all the images in this storage. At least in theory, there should be just one and if there is + StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage()); + BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1()); + + try { + // This removes now all the images in this storage. At least in theory, + // there should be just one and if there is // more, they should be copies of each other. - BlobHelper.deleteContainerIfExists(image.storage(), keys.key1(), "system"); - return !BlobHelper.customImageExists(image.storage(), keys.key1()); + blobHelper.deleteContainerIfExists("system"); + boolean result = !blobHelper.customImageExists(); + + if (!blobHelper.hasContainers()) { + logger.debug(">> storage account is empty after deleting the custom image. Deleting the storage account..."); + api.getStorageAccountApi(image.group()).delete(image.storage()); + cleanupResources.deleteResourceGroupIfEmpty(image.group()); + } + + return result; + } finally { + closeQuietly(blobHelper); } - - return false; } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java deleted file mode 100644 index 532e786..0000000 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToNodeMetadata.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jclouds.azurecompute.arm.compute.functions; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.inject.Inject; - -import com.google.common.collect.Sets; -import org.jclouds.azurecompute.arm.AzureComputeApi; -import org.jclouds.azurecompute.arm.domain.ComputeNode; -import org.jclouds.azurecompute.arm.domain.Deployment; -import org.jclouds.azurecompute.arm.domain.ImageReference; -import org.jclouds.azurecompute.arm.domain.IpConfiguration; -import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; -import org.jclouds.azurecompute.arm.domain.PublicIPAddress; -import org.jclouds.azurecompute.arm.domain.VMDeployment; -import org.jclouds.azurecompute.arm.domain.VMHardware; -import org.jclouds.azurecompute.arm.domain.VMImage; -import org.jclouds.azurecompute.arm.domain.VMSize; -import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; -import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder; -import org.jclouds.azurecompute.arm.util.GetEnumValue; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeMetadataBuilder; -import org.jclouds.compute.functions.GroupNamingConvention; -import org.jclouds.domain.Credentials; -import org.jclouds.domain.Location; -import com.google.common.base.Function; -import com.google.common.collect.ImmutableMap; -import org.jclouds.domain.LoginCredentials; -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.Hardware; - -public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMetadata> { - - public static final String JCLOUDS_DEFAULT_USERNAME = "root"; - public static final String AZURE_LOGIN_USERNAME = DeploymentTemplateBuilder.getLoginUserUsername(); - public static final String AZURE_LOGIN_PASSWORD = DeploymentTemplateBuilder.getLoginPassword(); - - private static final Map<ComputeNode.Status, NodeMetadata.Status> INSTANCESTATUS_TO_NODESTATUS = - ImmutableMap.<ComputeNode.Status, NodeMetadata.Status>builder(). - put(ComputeNode.Status.GOOD, NodeMetadata.Status.RUNNING). - put(ComputeNode.Status.BAD, NodeMetadata.Status.ERROR). - put(ComputeNode.Status.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED). - build(); - - // When using the Deployment API to deploy an ARM template, the deployment goes through - // stages. Accepted -> Running -> Succeeded. Only when the deployment has SUCCEEDED is - // the resource deployed using the template actually ready. - // - // To get details about the resource(s) deployed via template, one needs to query the - // various resources after the deployment has "SUCCEEDED". - private static final Map<Deployment.ProvisioningState, NodeMetadata.Status> STATUS_TO_NODESTATUS = - ImmutableMap.<Deployment.ProvisioningState, NodeMetadata.Status>builder(). - put(Deployment.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING). - put(Deployment.ProvisioningState.READY, NodeMetadata.Status.PENDING). - put(Deployment.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING). - put(Deployment.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED). - put(Deployment.ProvisioningState.FAILED, NodeMetadata.Status.ERROR). - put(Deployment.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED). - put(Deployment.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING). - put(Deployment.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED). - build(); - - public static Deployment.ProvisioningState provisioningStateFromString(final String text) { - return (Deployment.ProvisioningState) GetEnumValue.fromValueOrDefault(text, Deployment.ProvisioningState.UNRECOGNIZED); - } - - private final AzureComputeApi api; - - private final LocationToLocation locationToLocation; - - private final GroupNamingConvention nodeNamingConvention; - - private final VMImageToImage vmImageToImage; - - private final VMHardwareToHardware vmHardwareToHardware; - - private final Map<String, Credentials> credentialStore; - - @Inject - DeploymentToNodeMetadata( - AzureComputeApi api, - LocationToLocation locationToLocation, - GroupNamingConvention.Factory namingConvention, VMImageToImage vmImageToImage, - VMHardwareToHardware vmHardwareToHardware, Map<String, Credentials> credentialStore) { - - this.nodeNamingConvention = namingConvention.createWithoutPrefix(); - this.locationToLocation = locationToLocation; - this.vmImageToImage = vmImageToImage; - this.vmHardwareToHardware = vmHardwareToHardware; - this.credentialStore = credentialStore; - this.api = api; - } - - @Override - public NodeMetadata apply(final VMDeployment from) { - final NodeMetadataBuilder builder = new NodeMetadataBuilder(); - final Deployment deployment = from.deployment(); - builder.id(deployment.name()); - builder.providerId(deployment.name()); - builder.name(deployment.name()); - String group = this.nodeNamingConvention.extractGroup(deployment.name()); - builder.group(group); - if (from.tags() != null) - builder.tags(from.tags()); - if (from.userMetaData() != null) - builder.userMetadata(from.userMetaData()); - - NodeMetadata.Status status = STATUS_TO_NODESTATUS.get(provisioningStateFromString(deployment.properties().provisioningState())); - if (status == NodeMetadata.Status.RUNNING && from.vm() != null && from.vm().statuses() != null) { - List<VirtualMachineInstance.VirtualMachineStatus> statuses = from.vm().statuses(); - for (int c = 0; c < statuses.size(); c++) { - if (statuses.get(c).code().substring(0, 10).equals("PowerState")) { - if (statuses.get(c).displayStatus().equals("VM running")) { - status = NodeMetadata.Status.RUNNING; - } else if (statuses.get(c).displayStatus().equals("VM stopped")) { - status = NodeMetadata.Status.SUSPENDED; - } - break; - } - } - } - - builder.status(status); - - if (from.vm() != null) { - builder.hostname(deployment.name() + "pc"); - } - - Credentials credentials = credentialStore.get("node#" + from.deployment().name()); - if (credentials != null && credentials.identity.equals(JCLOUDS_DEFAULT_USERNAME)) { - credentials = new Credentials(AZURE_LOGIN_USERNAME, credentials.credential); - } - else if (credentials == null) { - String username = AZURE_LOGIN_USERNAME; - String password = AZURE_LOGIN_PASSWORD; - if (username == null) { - username = "jclouds"; - } - if (password == null) { - password = "Password1!"; - } - - credentials = new Credentials(username, password); - } - builder.credentials(LoginCredentials.fromCredentials(credentials)); - - final Set<String> publicIpAddresses = Sets.newLinkedHashSet(); - if (from.ipAddressList() != null) { - for (int c = 0; c < from.ipAddressList().size(); c++) { - PublicIPAddress ip = from.ipAddressList().get(c); - if (ip != null && ip.properties() != null && ip.properties().ipAddress() != null) - { - publicIpAddresses.add(ip.properties().ipAddress()); - break; - } - } - if (publicIpAddresses.size() > 0) - builder.publicAddresses(publicIpAddresses); - } - final Set<String> privateIpAddresses = Sets.newLinkedHashSet(); - if (from.networkInterfaceCards() != null) { - for (NetworkInterfaceCard nic : from.networkInterfaceCards()) { - if (nic != null && nic.properties() != null && nic.properties().ipConfigurations() != null) { - for (IpConfiguration ip : nic.properties().ipConfigurations()) { - if (ip != null && ip.properties() != null && ip.properties().privateIPAddress() != null) { - privateIpAddresses.add(ip.properties().privateIPAddress()); - } - } - } - } - if (!privateIpAddresses.isEmpty()) { - builder.privateAddresses(privateIpAddresses); - } - } - - org.jclouds.azurecompute.arm.domain.Location myLocation = null; - if (from.virtualMachine() != null) { - String locationName = from.virtualMachine().location(); - List<org.jclouds.azurecompute.arm.domain.Location> locations = api.getLocationApi().list(); - - for (org.jclouds.azurecompute.arm.domain.Location location : locations) { - if (location.name().equals(locationName)) { - myLocation = location; - break; - } - } - Location jLocation = this.locationToLocation.apply(myLocation); - builder.location(jLocation); - - ImageReference imageReference = from.virtualMachine().properties().storageProfile().imageReference(); - - if (imageReference != null) { - VMImage vmImage = VMImage.create(imageReference.publisher(), imageReference.offer(), imageReference.sku(), - imageReference.version(), locationName); - Image image = vmImageToImage.apply(vmImage); - builder.imageId(image.getId()); - } - - VMSize myVMSize = null; - String vmSizeName = from.virtualMachine().properties().hardwareProfile().vmSize(); - List<VMSize> vmSizes = api.getVMSizeApi(locationName).list(); - for (VMSize vmSize : vmSizes) { - if (vmSize.name().equals(vmSizeName)) { - myVMSize = vmSize; - break; - } - } - - VMHardware hwProfile = VMHardware.create( - myVMSize.name(), - myVMSize.numberOfCores(), - myVMSize.osDiskSizeInMB(), - myVMSize.resourceDiskSizeInMB(), - myVMSize.memoryInMB(), - myVMSize.maxDataDiskCount(), - locationName, - false); - - Hardware hardware = vmHardwareToHardware.apply(hwProfile); - builder.hardware(hardware); - } - - return builder.build(); - } -} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2f110387/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java deleted file mode 100644 index 31f1a58..0000000 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/DeploymentToVMDeployment.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jclouds.azurecompute.arm.compute.functions; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import org.jclouds.azurecompute.arm.AzureComputeApi; -import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; -import org.jclouds.azurecompute.arm.domain.Deployment; -import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; -import org.jclouds.azurecompute.arm.domain.PublicIPAddress; -import org.jclouds.azurecompute.arm.domain.VMDeployment; -import org.jclouds.azurecompute.arm.domain.VirtualMachine; -import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; - -import com.google.common.base.Function; - -/** - * Converts an Deployment into a VMDeployment. - */ -@Singleton -public class DeploymentToVMDeployment implements Function<Deployment, VMDeployment> { - - private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants; - - private final AzureComputeApi api; - - @Inject - DeploymentToVMDeployment(AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) { - this.api = api; - this.azureComputeConstants = azureComputeConstants; - } - - @Override - public VMDeployment apply(final Deployment deployment) { - String id = deployment.id(); - List<PublicIPAddress> ipAddressList = getIPAddresses(deployment); - List<NetworkInterfaceCard> networkInterfaceCards = getNetworkInterfaceCards(deployment); - VirtualMachine vm = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).get(id); - VirtualMachineInstance vmInstanceDetails = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).getInstanceDetails(id); - Map<String, String> userMetaData = null; - Iterable<String> tags = null; - if (vm != null && vm.tags() != null) { - userMetaData = vm.tags(); - String tagString = userMetaData.get("tags"); - tags = Arrays.asList(tagString.split(",")); - } - return VMDeployment.create(deployment, ipAddressList, vmInstanceDetails, vm, networkInterfaceCards, userMetaData, tags); - } - - private List<PublicIPAddress> getIPAddresses(Deployment deployment) { - List<PublicIPAddress> list = new ArrayList<PublicIPAddress>(); - String resourceGroup = getResourceGroupFromId(deployment.id()); - - if (deployment.properties() != null && deployment.properties().dependencies() != null) { - List<Deployment.Dependency> dependencies = deployment.properties().dependencies(); - for (int d = 0; d < dependencies.size(); d++) { - if (dependencies.get(d).resourceType().equals("Microsoft.Network/networkInterfaces")) { - List<Deployment.Dependency> dependsOn = dependencies.get(d).dependsOn(); - for (int e = 0; e < dependsOn.size(); e++) { - if (dependsOn.get(e).resourceType().equals("Microsoft.Network/publicIPAddresses")) { - String resourceName = dependsOn.get(e).resourceName(); - PublicIPAddress ip = api.getPublicIPAddressApi(resourceGroup).get(resourceName); - list.add(ip); - break; - } - } - } - } - } - return list; - } - - private String getResourceGroupFromId(String id) { - String searchStr = "/resourceGroups/"; - int indexStart = id.lastIndexOf(searchStr) + searchStr.length(); - searchStr = "/providers/"; - int indexEnd = id.lastIndexOf(searchStr); - - String resourceGroup = id.substring(indexStart, indexEnd); - return resourceGroup; - } - - private List<NetworkInterfaceCard> getNetworkInterfaceCards(Deployment deployment) { - List<NetworkInterfaceCard> result = new ArrayList<NetworkInterfaceCard>(); - - String resourceGroup = getResourceGroupFromId(deployment.id()); - - if (deployment.properties() != null && deployment.properties().dependencies() != null) { - for (Deployment.Dependency dependency : deployment.properties().dependencies()) { - if (dependency.resourceType().equals("Microsoft.Network/networkInterfaces")) { - String resourceName = dependency.resourceName(); - NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(resourceGroup).get(resourceName); - result.add(nic); - } - } - } - return result; - } - -}