From 00d9138864e890978efb012898003b74f99be097 Mon Sep 17 00:00:00 2001 From: Ignasi Barrera Date: Fri, 14 Oct 2016 17:51:42 +0200 Subject: [PATCH] Create one resource group in each region --- .../arm/AzureComputeProviderMetadata.java | 6 +- .../compute/AzureComputeServiceAdapter.java | 264 +++++++++--------- .../AzureComputeServiceContextModule.java | 106 +++---- .../AzureComputeImageExtension.java | 41 +-- .../LocationToResourceGroupName.java | 46 +++ .../ResourceDefinitionToCustomImage.java | 15 +- .../VirtualMachineToNodeMetadata.java | 16 +- .../CreateResourceGroupThenCreateNodes.java | 12 +- .../arm/config/AzureComputeProperties.java | 2 - .../azurecompute/arm/domain/RegionAndId.java | 50 ++++ .../arm/functions/CleanupResources.java | 38 +-- .../compute/AzureComputeServiceLiveTest.java | 23 +- .../compute/AzureTemplateBuilderLiveTest.java | 14 +- .../AzureComputeImageExtensionLiveTest.java | 23 +- .../arm/internal/AzureLiveTestUtils.java | 25 +- 15 files changed, 382 insertions(+), 299 deletions(-) create mode 100644 providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java create mode 100644 providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java index a434079a0b..beac9259c7 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/AzureComputeProviderMetadata.java @@ -25,12 +25,13 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_P import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO; import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER; +import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER; +import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX; import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET; @@ -88,9 +89,10 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata { properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}"); properties.put(RESOURCE, "https://management.azure.com/"); properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); - properties.put(RESOURCE_GROUP_NAME, "jclouds"); properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16"); properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24"); + properties.put(RESOURCENAME_PREFIX, "jclouds"); + properties.put(RESOURCENAME_DELIMITER, "-"); properties.put(DEFAULT_DATADISKSIZE, "100"); properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat"); // Default credentials for all images diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java index 0e2ed641f5..434c92f76c 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceAdapter.java @@ -30,11 +30,12 @@ import java.util.List; import java.util.Set; import javax.inject.Inject; -import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; +import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory; +import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.domain.DataDisk; import org.jclouds.azurecompute.arm.domain.HardwareProfile; @@ -51,6 +52,8 @@ import org.jclouds.azurecompute.arm.domain.OSProfile; import org.jclouds.azurecompute.arm.domain.Offer; import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties; +import org.jclouds.azurecompute.arm.domain.RegionAndId; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.SKU; import org.jclouds.azurecompute.arm.domain.StorageProfile; @@ -86,63 +89,67 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** - * Defines the connection between the {@link AzureComputeApi} implementation and the jclouds - * {@link org.jclouds.compute.ComputeService}. + * Defines the connection between the {@link AzureComputeApi} implementation and + * the jclouds {@link org.jclouds.compute.ComputeService}. */ @Singleton public class AzureComputeServiceAdapter implements ComputeServiceAdapter { - private final String azureGroup; private final CleanupResources cleanupResources; private final AzureComputeApi api; private final AzureComputeConstants azureComputeConstants; private final Supplier> regionIds; - private final Predicate publicIpAvailable; + private final PublicIpAvailablePredicateFactory publicIpAvailable; + private final LocationToResourceGroupName locationToResourceGroupName; @Inject AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants, CleanupResources cleanupResources, @Region Supplier> regionIds, - @Named("PublicIpAvailable") Predicate publicIpAvailable) { + PublicIpAvailablePredicateFactory publicIpAvailable, LocationToResourceGroupName locationToResourceGroupName) { this.api = api; this.azureComputeConstants = azureComputeConstants; - this.azureGroup = azureComputeConstants.azureResourceGroup(); this.cleanupResources = cleanupResources; this.regionIds = regionIds; this.publicIpAvailable = publicIpAvailable; + this.locationToResourceGroupName = locationToResourceGroupName; } @Override - public NodeAndInitialCredentials createNodeWithGroupEncodedIntoName( - final String group, final String name, final Template template) { + public NodeAndInitialCredentials createNodeWithGroupEncodedIntoName(final String group, + final String name, final Template template) { AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class); + String azureGroup = locationToResourceGroupName.apply(template.getLocation().getId()); - // TODO Store group apart from the name to be able to identify nodes with custom names in the configured group + // TODO Store group apart from the name to be able to identify nodes with + // custom names in the configured group // TODO ARM specific options // TODO user metadata and tags // TODO network ids => create one nic in each network // TODO inbound ports - + String locationName = template.getLocation().getId(); String subnetId = templateOptions.getSubnetId(); - NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName); + NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, azureGroup); StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob()); HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build(); OSProfile osProfile = createOsProfile(name, template); - NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build(); + NetworkProfile networkProfile = NetworkProfile.builder() + .networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build(); VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder() - .licenseType(null) // TODO - .availabilitySet(null) // TODO - .hardwareProfile(hardwareProfile) - .storageProfile(storageProfile) - .osProfile(osProfile) - .networkProfile(networkProfile) - .build(); + .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); + 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, name, null); + // Safe to pass null credentials here, as jclouds will default populate + // the node with the default credentials from the image, or the ones in + // the options, if provided. + RegionAndId regionAndId = RegionAndId.fromRegionAndId(template.getLocation().getId(), name); + return new NodeAndInitialCredentials(virtualMachine, regionAndId.slashEncode(), null); } @Override @@ -150,16 +157,11 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter hwProfiles = Lists.newArrayList(); for (Location location : listLocations()) { Iterable vmSizes = api.getVMSizeApi(location.name()).list(); - for (VMSize vmSize : vmSizes){ - VMHardware hwProfile = VMHardware.create( - vmSize.name(), - vmSize.numberOfCores(), - vmSize.osDiskSizeInMB(), - vmSize.resourceDiskSizeInMB(), - vmSize.memoryInMB(), - vmSize.maxDataDiskCount(), - location.name(), - false); + for (VMSize vmSize : vmSizes) { + VMHardware hwProfile = VMHardware + .create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(), + vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name(), + false); hwProfiles.add(hwProfile); } } @@ -188,7 +190,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter listImagesByLocation(String location) { final List osImages = Lists.newArrayList(); - Iterable publishers = Splitter.on(',').trimResults().omitEmptyStrings().split(this.azureComputeConstants.azureImagePublishers()); + Iterable publishers = Splitter.on(',').trimResults().omitEmptyStrings() + .split(this.azureComputeConstants.azureImagePublishers()); for (String publisher : publishers) { osImages.addAll(getImagesFromPublisher(publisher, location)); } @@ -199,42 +202,50 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter listImages() { final List osImages = Lists.newArrayList(); - for (Location location : listLocations()){ + for (Location location : listLocations()) { osImages.addAll(listImagesByLocation(location.name())); } + // list custom images - List storages = api.getStorageAccountApi(azureGroup).list(); - for (StorageService storage : storages) { - String name = storage.name(); - StorageService storageService = api.getStorageAccountApi(azureGroup).get(name); - if (storageService != null - && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) { - String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1(); - BlobHelper blobHelper = new BlobHelper(storage.name(), key); - try { - List images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER, - storage.location()); - osImages.addAll(images); - } finally { - closeQuietly(blobHelper); + for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) { + String azureGroup = resourceGroup.name(); + List storages = api.getStorageAccountApi(azureGroup).list(); + + for (StorageService storage : storages) { + String name = storage.name(); + StorageService storageService = api.getStorageAccountApi(azureGroup).get(name); + if (storageService != null + && Status.Succeeded == storageService.storageServiceProperties().provisioningState()) { + String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1(); + BlobHelper blobHelper = new BlobHelper(storage.name(), key); + try { + List images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER, + storage.location()); + osImages.addAll(images); + } finally { + closeQuietly(blobHelper); + } } } } - + return osImages; } @Override public VMImage getImage(final String id) { VMImage image = decodeFieldsFromUniqueId(id); + String azureGroup = locationToResourceGroupName.apply(image.location()); + if (image.custom()) { VMImage customImage = null; StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(image.storage()); if (keys == null) { - // If the storage account for the image does not exist, it means the image was deleted + // If the storage account for the image does not exist, it means the + // image was deleted return null; } - + BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1()); try { if (blobHelper.customImageExists()) { @@ -270,40 +281,38 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter listLocations() { final Iterable vmLocations = FluentIterable.from(api.getResourceProviderApi().get("Microsoft.Compute")) - .filter(new Predicate() { - @Override - public boolean apply(ResourceProviderMetaData input) { - return input.resourceType().equals("virtualMachines"); - } - }) - .transformAndConcat(new Function>() { - @Override - public Iterable apply(ResourceProviderMetaData resourceProviderMetaData) { - return resourceProviderMetaData.locations(); - } - }); + .filter(new Predicate() { + @Override + public boolean apply(ResourceProviderMetaData input) { + return input.resourceType().equals("virtualMachines"); + } + }).transformAndConcat(new Function>() { + @Override + public Iterable apply(ResourceProviderMetaData resourceProviderMetaData) { + return resourceProviderMetaData.locations(); + } + }); - List locations = FluentIterable.from(api.getLocationApi().list()) - .filter(new Predicate() { - @Override - public boolean apply(Location location) { - return Iterables.contains(vmLocations, location.displayName()); - } - }) - .filter(new Predicate() { - @Override - public boolean apply(Location location) { - return regionIds.get().isEmpty() ? true : regionIds.get().contains(location.name()); - } - }) - .toList(); + List locations = FluentIterable.from(api.getLocationApi().list()).filter(new Predicate() { + @Override + public boolean apply(Location location) { + return Iterables.contains(vmLocations, location.displayName()); + } + }).filter(new Predicate() { + @Override + public boolean apply(Location location) { + return regionIds.get().isEmpty() ? true : regionIds.get().contains(location.name()); + } + }).toList(); return locations; } @Override public VirtualMachine getNode(final String id) { - return api.getVirtualMachineApi(azureGroup).get(id); + RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); + String azureGroup = locationToResourceGroupName.apply(regionAndId.region()); + return api.getVirtualMachineApi(azureGroup).get(regionAndId.id()); } @Override @@ -313,22 +322,32 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter listNodes() { - return api.getVirtualMachineApi(azureGroup).list(); + ImmutableList.Builder nodes = ImmutableList.builder(); + for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) { + nodes.addAll(api.getVirtualMachineApi(resourceGroup.name()).list()); + } + return nodes.build(); } @Override @@ -341,59 +360,54 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapterof()); + + return StorageProfile.create(imageReference, osDisk, ImmutableList. of()); } } diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java index 24f02ead6c..34a5160d8b 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/config/AzureComputeServiceContextModule.java @@ -24,7 +24,6 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_P import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; @@ -137,10 +136,6 @@ public class AzureComputeServiceContextModule @Inject private String tcpRuleRegexpProperty; - @Named(RESOURCE_GROUP_NAME) - @Inject - private String azureResourceGroupProperty; - @Named(IMAGE_PUBLISHERS) @Inject private String azureImagePublishersProperty; @@ -161,10 +156,6 @@ public class AzureComputeServiceContextModule return Long.parseLong(operationTimeoutProperty); } - public String azureResourceGroup() { - return azureResourceGroupProperty; - } - public String azureImagePublishers() { return azureImagePublishersProperty; } @@ -199,11 +190,11 @@ public class AzureComputeServiceContextModule } @Provides - @com.google.inject.name.Named(TIMEOUT_NODE_RUNNING) - protected Predicate provideVirtualMachineRunningPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, PollPeriod pollPeriod) { - String azureGroup = azureComputeConstants.azureResourceGroup(); - return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.RUNNING), timeouts.nodeRunning, - pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); + @Named(TIMEOUT_NODE_RUNNING) + protected VirtualMachineInStatePredicateFactory provideVirtualMachineRunningPredicate(final AzureComputeApi api, + Timeouts timeouts, PollPeriod pollPeriod) { + return new VirtualMachineInStatePredicateFactory(api, PowerState.RUNNING, timeouts.nodeRunning, + pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); } @Provides @@ -229,19 +220,17 @@ public class AzureComputeServiceContextModule @Provides @Named(TIMEOUT_NODE_SUSPENDED) - protected Predicate provideNodeSuspendedPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, - Timeouts timeouts, PollPeriod pollPeriod) { - String azureGroup = azureComputeConstants.azureResourceGroup(); - return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.STOPPED), timeouts.nodeTerminated, - pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); + protected VirtualMachineInStatePredicateFactory provideNodeSuspendedPredicate(final AzureComputeApi api, + Timeouts timeouts, PollPeriod pollPeriod) { + return new VirtualMachineInStatePredicateFactory(api, PowerState.STOPPED, timeouts.nodeTerminated, + pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); } @Provides - @Named("PublicIpAvailable") - protected Predicate providePublicIpAvailablePredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, - Timeouts timeouts, PollPeriod pollPeriod) { - String azureGroup = azureComputeConstants.azureResourceGroup(); - return retry(new PublicIpAvailablePredicate(api, azureGroup), azureComputeConstants.operationTimeout(), + protected PublicIpAvailablePredicateFactory providePublicIpAvailablePredicate(final AzureComputeApi api, + final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, + PollPeriod pollPeriod) { + return new PublicIpAvailablePredicateFactory(api, azureComputeConstants.operationTimeout(), azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod()); } @@ -280,45 +269,62 @@ public class AzureComputeServiceContextModule } } - @VisibleForTesting - static class VirtualMachineInStatePredicate implements Predicate { + public static class VirtualMachineInStatePredicateFactory { private final AzureComputeApi api; - private final String azureGroup; private final PowerState powerState; + private final long timeout; + private final long period; + private final long maxPeriod; - 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"); + VirtualMachineInStatePredicateFactory(AzureComputeApi api, PowerState powerState, long timeout, + long period, long maxPeriod) { + this.api = checkNotNull(api, "api cannot be null"); + this.powerState = checkNotNull(powerState, "powerState cannot be null"); + this.timeout = timeout; + this.period = period; + this.maxPeriod = maxPeriod; } - @Override - public boolean apply(String name) { - checkNotNull(name, "name cannot be null"); - VirtualMachineInstance vmInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name); - if (vmInstance == null) return false; - return powerState == vmInstance.powerState(); + public Predicate create(final String azureGroup) { + return retry(new Predicate() { + @Override + public boolean apply(String name) { + checkNotNull(name, "name cannot be null"); + VirtualMachineInstance vmInstance = api.getVirtualMachineApi(azureGroup).getInstanceDetails(name); + if (vmInstance == null) + return false; + return powerState == vmInstance.powerState(); + } + }, timeout, period, maxPeriod); } } - @VisibleForTesting - static class PublicIpAvailablePredicate implements Predicate { + public static class PublicIpAvailablePredicateFactory { private final AzureComputeApi api; - private final String azureGroup; + private final long timeout; + private final long period; + private final long maxPeriod; - public PublicIpAvailablePredicate(AzureComputeApi api, String azureGroup) { - this.api = checkNotNull(api, "api must not be null"); - this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null"); + PublicIpAvailablePredicateFactory(AzureComputeApi api, long timeout, + long period, long maxPeriod) { + this.api = checkNotNull(api, "api cannot be null"); + this.timeout = timeout; + this.period = period; + this.maxPeriod = maxPeriod; } - - @Override - public boolean apply(String name) { - checkNotNull(name, "name cannot be null"); - PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name); - if (publicIp == null) return false; - return publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded"); + + public Predicate create(final String azureGroup) { + return retry(new Predicate() { + @Override + public boolean apply(String name) { + checkNotNull(name, "name cannot be null"); + PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name); + if (publicIp == null) return false; + return publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded"); + } + }, timeout, period, maxPeriod); } } diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java index 99c9c6cde1..1e57899d5c 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java @@ -31,8 +31,10 @@ import javax.annotation.Resource; import org.jclouds.Constants; import org.jclouds.azurecompute.arm.AzureComputeApi; -import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; +import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory; +import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage; +import org.jclouds.azurecompute.arm.domain.RegionAndId; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.VMImage; @@ -61,27 +63,27 @@ public class AzureComputeImageExtension implements ImageExtension { protected Logger logger = Logger.NULL; private final AzureComputeApi api; - private final String group; private final ListeningExecutorService userExecutor; private final Predicate imageAvailablePredicate; - private final Predicate nodeSuspendedPredicate; + private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate; private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage; private final CleanupResources cleanupResources; + private final LocationToResourceGroupName locationToResourceGroupName; @Inject AzureComputeImageExtension(AzureComputeApi api, @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate imageAvailablePredicate, - @Named(TIMEOUT_NODE_SUSPENDED) Predicate nodeSuspendedPredicate, - AzureComputeConstants azureComputeConstants, + @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, - ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources) { + ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources, + LocationToResourceGroupName locationToResourceGroupName) { this.api = api; this.imageAvailablePredicate = imageAvailablePredicate; this.nodeSuspendedPredicate = nodeSuspendedPredicate; - this.group = azureComputeConstants.azureResourceGroup(); this.userExecutor = userExecutor; this.resourceDefinitionToImage = resourceDefinitionToImage; this.cleanupResources = cleanupResources; + this.locationToResourceGroupName = locationToResourceGroupName; } @Override @@ -92,21 +94,23 @@ public class AzureComputeImageExtension implements ImageExtension { @Override public ListenableFuture createImage(ImageTemplate template) { final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; - final String id = cloneTemplate.getSourceNodeId(); - final String name = cloneTemplate.getName(); + + final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId()); + final String group = locationToResourceGroupName.apply(regionAndId.region()); - logger.debug(">> stopping node %s...", id); - api.getVirtualMachineApi(group).stop(id); - checkState(nodeSuspendedPredicate.apply(id), "Node %s was not suspended within the configured time limit", id); + logger.debug(">> stopping node %s...", regionAndId.slashEncode()); + api.getVirtualMachineApi(group).stop(regionAndId.id()); + checkState(nodeSuspendedPredicate.create(group).apply(regionAndId.id()), + "Node %s was not suspended within the configured time limit", regionAndId.slashEncode()); return userExecutor.submit(new Callable() { @Override public Image call() throws Exception { - logger.debug(">> generalizing virtal machine %s...", id); - api.getVirtualMachineApi(group).generalize(id); + logger.debug(">> generalizing virtal machine %s...", regionAndId.id()); + api.getVirtualMachineApi(group).generalize(regionAndId.id()); - logger.debug(">> capturing virtual machine %s to container %s...", id, CONTAINER_NAME); - URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME); + logger.debug(">> capturing virtual machine %s to container %s...", regionAndId.id(), CONTAINER_NAME); + URI uri = api.getVirtualMachineApi(group).capture(regionAndId.id(), cloneTemplate.getName(), CONTAINER_NAME); checkState(uri != null && imageAvailablePredicate.apply(uri), "Image %s was not created within the configured time limit", cloneTemplate.getName()); @@ -114,7 +118,8 @@ public class AzureComputeImageExtension implements ImageExtension { checkState(definitions.size() == 1, "Expected one resource definition after creating the image but %s were returned", definitions.size()); - Image image = resourceDefinitionToImage.create(id, name).apply(definitions.get(0)); + Image image = resourceDefinitionToImage.create(cloneTemplate.getSourceNodeId(), cloneTemplate.getName()) + .apply(definitions.get(0)); logger.debug(">> created %s", image); return image; } @@ -130,7 +135,7 @@ public class AzureComputeImageExtension implements ImageExtension { StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage()); BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1()); - + try { // This removes now all the images in this storage. At least in theory, // there should be just one and if there is diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java new file mode 100644 index 0000000000..c97850a2b1 --- /dev/null +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/LocationToResourceGroupName.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.compute.functions; + +import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER; +import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX; + +import javax.inject.Inject; +import javax.inject.Named; + +import com.google.common.base.Function; + +/** + * Returns the name of the resource group for the current location. + */ +public class LocationToResourceGroupName implements Function { + + private final String prefix; + private final char delimiter; + + @Inject + LocationToResourceGroupName(@Named(RESOURCENAME_PREFIX) String prefix, @Named(RESOURCENAME_DELIMITER) char delimiter) { + this.prefix = prefix; + this.delimiter = delimiter; + } + + @Override + public String apply(String input) { + return String.format("%s%s%s", prefix, delimiter, input); + } + +} diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java index cce6b50847..02fb0f49b6 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java @@ -23,7 +23,7 @@ import java.util.Map; import javax.inject.Inject; import org.jclouds.azurecompute.arm.AzureComputeApi; -import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; +import org.jclouds.azurecompute.arm.domain.RegionAndId; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VirtualMachine; @@ -39,21 +39,24 @@ public class ResourceDefinitionToCustomImage implements Function vmImageToImage; private final String imageName; private final String storageAccountName; private final VirtualMachine vm; + private final String resourceGroup; @Inject - ResourceDefinitionToCustomImage(AzureComputeApi api, AzureComputeConstants azureComputeConstants, + ResourceDefinitionToCustomImage(AzureComputeApi api, StorageProfileToStorageAccountName storageProfileToStorageAccountName, - Function vmImageToImage, @Assisted("nodeId") String nodeId, + Function vmImageToImage, LocationToResourceGroupName locationToResourceGroupName, + @Assisted("nodeId") String nodeId, @Assisted("imageName") String imageName) { this.vmImageToImage = vmImageToImage; - this.resourceGroup = azureComputeConstants.azureResourceGroup(); this.imageName = imageName; - this.vm = api.getVirtualMachineApi(resourceGroup).get(nodeId); + + RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId); + this.resourceGroup = locationToResourceGroupName.apply(regionAndId.region()); + this.vm = api.getVirtualMachineApi(this.resourceGroup).get(regionAndId.id()); this.storageAccountName = storageProfileToStorageAccountName.apply(vm.properties().storageProfile()); } diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java index e151a4a17e..1f9087028f 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java @@ -38,6 +38,7 @@ import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextMod import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IpConfiguration; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; +import org.jclouds.azurecompute.arm.domain.RegionAndId; import org.jclouds.azurecompute.arm.domain.StorageProfile; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.VMImage; @@ -110,7 +111,6 @@ public class VirtualMachineToNodeMetadata implements Function> images; @@ -119,28 +119,32 @@ public class VirtualMachineToNodeMetadata implements Function credentialStore; private final Function vmImageToImge; private final StorageProfileToStorageAccountName storageProfileToStorageAccountName; + private final LocationToResourceGroupName locationToResourceGroupName; @Inject VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention, Supplier> images, Supplier> hardwares, @Memoized Supplier> locations, Map credentialStore, final AzureComputeConstants azureComputeConstants, Function vmImageToImge, - StorageProfileToStorageAccountName storageProfileToStorageAccountName) { + StorageProfileToStorageAccountName storageProfileToStorageAccountName, + LocationToResourceGroupName locationToResourceGroupName) { this.api = api; this.nodeNamingConvention = namingConvention.createWithoutPrefix(); this.images = checkNotNull(images, "images cannot be null"); this.locations = checkNotNull(locations, "locations cannot be null"); this.hardwares = checkNotNull(hardwares, "hardwares cannot be null"); this.credentialStore = credentialStore; - this.azureGroup = azureComputeConstants.azureResourceGroup(); this.vmImageToImge = vmImageToImge; this.storageProfileToStorageAccountName = storageProfileToStorageAccountName; + this.locationToResourceGroupName = locationToResourceGroupName; } @Override public NodeMetadata apply(VirtualMachine virtualMachine) { + String azureGroup = locationToResourceGroupName.apply(virtualMachine.location()); + NodeMetadataBuilder builder = new NodeMetadataBuilder(); - builder.id(virtualMachine.name()); + builder.id(RegionAndId.fromRegionAndId(virtualMachine.location(), virtualMachine.name()).slashEncode()); builder.providerId(virtualMachine.id()); builder.name(virtualMachine.name()); builder.hostname(virtualMachine.name()); @@ -180,7 +184,7 @@ public class VirtualMachineToNodeMetadata implements Function image = findImage(virtualMachine.properties().storageProfile(), locationName); + Optional image = findImage(virtualMachine.properties().storageProfile(), locationName, azureGroup); if (image.isPresent()) { builder.imageId(image.get().getId()); builder.operatingSystem(image.get().getOperatingSystem()); @@ -239,7 +243,7 @@ public class VirtualMachineToNodeMetadata implements Function findImage(final StorageProfile storageProfile, String locatioName) { + protected Optional findImage(final StorageProfile storageProfile, String locatioName, String azureGroup) { if (storageProfile.imageReference() != null) { return Optional.fromNullable(images.get().get( encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference()))); diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java index 99528fdcbe..024204bec0 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CreateResourceGroupThenCreateNodes.java @@ -35,6 +35,7 @@ import javax.inject.Singleton; import org.jclouds.Constants; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; +import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.StorageService; @@ -73,20 +74,23 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco private final AzureComputeApi api; private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants; + private final LocationToResourceGroupName locationToResourceGroupName; @Inject protected CreateResourceGroupThenCreateNodes( CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy, ListNodesStrategy listNodesStrategy, GroupNamingConvention.Factory namingConvention, - @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, - CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, - AzureComputeApi api, AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) { + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, + CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, + AzureComputeApi api, AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, + LocationToResourceGroupName locationToResourceGroupName) { super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor, customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory); this.api = checkNotNull(api, "api cannot be null"); checkNotNull(userExecutor, "userExecutor cannot be null"); this.azureComputeConstants = azureComputeConstants; + this.locationToResourceGroupName = locationToResourceGroupName; } @Override @@ -100,7 +104,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco logger.warn(">> a runScript was configured but no SSH key has been provided. " + "Authentication will delegate to the ssh-agent"); } - String azureGroupName = this.azureComputeConstants.azureResourceGroup(); + String azureGroupName = locationToResourceGroupName.apply(template.getLocation().getId()); AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class); // create resource group for jclouds group if it does not already exist diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java index 8f945d94e2..2a15e4b34a 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/config/AzureComputeProperties.java @@ -34,8 +34,6 @@ public class AzureComputeProperties { public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.arm.tcp.rule.regexp"; - public static final String RESOURCE_GROUP_NAME = "jclouds.azurecompute.arm.operation.resourcegroup"; - public static final String IMAGE_PUBLISHERS = "jclouds.azurecompute.arm.publishers"; public static final String DEFAULT_IMAGE_LOGIN = "jclouds.azurecompute.arm.defaultimagelogin"; diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java new file mode 100644 index 0000000000..233109aa0a --- /dev/null +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/domain/RegionAndId.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.azurecompute.arm.domain; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; + +@AutoValue +public abstract class RegionAndId { + + public abstract String region(); + public abstract String id(); + + RegionAndId() { + + } + + public static RegionAndId fromSlashEncoded(String id) { + Iterable parts = Splitter.on('/').split(checkNotNull(id, "id")); + checkArgument(Iterables.size(parts) == 2, "id must be in format regionId/id"); + return new AutoValue_RegionAndId(Iterables.get(parts, 0), Iterables.get(parts, 1)); + } + + public static RegionAndId fromRegionAndId(String region, String id) { + return new AutoValue_RegionAndId(region, id); + } + + public String slashEncode() { + return region() + "/" + id(); + } + +} diff --git a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java index 39cc32c23d..ead676a751 100644 --- a/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java +++ b/providers/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/functions/CleanupResources.java @@ -16,7 +16,6 @@ */ package org.jclouds.azurecompute.arm.functions; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.notNull; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.transform; @@ -25,7 +24,6 @@ import static org.jclouds.util.Closeables2.closeQuietly; import java.net.URI; import java.util.List; -import java.util.Map; import javax.annotation.Resource; import javax.inject.Inject; @@ -33,10 +31,11 @@ import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IpConfiguration; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; -import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.azurecompute.arm.domain.RegionAndId; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.util.BlobHelper; @@ -46,10 +45,8 @@ import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; @Singleton public class CleanupResources implements Function { @@ -61,28 +58,29 @@ public class CleanupResources implements Function { protected final AzureComputeApi api; private final Predicate resourceDeleted; private final StorageProfileToStorageAccountName storageProfileToStorageAccountName; + private final LocationToResourceGroupName locationToResourceGroupName; @Inject CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate resourceDeleted, - StorageProfileToStorageAccountName storageProfileToStorageAccountName) { + StorageProfileToStorageAccountName storageProfileToStorageAccountName, + LocationToResourceGroupName locationToResourceGroupName) { this.api = azureComputeApi; this.resourceDeleted = resourceDeleted; this.storageProfileToStorageAccountName = storageProfileToStorageAccountName; + this.locationToResourceGroupName = locationToResourceGroupName; } @Override public Boolean apply(final String id) { - logger.debug(">> destroying %s ...", id); - - Map resourceGroupNamesAndVirtualMachines = getResourceGroupNamesAndVirtualMachines(id); - if (resourceGroupNamesAndVirtualMachines.isEmpty()) + RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); + String group = locationToResourceGroupName.apply(regionAndId.region()); + + VirtualMachine virtualMachine = api.getVirtualMachineApi(group).get(regionAndId.id()); + if (virtualMachine == null) { return true; + } - String group = checkNotNull(resourceGroupNamesAndVirtualMachines.entrySet().iterator().next().getKey(), - "resourceGroup name must not be null"); - VirtualMachine virtualMachine = checkNotNull(resourceGroupNamesAndVirtualMachines.get(group), - "virtualMachine must not be null"); - + logger.debug(">> destroying %s ...", regionAndId.slashEncode()); boolean vmDeleted = deleteVirtualMachine(group, virtualMachine); // We don't delete the network here, as it is global to the resource @@ -163,14 +161,4 @@ public class CleanupResources implements Function { return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name())); } - private Map getResourceGroupNamesAndVirtualMachines(String id) { - for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) { - String group = resourceGroup.name(); - VirtualMachine virtualMachine = api.getVirtualMachineApi(group).get(id); - if (virtualMachine != null) { - return ImmutableMap.of(group, virtualMachine); - } - } - return Maps.newHashMap(); - } } diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java index c3389540c4..c59509f14b 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureComputeServiceLiveTest.java @@ -16,19 +16,9 @@ */ package org.jclouds.azurecompute.arm.compute; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE; import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey; -import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; import java.util.Properties; -import java.util.concurrent.TimeUnit; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; @@ -78,19 +68,8 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest { @Override protected Properties setupProperties() { Properties properties = super.setupProperties(); - String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES)); - properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout); - properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout); - properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout); - properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout); - properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout); - properties.put(RESOURCE_GROUP_NAME, "jc"); - properties.put(PROPERTY_REGIONS, "eastus"); - properties.put(IMAGE_PUBLISHERS, "Canonical"); - AzureLiveTestUtils.defaultProperties(properties); - checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); - + setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); return properties; } diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java index c20655b091..56200c485b 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/AzureTemplateBuilderLiveTest.java @@ -16,8 +16,6 @@ */ package org.jclouds.azurecompute.arm.compute; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -58,25 +56,23 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest { @Override protected Properties setupProperties() { Properties properties = super.setupProperties(); - properties.put(RESOURCE_GROUP_NAME, "jc"); - AzureLiveTestUtils.defaultProperties(properties); - checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); - + setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); return properties; } - + @Override @Test public void testDefaultTemplateBuilder() throws IOException { Template defaultTemplate = view.getComputeService().templateBuilder().build(); assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[45]\\.[01][04]\\.[0-9]-LTS"), - "Version mismatch, expected dd.dd.d-LTS, found: " + defaultTemplate.getImage().getOperatingSystem().getVersion()); + "Version mismatch, expected dd.dd.d-LTS, found: " + + defaultTemplate.getImage().getOperatingSystem().getVersion()); assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU); assertEquals(getCores(defaultTemplate.getHardware()), 1.0d); } - + @Override protected Set getIso3166Codes() { return Region.iso3166Codes(); diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java index de44668ed4..c8a9259dc5 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtensionLiveTest.java @@ -16,20 +16,10 @@ */ package org.jclouds.azurecompute.arm.compute.extensions; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN; -import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE; import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey; -import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; import java.util.Map; import java.util.Properties; -import java.util.concurrent.TimeUnit; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; @@ -63,19 +53,8 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe @Override protected Properties setupProperties() { Properties properties = super.setupProperties(); - String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES)); - properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout); - properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout); - properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout); - properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout); - properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout); - properties.put(RESOURCE_GROUP_NAME, "jc"); - properties.put(PROPERTY_REGIONS, "eastus"); - properties.put(IMAGE_PUBLISHERS, "Canonical"); - AzureLiveTestUtils.defaultProperties(properties); - checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); - + setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); return properties; } diff --git a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java index 3f69e59f42..125e11a260 100644 --- a/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java +++ b/providers/azurecompute-arm/src/test/java/org/jclouds/azurecompute/arm/internal/AzureLiveTestUtils.java @@ -16,21 +16,34 @@ */ package org.jclouds.azurecompute.arm.internal; -import java.util.Properties; - +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN; +import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET; import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + public class AzureLiveTestUtils { public static Properties defaultProperties(Properties properties) { properties = properties == null ? new Properties() : properties; - properties.put("oauth.identity", "foo"); - properties.put("oauth.credential", "password"); - properties.put("oauth.endpoint", "https://login.microsoftonline.com/oauth2/token"); properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); - properties.put(PROPERTY_REGIONS, "northeurope"); + properties.put(PROPERTY_REGIONS, "eastus"); + properties.put(IMAGE_PUBLISHERS, "Canonical"); + + String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES)); + properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout); + properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout); + properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout); + properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout); + properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout); + return properties; } }