JCLOUDS-664 Azurecompute-arm image capture userdata keyvault
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/2b36a75f Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/2b36a75f Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/2b36a75f Branch: refs/heads/master Commit: 2b36a75f9fb44e84ff82ae51438347b43db225a5 Parents: 5722ec2 Author: Rita Zhang <[email protected]> Authored: Mon May 16 18:55:01 2016 -0700 Committer: Ignasi Barrera <[email protected]> Committed: Fri Jul 1 00:30:29 2016 +0200 ---------------------------------------------------------------------- azurecompute-arm/pom.xml | 1 + .../arm/AzureComputeProviderMetadata.java | 8 +- .../arm/compute/AzureComputeServiceAdapter.java | 103 ++++--- .../AzureComputeServiceContextModule.java | 144 ++++++++- .../extensions/AzureComputeImageExtension.java | 142 +++++++++ .../functions/DeploymentToNodeMetadata.java | 56 ++-- .../compute/functions/VMHardwareToHardware.java | 23 +- .../arm/compute/functions/VMImageToImage.java | 29 +- .../compute/options/AzureTemplateOptions.java | 223 ++++++++++++++ ...DefaultLoginCredentialsForImageStrategy.java | 43 +++ .../CreateResourceGroupThenCreateNodes.java | 62 +++- .../arm/config/AzureComputeProperties.java | 6 + .../arm/domain/DeploymentTemplate.java | 27 +- .../arm/domain/KeyVaultReference.java | 46 +++ .../domain/NetworkInterfaceCardProperties.java | 12 +- .../jclouds/azurecompute/arm/domain/OSDisk.java | 29 +- .../azurecompute/arm/domain/StorageProfile.java | 1 + .../arm/domain/TemplateParameterType.java | 34 +++ .../azurecompute/arm/domain/VMDeployment.java | 5 + .../azurecompute/arm/domain/VMHardware.java | 25 +- .../azurecompute/arm/domain/VMImage.java | 21 +- .../azurecompute/arm/features/JobApi.java | 15 + .../arm/features/VirtualMachineApi.java | 25 ++ .../arm/functions/CleanupResources.java | 96 ++++-- .../arm/functions/StatusCodeParser.java | 38 +++ .../arm/handlers/AzureComputeErrorHandler.java | 7 +- .../arm/util/DeploymentTemplateBuilder.java | 300 +++++++++++++------ .../AzureComputeServiceContextLiveTest.java | 284 ------------------ .../compute/AzureComputeServiceLiveTest.java | 64 +++- .../AzureComputeImageExtensionLiveTest.java | 89 ++++++ .../arm/features/DeploymentApiLiveTest.java | 3 +- .../features/DeploymentTemplateBuilderTest.java | 80 +++-- .../arm/features/JobApiMockTest.java | 23 ++ .../NetworkInterfaceCardApiMockTest.java | 3 +- .../TemplateToDeploymentTemplateLiveTest.java | 89 +++++- .../arm/features/VirtualMachineApiLiveTest.java | 103 +++++-- .../arm/features/VirtualMachineApiMockTest.java | 32 +- .../AbstractAzureComputeApiLiveTest.java | 15 + .../internal/BaseAzureComputeApiLiveTest.java | 10 +- azurecompute-arm/src/test/resources/logback.xml | 82 +++++ .../src/test/resources/resourceDefinition.json | 22 ++ 41 files changed, 1787 insertions(+), 633 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/pom.xml ---------------------------------------------------------------------- diff --git a/azurecompute-arm/pom.xml b/azurecompute-arm/pom.xml index 33251fd..5a41e44 100644 --- a/azurecompute-arm/pom.xml +++ b/azurecompute-arm/pom.xml @@ -156,6 +156,7 @@ <goal>test</goal> </goals> <configuration> + <threadCount>1</threadCount> <systemPropertyVariables> <test.azurecompute-arm.endpoint>${test.azurecompute-arm.endpoint}</test.azurecompute-arm.endpoint> <test.azurecompute-arm.api-version>${test.azurecompute-arm.api-version}</test.azurecompute-arm.api-version> http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/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 4bbc508..460df67 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 @@ -24,6 +24,9 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATI import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; 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; @@ -70,7 +73,10 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata { properties.put(RESOURCE, "https://management.azure.com/"); properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup"); - properties.put(IMAGE_PUBLISHERS, "Microsoft.WindowsAzure.Compute, MicrosoftWindowsServer, Canonical"); + 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!"); properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000); return properties; http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/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 9a1d221..3d87d6d 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 @@ -18,9 +18,11 @@ package org.jclouds.azurecompute.arm.compute; import static java.lang.String.format; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX; import static org.jclouds.util.Predicates2.retry; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -40,15 +42,14 @@ import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; 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.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.Location; import org.jclouds.azurecompute.arm.domain.Offer; import org.jclouds.azurecompute.arm.domain.PublicIPAddress; -import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.SKU; import org.jclouds.azurecompute.arm.domain.VMDeployment; -import org.jclouds.azurecompute.arm.domain.VMSize; import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.features.DeploymentApi; import org.jclouds.azurecompute.arm.features.OSImageApi; @@ -60,6 +61,8 @@ import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.LoginCredentials; import org.jclouds.logging.Logger; import org.jclouds.azurecompute.arm.functions.CleanupResources; +import org.jclouds.azurecompute.arm.domain.VMSize; +import org.jclouds.azurecompute.arm.domain.Version; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -118,15 +121,13 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo logger.debug("Deployment created with name: %s group: %s", name, group); - final Set<VMDeployment> deployments = Sets.newHashSet(); - final DeploymentApi deploymentApi = api.getDeploymentApi(group); + 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) { @@ -149,8 +150,18 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo final VMDeployment deployment = deployments.iterator().next(); - return new NodeAndInitialCredentials<VMDeployment>(deployment, name, - LoginCredentials.builder().user(loginUser).identity(loginUser).password(loginPassword).authenticateSudo(true).build()); + NodeAndInitialCredentials<VMDeployment> credential = null; + + 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; } @Override @@ -166,17 +177,17 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list(); for (VMSize vmSize : vmSizes){ - VMHardware hwProfile = new VMHardware(); - hwProfile.name = vmSize.name(); - hwProfile.numberOfCores = vmSize.numberOfCores(); - hwProfile.osDiskSizeInMB = vmSize.osDiskSizeInMB(); - hwProfile.resourceDiskSizeInMB = vmSize.resourceDiskSizeInMB(); - hwProfile.memoryInMB = vmSize.memoryInMB(); - hwProfile.maxDataDiskCount = vmSize.maxDataDiskCount(); - hwProfile.location = location.name(); + VMHardware hwProfile = VMHardware.create( + vmSize.name(), + vmSize.numberOfCores(), + vmSize.osDiskSizeInMB(), + vmSize.resourceDiskSizeInMB(), + vmSize.memoryInMB(), + vmSize.maxDataDiskCount(), + location.name(), + false); hwProfiles.add(hwProfile); } - } checkAndSetHwAvailability(hwProfiles, Sets.newHashSet(locationIds)); @@ -186,32 +197,33 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo 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); + hwMap.put(hw.name(), hw.location()); } - for (VMHardware hw : hwProfiles) { - hw.globallyAvailable = hwMap.get(hw.name).containsAll(locations); - } + /// TODO + // for (VMHardware hw : hwProfiles) { + // hw.globallyAvailable() = hwMap.get(hw.name()).containsAll(locations); + // } } private void getImagesFromPublisher(String publisherName, List<VMImage> osImagesRef, String location) { - OSImageApi osImageApi = api.getOSImageApi(location); + OSImageApi osImageApi = api.getOSImageApi(location); Iterable<Offer> offerList = osImageApi.listOffers(publisherName); for (Offer offer : offerList) { Iterable<SKU> skuList = osImageApi.listSKUs(publisherName, offer.name()); for (SKU sku : skuList) { - VMImage vmImage = new VMImage(); - vmImage.publisher = publisherName; - vmImage.offer = offer.name(); - vmImage.sku = sku.name(); - vmImage.location = location; - osImagesRef.add(vmImage); + 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, false); + osImagesRef.add(vmImage); + } } } + } private List<VMImage> listImagesByLocation(String location) { @@ -241,17 +253,23 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo Multimap<String, String> map = ArrayListMultimap.create(); for (VMImage image : images) { - map.put( image.offer + "/" + image.sku, image.location); - } - - for (VMImage image : images) { - image.globallyAvailable = map.get(image.offer + "/" + image.sku).containsAll(locations); + map.put( image.offer() + "/" + image.sku(), image.location()); } + ///TODO + // for (VMImage image : images) { + // image.globallyAvailable() = map.get(image.offer() + "/" + image.sku()).containsAll(locations); + // } } @Override public VMImage getImage(final String id) { String[] fields = VMImageToImage.decodeFieldsFromUniqueId(id); + if (fields[2].startsWith(CUSTOM_IMAGE_PREFIX)) { + String storage = fields[2].substring(CUSTOM_IMAGE_PREFIX.length()); + String vhd = fields[3]; + VMImage ref = VMImage.create(CUSTOM_IMAGE_PREFIX + azureGroup, CUSTOM_IMAGE_PREFIX + storage, vhd, null, fields[0], false); + return ref; + } Iterable<VMImage> images = listImages(); @@ -266,6 +284,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo @Override public Iterable<Location> listLocations() { + List<Location> locations = api.getLocationApi().list(); List<ResourceProviderMetaData> resources = api.getResourceProviderApi().get("Microsoft.Compute"); @@ -286,7 +305,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo } }); - return result; + return result; } private String getResourceGroupFromId(String id) { @@ -309,9 +328,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo vmDeployment.deployment = deployment; List<PublicIPAddress> list = getIPAddresses(deployment); vmDeployment.ipAddressList = list; - VirtualMachine vm = api.getVirtualMachineApi(azureGroup).get(id); vmDeployment.virtualMachine = vm; + vmDeployment.vm = api.getVirtualMachineApi(azureGroup).getInstanceDetails(id); + if (vm != null && vm.tags() != null) { + vmDeployment.userMetaData = vm.tags(); + String tagString = vmDeployment.userMetaData.get("tags"); + List<String> tags = Arrays.asList(tagString.split(",")); + vmDeployment.tags = tags; + } return vmDeployment; } @@ -372,9 +397,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo List<PublicIPAddress> list = getIPAddresses(d); vmDeployment.ipAddressList = list; - VirtualMachine virtualMachine = vmApi.get(d.name()); - vmDeployment.virtualMachine = virtualMachine; + VirtualMachine vm = vmApi.get(d.name()); + vmDeployment.virtualMachine = vm; + if (vm != null && vm.tags() != null) { + vmDeployment.userMetaData = vm.tags(); + String tagString = vmDeployment.userMetaData.get("tags"); + List<String> tags = Arrays.asList(tagString.split(",")); + vmDeployment.tags = tags; + } vmDeployments.add(vmDeployment); } return vmDeployments; http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/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 9844be4..7df8111 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,34 +16,56 @@ */ package org.jclouds.azurecompute.arm.compute.config; +import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Singleton; + import com.google.inject.Provides; import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter; +import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension; import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata; import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware; import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation; +import org.jclouds.azurecompute.arm.compute.strategy.AzurePopulateDefaultLoginCredentialsForImageStrategy; +import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; +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.Location; import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes; import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.functions.ParseJobStatus; -import org.jclouds.azurecompute.arm.compute.AzureComputeService; - +import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod; -import org.jclouds.compute.ComputeService; + +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.TCP_RULE_FORMAT; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN; +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.TIMEOUT_RESOURCE_DELETED; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; + +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; import static org.jclouds.util.Predicates2.retry; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; import com.google.common.base.Function; import com.google.inject.Inject; @@ -52,21 +74,22 @@ import com.google.common.base.Predicate; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.VisibleForTesting; import java.net.URI; +import java.util.List; -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.TCP_RULE_FORMAT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; +import org.jclouds.azurecompute.arm.compute.AzureComputeService; +import org.jclouds.compute.ComputeService; +import org.jclouds.logging.Logger; public class AzureComputeServiceContextModule extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + @Override protected void configure() { super.configure(); @@ -84,7 +107,12 @@ public class AzureComputeServiceContextModule install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() { }); + bind(TemplateOptions.class).to(AzureTemplateOptions.class); + bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(AzurePopulateDefaultLoginCredentialsForImageStrategy.class); + //bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class); bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class); + bind(new TypeLiteral<ImageExtension>() { + }).to(AzureComputeImageExtension.class); } @Singleton @@ -122,6 +150,18 @@ public class AzureComputeServiceContextModule @Inject private String azureDefaultImageLoginProperty; + @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) + @Inject + private String azureDefaultVnetAddressPrefixProperty; + + @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) + @Inject + private String azureDefaultSubnetAddressPrefixProperty; + + @Named(DEFAULT_DATADISKSIZE) + @Inject + private String azureDefaultDataDiskSizeProperty; + public Long operationTimeout() { return Long.parseLong(operationTimeoutProperty); } @@ -138,6 +178,18 @@ public class AzureComputeServiceContextModule return azureDefaultImageLoginProperty; } + public String azureDefaultVnetAddressPrefixProperty() { + return azureDefaultVnetAddressPrefixProperty; + } + + public String azureDefaultSubnetAddressPrefixProperty() { + return azureDefaultSubnetAddressPrefixProperty; + } + + public String azureDefaultDataDiskSizeProperty() { + return azureDefaultDataDiskSizeProperty; + } + public Integer operationPollInitialPeriod() { return Integer.parseInt(operationPollInitialPeriodProperty); } @@ -158,19 +210,39 @@ public class AzureComputeServiceContextModule @Provides @Named(TIMEOUT_NODE_TERMINATED) protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, Timeouts timeouts, - PollPeriod pollPeriod) { + PollPeriod pollPeriod) { return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); } @Provides + @Named(TIMEOUT_IMAGE_AVAILABLE) + protected Predicate<URI> provideImageAvailablePredicate(final AzureComputeApi api, Timeouts timeouts, + PollPeriod pollPeriod) { + return retry(new ImageDonePredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod, + pollPeriod.pollMaxPeriod); + } + + @Provides @Named(TIMEOUT_RESOURCE_DELETED) protected Predicate<URI> provideResourceDeletedPredicate(final AzureComputeApi api, Timeouts timeouts, - PollPeriod pollPeriod) { + PollPeriod pollPeriod) { return retry(new ActionDonePredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); } + @Provides + @Named(TIMEOUT_NODE_SUSPENDED) + protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api, + final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, + Timeouts timeouts, + PollPeriod pollPeriod) { + + String azureGroup = azureComputeConstants.azureResourceGroup(); + return retry(new NodeSuspendedPredicate(api, azureGroup), timeouts.nodeSuspended, pollPeriod.pollInitialPeriod, + pollPeriod.pollMaxPeriod); + } + @VisibleForTesting static class ActionDonePredicate implements Predicate<URI> { @@ -183,9 +255,51 @@ public class AzureComputeServiceContextModule @Override public boolean apply(URI uri) { checkNotNull(uri, "uri cannot be null"); - return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri); + return (ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri)) || (ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri)); } } + @VisibleForTesting + static class ImageDonePredicate implements Predicate<URI> { + + private final AzureComputeApi api; + + public ImageDonePredicate(AzureComputeApi api) { + this.api = checkNotNull(api, "api must not be null"); + } + + @Override + public boolean apply(URI uri) { + checkNotNull(uri, "uri cannot be null"); + List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri); + return definitions != null; + } + } + + @VisibleForTesting + static class NodeSuspendedPredicate implements Predicate<String> { + + private final AzureComputeApi api; + private final String azureGroup; + + public NodeSuspendedPredicate(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"); + String status = ""; + List<VirtualMachineInstance.VirtualMachineStatus> statuses = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name).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"); + } + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/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 new file mode 100644 index 0000000..626f511 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java @@ -0,0 +1,142 @@ +/* + * 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.extensions; + +import com.google.common.base.Predicate; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.gson.internal.LinkedTreeMap; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import org.jclouds.Constants; +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; +import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; +import org.jclouds.azurecompute.arm.domain.ResourceDefinition; +import org.jclouds.azurecompute.arm.domain.VMImage; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; +import org.jclouds.compute.domain.CloneImageTemplate; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageTemplate; +import org.jclouds.compute.domain.ImageTemplateBuilder; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; + +import static java.lang.String.format; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; + +import com.google.common.util.concurrent.UncheckedTimeoutException; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + + +public class AzureComputeImageExtension implements ImageExtension { + private final AzureComputeApi api; + private final Predicate<URI> imageAvailablePredicate; + private final Predicate<String> nodeSuspendedPredicate; + private final AzureComputeConstants azureComputeConstants; + private final ListeningExecutorService userExecutor; + private final String group; + private final VMImageToImage imageReferenceToImage; + public static final String CONTAINER_NAME = "vhdsnew"; + public static final String CUSTOM_IMAGE_PREFIX = "#"; + + @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; + this.api = api; + this.imageAvailablePredicate = imageAvailablePredicate; + this.nodeSuspendedPredicate = nodeSuspendedPredicate; + this.azureComputeConstants = azureComputeConstants; + } + + @Override + public ImageTemplate buildImageTemplateFromNode(String name, String id) { + String imageName = name.toLowerCase(); + return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(imageName).build(); + } + + @Override + public ListenableFuture<Image> createImage(ImageTemplate template) { + final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; + final String id = cloneTemplate.getSourceNodeId(); + final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor"; + + // VM needs to be stopped before it can be generalized + String status = ""; + api.getVirtualMachineApi(group).stop(id); + //Poll until resource is ready to be used + 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); + String location = vm.location(); + final VMImage ref = VMImage.create(CUSTOM_IMAGE_PREFIX + group, CUSTOM_IMAGE_PREFIX + storageAccountName, disks[0], disks[1], location, false); + 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); + } + } + + @Override + public boolean deleteImage(String id) { + return false; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/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 index bccc63c..40e09b7 100644 --- 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 @@ -48,6 +48,7 @@ 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(); @@ -116,6 +117,10 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta 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) { @@ -134,9 +139,25 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta builder.status(status); + if (from.vm != null) { + builder.hostname(deployment.name() + "pc"); + } + Credentials credentials = credentialStore.get("node#" + from.deployment.name()); - if (credentials == null) { - credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD); + 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)); @@ -149,7 +170,6 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta publicIpAddresses.add(ip.properties().ipAddress()); break; } - } if (publicIpAddresses.size() > 0) builder.publicAddresses(publicIpAddresses); @@ -171,13 +191,12 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta ImageReference imageReference = from.virtualMachine.properties().storageProfile().imageReference(); - VMImage vmImage = new VMImage(); - vmImage.publisher = imageReference.publisher(); - vmImage.offer = imageReference.offer(); - vmImage.sku = imageReference.sku(); - vmImage.location = locationName; - Image image = vmImageToImage.apply(vmImage); - builder.imageId(image.getId()); + if (imageReference != null) { + VMImage vmImage = VMImage.create(imageReference.publisher(), imageReference.offer(), imageReference.sku(), + imageReference.version(), locationName, false); + Image image = vmImageToImage.apply(vmImage); + builder.imageId(image.getId()); + } VMSize myVMSize = null; String vmSizeName = from.virtualMachine.properties().hardwareProfile().vmSize(); @@ -189,14 +208,15 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta } } - VMHardware hwProfile = new VMHardware(); - hwProfile.name = myVMSize.name(); - hwProfile.numberOfCores = myVMSize.numberOfCores(); - hwProfile.osDiskSizeInMB = myVMSize.osDiskSizeInMB(); - hwProfile.resourceDiskSizeInMB = myVMSize.resourceDiskSizeInMB(); - hwProfile.memoryInMB = myVMSize.memoryInMB(); - hwProfile.maxDataDiskCount = myVMSize.maxDataDiskCount(); - hwProfile.location = locationName; + 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); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java index 51a6e5e..5303e25 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMHardwareToHardware.java @@ -47,30 +47,31 @@ public class VMHardwareToHardware implements Function<VMHardware, Hardware> { @Override public Hardware apply(VMHardware from) { final HardwareBuilder builder = new HardwareBuilder() - .name(from.name) - .id(from.name) - .processors(ImmutableList.of(new Processor(from.numberOfCores, 2))) - .ram(from.memoryInMB) - .location(from.globallyAvailable ? null : FluentIterable.from(locations.get()) - .firstMatch(LocationPredicates.idEquals(from.location)) + .name(from.name()) + .providerId(from.name()) + .id(from.name()) + .processors(ImmutableList.of(new Processor(from.numberOfCores(), 2))) + .ram(from.memoryInMB()) + .location(from.globallyAvailable() ? null : FluentIterable.from(locations.get()) + .firstMatch(LocationPredicates.idEquals(from.location())) .get()); // No id or providerId from Azure - if (from.resourceDiskSizeInMB != null) { + if (from.resourceDiskSizeInMB() != null) { builder.volume(new VolumeBuilder() - .size(Float.valueOf(from.resourceDiskSizeInMB)) + .size(Float.valueOf(from.resourceDiskSizeInMB())) .type(Volume.Type.LOCAL) .build()); } - if (from.osDiskSizeInMB != null) { + if (from.osDiskSizeInMB() != null) { builder.volume(new VolumeBuilder() - .size(Float.valueOf(from.osDiskSizeInMB)) + .size(Float.valueOf(from.osDiskSizeInMB())) .type(Volume.Type.LOCAL) .build()); } ImmutableMap.Builder<String, String> metadata = ImmutableMap.builder(); - metadata.put("maxDataDiskCount", String.valueOf(from.maxDataDiskCount)); + metadata.put("maxDataDiskCount", String.valueOf(from.maxDataDiskCount())); builder.userMetadata(metadata.build()); return builder.build(); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java index 65a3d4b..75bcc0e 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VMImageToImage.java @@ -17,6 +17,8 @@ package org.jclouds.azurecompute.arm.compute.functions; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD; +import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME; import com.google.common.base.Supplier; import com.google.common.collect.FluentIterable; @@ -29,7 +31,9 @@ import org.jclouds.compute.domain.OsFamily; import com.google.common.base.Function; import com.google.inject.Inject; +import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; +import org.jclouds.domain.LoginCredentials; import org.jclouds.location.predicates.LocationPredicates; import java.util.Set; @@ -59,7 +63,7 @@ public class VMImageToImage implements Function<VMImage, Image> { private final Supplier<Set<? extends org.jclouds.domain.Location>> locations; public static String encodeFieldsToUniqueId(VMImage imageReference){ - return (imageReference.globallyAvailable ? "global" : imageReference.location) + "/" + imageReference.publisher + "/" + imageReference.offer + "/" + imageReference.sku; + return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku(); } public static String[] decodeFieldsFromUniqueId(final String id) { @@ -74,18 +78,19 @@ public class VMImageToImage implements Function<VMImage, Image> { @Override public Image apply(final VMImage image) { + Credentials credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD); final ImageBuilder builder = new ImageBuilder() - .name(image.offer) - .description(image.sku) + .name(image.offer()) + .description(image.sku()) .status(Image.Status.AVAILABLE) - .version(image.sku) + .version(image.sku()) .id(encodeFieldsToUniqueId(image)) - .providerId(image.publisher) - .location(image.globallyAvailable ? null : FluentIterable.from(locations.get()) - .firstMatch(LocationPredicates.idEquals(image.location)) + .defaultCredentials(LoginCredentials.fromCredentials(credentials)) + .providerId(image.publisher()) + .location(image.globallyAvailable() ? null : FluentIterable.from(locations.get()) + .firstMatch(LocationPredicates.idEquals(image.location())) .get()); - final OperatingSystem.Builder osBuilder = osFamily().apply(image); return builder.operatingSystem(osBuilder.build()).build(); } @@ -94,8 +99,8 @@ public class VMImageToImage implements Function<VMImage, Image> { return new Function<VMImage, OperatingSystem.Builder>() { @Override public OperatingSystem.Builder apply(final VMImage image) { - checkNotNull(image.offer, "offer"); - final String label = image.offer; + checkNotNull(image.offer(), "offer"); + final String label = image.offer(); OsFamily family = OsFamily.UNRECOGNIZED; if (label.contains(CENTOS)) { @@ -116,8 +121,8 @@ public class VMImageToImage implements Function<VMImage, Image> { return OperatingSystem.builder(). family(family). is64Bit(true). - description(image.sku). - version(image.sku); + description(image.sku()). + version(image.sku()); } }; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java new file mode 100644 index 0000000..c5267b1 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/options/AzureTemplateOptions.java @@ -0,0 +1,223 @@ +/* + * 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.options; + +import static com.google.common.base.Objects.equal; +import org.jclouds.compute.options.TemplateOptions; +import com.google.common.base.Objects; + +/** + * Azure ARM custom options + */ +public class AzureTemplateOptions extends TemplateOptions implements Cloneable { + + + private String customData; + private String virtualNetworkAddressPrefix; + private String subnetAddressPrefix; + private String DNSLabelPrefix; + private String keyVaultIdAndSecret; + + + /** + * Custom options for the Azure ARM API + */ + public AzureTemplateOptions customData(String customData) { + this.customData = customData; + return this; + } + private String virtualNetworkName; + private String subnetId; + + /** + * Sets the CIDR block for virtual network + */ + public AzureTemplateOptions virtualNetworkAddressPrefix(String virtualNetworkAddressPrefix) { + this.virtualNetworkAddressPrefix = virtualNetworkAddressPrefix; + return this; + } + + /** + * Sets the CIDR block for subnet within virtual network + */ + public AzureTemplateOptions subnetAddressPrefix(String subnetAddressPrefix) { + this.subnetAddressPrefix = subnetAddressPrefix; + return this; + } + + /** + * Sets the DNS label prefix for public IP address. label.location.cloudapp.azure.com + */ + public AzureTemplateOptions DNSLabelPrefix(String DNSLabelPrefix) { + this.DNSLabelPrefix = DNSLabelPrefix; + return this; + } + + /** + * Sets the KeyVault id and secret separated with ":" + */ + public AzureTemplateOptions keyVaultIdAndSecret(String keyVaultIdAndSecret) { + this.keyVaultIdAndSecret = keyVaultIdAndSecret; + return this; + } + + public String getCustomData() { return customData; } + public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; } + public String getSubnetAddressPrefix() { return subnetAddressPrefix; } + public String getDNSLabelPrefix() { return DNSLabelPrefix; } + public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; } + public String getVirtualNetworkName() { return virtualNetworkName; } + public String getSubnetId() { return subnetId; } + + + /** + * Sets the virtual network name + */ + public AzureTemplateOptions virtualNetworkName(String virtualNetworkName) { + this.virtualNetworkName = virtualNetworkName; + return this; + } + + /** + * Sets the subnet name + */ + public AzureTemplateOptions subnetId(String subnetId) { + this.subnetId = subnetId; + return this; + } + + @Override + public AzureTemplateOptions clone() { + AzureTemplateOptions options = new AzureTemplateOptions(); + copyTo(options); + return options; + } + + @Override + public void copyTo(TemplateOptions to) { + super.copyTo(to); + if (to instanceof AzureTemplateOptions) { + AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to); + eTo.customData(customData); + eTo.virtualNetworkAddressPrefix(virtualNetworkAddressPrefix); + eTo.subnetAddressPrefix(subnetAddressPrefix); + eTo.DNSLabelPrefix(DNSLabelPrefix); + eTo.keyVaultIdAndSecret(keyVaultIdAndSecret); + eTo.virtualNetworkName(virtualNetworkName); + eTo.subnetId(subnetId); + } + } + + @Override + public int hashCode() { + return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AzureTemplateOptions other = (AzureTemplateOptions) obj; + return super.equals(other) + && equal(this.customData, other.customData) + && equal(this.virtualNetworkAddressPrefix, other.virtualNetworkAddressPrefix) + && equal(this.subnetAddressPrefix, other.subnetAddressPrefix) + && equal(this.DNSLabelPrefix, other.DNSLabelPrefix) + && equal(this.keyVaultIdAndSecret, other.keyVaultIdAndSecret) + && equal(this.virtualNetworkName, other.virtualNetworkName) + && equal(this.subnetId, other.subnetId); + } + + @Override + public Objects.ToStringHelper string() { + Objects.ToStringHelper toString = super.string().omitNullValues(); + toString.add("customData", customData); + toString.add("virtualNetworkAddressPrefix", virtualNetworkAddressPrefix); + toString.add("subnetAddressPrefix", subnetAddressPrefix); + toString.add("DNSLabelPrefix", DNSLabelPrefix); + toString.add("keyVaultIdAndSecret", keyVaultIdAndSecret); + toString.add("virtualNetworkName", virtualNetworkName); + toString.add("subnetId", subnetId); + return toString; + } + + public static class Builder { + + /** + * @see AzureTemplateOptions#customData + */ + public static AzureTemplateOptions customData(String customData) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.customData(customData); + } + + /** + * @see AzureTemplateOptions#virtualNetworkAddressPrefix + */ + public static AzureTemplateOptions virtualNetworkAddressPrefix(String virtualNetworkAddressPrefix) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.virtualNetworkAddressPrefix(virtualNetworkAddressPrefix); + } + + /** + * @see AzureTemplateOptions#subnetAddressPrefix + */ + public static AzureTemplateOptions subnetAddressPrefix(String subnetAddressPrefix) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.subnetAddressPrefix(subnetAddressPrefix); + } + + /** + * @see AzureTemplateOptions#DNSLabelPrefix + */ + public static AzureTemplateOptions DNSLabelPrefix(String DNSLabelPrefix) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.DNSLabelPrefix(DNSLabelPrefix); + } + + /** + * @see AzureTemplateOptions#keyVaultIdAndSecret + */ + public static AzureTemplateOptions keyVaultIdAndSecret(String keyVaultIdAndSecret) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.keyVaultIdAndSecret(keyVaultIdAndSecret); + } + + /** + * @see AzureTemplateOptions#virtualNetworkName + */ + public static AzureTemplateOptions virtualNetworkName(String virtualNetworkName) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.virtualNetworkName(virtualNetworkName); + } + + /** + * @see AzureTemplateOptions#subnetId + */ + public static AzureTemplateOptions subnetId(String subnetId) { + AzureTemplateOptions options = new AzureTemplateOptions(); + return options.subnetId(subnetId); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java new file mode 100644 index 0000000..55d1a3c --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/AzurePopulateDefaultLoginCredentialsForImageStrategy.java @@ -0,0 +1,43 @@ +/* + * 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.strategy; + +import org.jclouds.compute.domain.internal.ImageImpl; +import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.LoginCredentials; + +import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD; +import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME; + +public class AzurePopulateDefaultLoginCredentialsForImageStrategy implements PopulateDefaultLoginCredentialsForImageStrategy { + @Override + public LoginCredentials apply(Object o) { + ImageImpl node = (ImageImpl)o; + String username = AZURE_LOGIN_USERNAME; + String password = AZURE_LOGIN_PASSWORD; + if (username == null) { + username = "jclouds"; + } + if (password == null) { + password = "Password1!"; + } + Credentials creds = new Credentials(username, password); + LoginCredentials credentials = LoginCredentials.fromCredentials(creds); + return credentials; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java index 6900f17..468b87c 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java @@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.compute.strategy; import static com.google.common.base.Preconditions.checkNotNull; +import java.util.Arrays; import java.util.Map; import java.util.Set; @@ -28,8 +29,13 @@ import javax.inject.Singleton; import com.google.common.collect.ImmutableMap; import org.jclouds.Constants; +import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; +import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.azurecompute.arm.domain.Subnet; import org.jclouds.azurecompute.arm.features.ResourceGroupApi; +import org.jclouds.azurecompute.arm.features.SubnetApi; +import org.jclouds.azurecompute.arm.features.VirtualNetworkApi; import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; @@ -40,7 +46,7 @@ import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIn import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet; import org.jclouds.azurecompute.arm.AzureComputeApi; - +import org.jclouds.azurecompute.arm.domain.VirtualNetwork; import org.jclouds.logging.Logger; import com.google.common.collect.Multimap; import com.google.common.util.concurrent.ListenableFuture; @@ -54,6 +60,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco protected Logger logger = Logger.NULL; private final AzureComputeApi api; + private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants; @Inject protected CreateResourceGroupThenCreateNodes( @@ -62,11 +69,12 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco GroupNamingConvention.Factory namingConvention, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, - AzureComputeApi api) { + AzureComputeApi api, AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) { super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor, customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory); this.api = checkNotNull(api, "api cannot be null"); checkNotNull(userExecutor, "userExecutor cannot be null"); + this.azureComputeConstants = azureComputeConstants; } @Override @@ -74,23 +82,59 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) { + String azureGroupName = this.azureComputeConstants.azureResourceGroup(); + + AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class); + // create resource group for jclouds group if it does not already exist ResourceGroupApi resourceGroupApi = api.getResourceGroupApi(); - ResourceGroup resourceGroup = resourceGroupApi.get(group); + ResourceGroup resourceGroup = resourceGroupApi.get(azureGroupName); final String location = template.getLocation().getId(); - final String resourceGroupName; if (resourceGroup == null){ - final Map<String, String> tags = ImmutableMap.of("description", "jClouds managed VMs"); - resourceGroupName = resourceGroupApi.create(group, location, tags).name(); - } else { - resourceGroupName = resourceGroup.name(); + resourceGroupApi.create(azureGroupName, location, tags).name(); } - Map<?, ListenableFuture<Void>> responses = super.execute(resourceGroupName, count, template, goodNodes, badNodes, + String vnetName = azureGroupName + "virtualnetwork"; + String subnetName = azureGroupName + "subnet"; + + if (options.getVirtualNetworkName() != null) { + vnetName = options.getVirtualNetworkName(); + } + + this.getOrCreateVirtualNetworkWithSubnet(vnetName, subnetName, location, options, azureGroupName); + + + Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes, customizationResponses); return responses; } + protected synchronized void getOrCreateVirtualNetworkWithSubnet( + final String virtualNetworkName, final String subnetName, final String location, + AzureTemplateOptions options, final String azureGroupName) { + + //Subnets belong to a virtual network so that needs to be created first + VirtualNetworkApi vnApi = api.getVirtualNetworkApi(azureGroupName); + VirtualNetwork vn = vnApi.get(virtualNetworkName); + + if (vn == null) { + VirtualNetwork.VirtualNetworkProperties virtualNetworkProperties = VirtualNetwork.VirtualNetworkProperties.builder() + .addressSpace(VirtualNetwork.AddressSpace.create(Arrays.asList(this.azureComputeConstants.azureDefaultVnetAddressPrefixProperty()))) + .subnets( + Arrays.asList( + Subnet.create(subnetName, null, null, + Subnet.SubnetProperties.builder().addressPrefix(this.azureComputeConstants.azureDefaultSubnetAddressPrefixProperty()).build()))) + .build(); + vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties); + } + + SubnetApi subnetApi = api.getSubnetApi(azureGroupName, virtualNetworkName); + Subnet subnet = subnetApi.get(subnetName); + + options.virtualNetworkName(virtualNetworkName); + options.subnetId(subnet.id()); + + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java index 48d6287..e5ef5cd 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java @@ -41,4 +41,10 @@ public class AzureComputeProperties { public static final String TIMEOUT_RESOURCE_DELETED = "jclouds.azurecompute.arm.timeout.resourcedeleted"; + public static final String DEFAULT_VNET_ADDRESS_SPACE_PREFIX = "jclouds.azurecompute.arm.vnet.addressprefix"; + + public static final String DEFAULT_SUBNET_ADDRESS_PREFIX = "jclouds.azurecompute.arm.subnet.addressprefix"; + + public static final String DEFAULT_DATADISKSIZE = "jclouds.azurecompute.arm.datadisksize"; + } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java index 848000d..5221e05 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/DeploymentTemplate.java @@ -31,8 +31,25 @@ public abstract class DeploymentTemplate { //Empty placeholders as we want to generate the empty JSON object @AutoValue public abstract static class Parameters { - public static Parameters create() { - return new AutoValue_DeploymentTemplate_Parameters(); + + @Nullable + public abstract KeyVaultReference publicKeyFromAzureKeyVault(); + + public static Parameters create(KeyVaultReference reference) + { + return new AutoValue_DeploymentTemplate_Parameters(reference); + } + } + + @AutoValue + public abstract static class TemplateParameters { + + @Nullable + public abstract TemplateParameterType publicKeyFromAzureKeyVault(); + + public static TemplateParameters create(TemplateParameterType publicKeyFromAzureKeyVault) + { + return new AutoValue_DeploymentTemplate_TemplateParameters(publicKeyFromAzureKeyVault); } } @@ -40,7 +57,7 @@ public abstract class DeploymentTemplate { public abstract String contentVersion(); - public abstract Parameters parameters(); + public abstract TemplateParameters parameters(); public abstract Map<String, String> variables(); @@ -52,7 +69,7 @@ public abstract class DeploymentTemplate { @SerializedNames({"$schema", "contentVersion", "parameters", "variables", "resources" , "outputs"}) public static DeploymentTemplate create(final String schema, final String contentVersion, - final Parameters parameters, + final TemplateParameters parameters, final Map<String, String> variables, final List<ResourceDefinition> resources, final List<?> outputs) { @@ -83,7 +100,7 @@ public abstract class DeploymentTemplate { public abstract Builder contentVersion(String type); - public abstract Builder parameters(Parameters parameters); + public abstract Builder parameters(TemplateParameters parameters); public abstract Builder variables(Map<String, String> variables); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/KeyVaultReference.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/KeyVaultReference.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/KeyVaultReference.java new file mode 100644 index 0000000..2eb2f87 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/KeyVaultReference.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.domain; + +import com.google.auto.value.AutoValue; +import org.jclouds.json.SerializedNames; + +// Simple helper class to serialize / deserialize keyvault reference. + +@AutoValue +public abstract class KeyVaultReference { + + @AutoValue + public abstract static class Reference { + + public abstract IdReference keyVault(); + + public abstract String secretName(); + + @SerializedNames({"keyVault", "secretName"}) + public static Reference create(final IdReference keyVault, final String secretName) { + return new AutoValue_KeyVaultReference_Reference(keyVault, secretName); + } + } + + public abstract Reference reference(); + + @SerializedNames({"reference"}) + public static KeyVaultReference create(final Reference reference) { + return new AutoValue_KeyVaultReference(reference); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java index e6f2de7..8b19493 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/NetworkInterfaceCardProperties.java @@ -38,13 +38,17 @@ public abstract class NetworkInterfaceCardProperties { @Nullable public abstract List<IpConfiguration> ipConfigurations(); - @SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations"}) - public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid, final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations) { + @Nullable + public abstract IdReference networkSecurityGroup(); + + @SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations", "networkSecurityGroup"}) + public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid, final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations, final IdReference networkSecurityGroup) { NetworkInterfaceCardProperties.Builder builder = NetworkInterfaceCardProperties.builder() .provisioningState(provisioningState) .resourceGuid(resourceGuid) .enableIPForwarding(enableIPForwarding) - .ipConfigurations(ipConfigurations == null ? null : ImmutableList.copyOf(ipConfigurations)); + .ipConfigurations(ipConfigurations == null ? null : ImmutableList.copyOf(ipConfigurations)) + .networkSecurityGroup(networkSecurityGroup); return builder.build(); } @@ -66,6 +70,8 @@ public abstract class NetworkInterfaceCardProperties { abstract List<IpConfiguration> ipConfigurations(); + public abstract Builder networkSecurityGroup(IdReference networkSecurityGroup); + abstract NetworkInterfaceCardProperties autoBuild(); public NetworkInterfaceCardProperties build() { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java index a9f7349..0be43bf 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/OSDisk.java @@ -52,16 +52,23 @@ public abstract class OSDisk { @Nullable public abstract String createOption(); - @SerializedNames({"osType", "name", "vhd", "caching", "createOption"}) + /** + * The url of the custom image + */ + @Nullable + public abstract VHD image(); + + @SerializedNames({"osType", "name", "vhd", "caching", "createOption", "image"}) public static OSDisk create(final String osType, final String name, final VHD vhd, - final String caching, final String createOption) { + final String caching, final String createOption, final VHD image) { return builder() - .osType(osType) - .name(name) - .vhd(vhd) - .caching(caching) - .createOption(createOption) - .build(); + .osType(osType) + .name(name) + .vhd(vhd) + .caching(caching) + .createOption(createOption) + .image(image) + .build(); } public static Builder builder() { @@ -71,15 +78,11 @@ public abstract class OSDisk { @AutoValue.Builder public abstract static class Builder { public abstract Builder osType(String osType); - public abstract Builder name(String name); - public abstract Builder caching(String caching); - public abstract Builder createOption(String createOption); - public abstract Builder vhd(VHD vhd); - + public abstract Builder image(VHD image); public abstract OSDisk build(); } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageProfile.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageProfile.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageProfile.java index 7c693ef..bcb62ee 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageProfile.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/StorageProfile.java @@ -29,6 +29,7 @@ public abstract class StorageProfile { /** * The image reference of the storage profile */ + @Nullable public abstract ImageReference imageReference(); /** http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/TemplateParameterType.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/TemplateParameterType.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/TemplateParameterType.java new file mode 100644 index 0000000..d0ccc71 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/TemplateParameterType.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.domain; + +import com.google.auto.value.AutoValue; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; + +// Simple helper class to serialize / deserialize id reference. + +@AutoValue +public abstract class TemplateParameterType { + @Nullable + public abstract String type(); + + @SerializedNames({"type"}) + public static TemplateParameterType create(final String type) { + return new AutoValue_TemplateParameterType(type); + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java index 6909a7b..c663944 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMDeployment.java @@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.domain; import java.util.List; +import java.util.Map; public class VMDeployment { @@ -28,4 +29,8 @@ public class VMDeployment { public VirtualMachineInstance vm; public VirtualMachine virtualMachine; + + public Map<String, String> userMetaData; + + public Iterable<String> tags; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java index d338327..f0aa77e 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMHardware.java @@ -17,6 +17,7 @@ package org.jclouds.azurecompute.arm.domain; import com.google.auto.value.AutoValue; +import org.jclouds.json.SerializedNames; /** * A VM Size that is available in a region for a given subscription. @@ -24,45 +25,51 @@ import com.google.auto.value.AutoValue; * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt269440.aspx" >api</a> */ @AutoValue -public class VMHardware { +public abstract class VMHardware { /** * The name of the VM size. */ - public String name; + public abstract String name(); /** * The number of cores that are available in the VM size. */ - public Integer numberOfCores; + public abstract Integer numberOfCores(); /** * Specifies the size in MB of the OS Disk. */ - public Integer osDiskSizeInMB; + public abstract Integer osDiskSizeInMB(); /** * The size of the resource disk. */ - public Integer resourceDiskSizeInMB; + public abstract Integer resourceDiskSizeInMB(); /** * Specifies the available RAM in MB. */ - public Integer memoryInMB; + public abstract Integer memoryInMB(); /** * Specifies the maximum number of data disks that can be attached to the VM size. */ - public Integer maxDataDiskCount; + public abstract Integer maxDataDiskCount(); /** * Specifies the location of the HW resource */ - public String location; + public abstract String location(); /** * Specifies if this HW is globally available */ - public boolean globallyAvailable; + public abstract boolean globallyAvailable(); + + @SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location", "globallyAvailable"}) + public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location, boolean globallyAvailable) { + + return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location, globallyAvailable); + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java index ccfb05a..2d4fc91 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/VMImage.java @@ -17,37 +17,44 @@ package org.jclouds.azurecompute.arm.domain; import com.google.auto.value.AutoValue; +import org.jclouds.json.SerializedNames; @AutoValue -public class VMImage { +public abstract class VMImage { /** * The publisher of the image reference. */ - public String publisher; + public abstract String publisher(); /** * The offer of the image reference. */ - public String offer; + public abstract String offer(); /** * The sku of the image reference. */ - public String sku; + public abstract String sku(); /** * The version of the image reference. */ - public String version; + public abstract String version(); /** * The location from where Image was fetched */ - public String location; + public abstract String location(); /** * Specifies if this image is globally available */ - public boolean globallyAvailable; + public abstract boolean globallyAvailable(); + + @SerializedNames({ "publisher", "offer", "sku", "version", "location", "globallyAvailable"}) + public static VMImage create(String publisher, String offer, String sku, String version, String location, boolean globallyAvailable) { + + return new AutoValue_VMImage(publisher, offer, sku, version, location, globallyAvailable); + } } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2b36a75f/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java index 7dd75a9..f2858d9 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/features/JobApi.java @@ -17,15 +17,21 @@ package org.jclouds.azurecompute.arm.features; import java.io.Closeable; import java.net.URI; +import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.core.MediaType; import javax.ws.rs.GET; + +import org.jclouds.Fallbacks; +import org.jclouds.azurecompute.arm.domain.ResourceDefinition; import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.azurecompute.arm.functions.ParseJobStatus; import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus; +import org.jclouds.rest.annotations.SelectJson; /** * The Azure Resource Manager API checks for job status and progress. @@ -37,5 +43,14 @@ public interface JobApi extends Closeable{ @GET @ResponseParser(ParseJobStatus.class) JobStatus jobStatus(@EndpointParam URI jobURI); + + /** + * Get status of captured custom image after capture call + */ + @GET + @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class) + @SelectJson("resources") + List<ResourceDefinition> captureStatus(@EndpointParam URI jobURI); + }
