Cleanup legacy code and introduce the resource group cache
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/fde928eb Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/fde928eb Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/fde928eb Branch: refs/heads/master Commit: fde928eb084c7d7291702265acec8fd4528e795d Parents: 867ddef Author: Ignasi Barrera <[email protected]> Authored: Thu Jan 26 10:34:49 2017 +0100 Committer: Ignasi Barrera <[email protected]> Committed: Thu Jan 26 21:58:23 2017 +0100 ---------------------------------------------------------------------- .../arm/AzureComputeProviderMetadata.java | 17 +- .../arm/compute/AzureComputeService.java | 18 +- .../arm/compute/AzureComputeServiceAdapter.java | 51 +++-- .../AzureComputeServiceContextModule.java | 116 +++-------- .../extensions/AzureComputeImageExtension.java | 25 ++- .../AzureComputeSecurityGroupExtension.java | 75 +++---- .../NetworkSecurityRuleToIpPermission.java | 4 +- .../ResourceDefinitionToCustomImage.java | 33 +-- .../functions/VirtualMachineToNodeMetadata.java | 41 ++-- .../loaders/CreateSecurityGroupIfNeeded.java | 13 +- .../loaders/ResourceGroupForLocation.java | 62 ++++++ .../compute/options/AzureTemplateOptions.java | 108 +--------- .../predicates/IsDeploymentInRegions.java | 47 ----- .../arm/compute/strategy/CleanupResources.java | 205 +++++++++++++++++++ .../CreateResourceGroupThenCreateNodes.java | 94 ++++----- .../arm/config/AzureComputeProperties.java | 14 -- .../arm/functions/CleanupResources.java | 202 ------------------ ...reComputeSecurityGroupExtensionLiveTest.java | 36 ++-- 18 files changed, 482 insertions(+), 679 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/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 dd516ef..1590bf2 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 @@ -19,16 +19,10 @@ package org.jclouds.azurecompute.arm; import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.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.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.POLL_INITIAL_PERIOD; @@ -83,27 +77,22 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata { public static Properties defaultProperties() { final Properties properties = AzureManagementApiMetadata.defaultProperties(); properties.put(POLL_INITIAL_PERIOD, 1000); - properties.put(POLL_MAX_PERIOD, 10000); + properties.put(POLL_MAX_PERIOD, 15000); properties.put(OPERATION_TIMEOUT, 46000000); - properties.put(OPERATION_POLL_INITIAL_PERIOD, 5); - properties.put(OPERATION_POLL_MAX_PERIOD, 15); + properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000); // Default max wait in rate limit: 5m30s properties.put(PROPERTY_MAX_RATE_LIMIT_WAIT, 330000); - properties.put(TCP_RULE_FORMAT, "tcp_%s-%s"); - properties.put(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(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 properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!"); properties.put(IMAGE_AUTHENTICATE_SUDO, "true"); properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS"); - properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000); // Api versions used in each API properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01"); properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01"); @@ -114,7 +103,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata { properties.put(API_VERSION_PREFIX + PublicIPAddressApi.class.getSimpleName(), "2015-06-15"); properties.put(API_VERSION_PREFIX + ResourceGroupApi.class.getSimpleName(), "2015-01-01"); properties.put(API_VERSION_PREFIX + ResourceProviderApi.class.getSimpleName(), "2015-01-01"); - properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), STORAGE_API_VERSION); + properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), "2015-06-15"); properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15"); properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15"); properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15"); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java index a561375..f566a69 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/AzureComputeService.java @@ -31,8 +31,8 @@ import javax.inject.Provider; import javax.inject.Singleton; import org.jclouds.Constants; -import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; -import org.jclouds.azurecompute.arm.functions.CleanupResources; +import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.collect.Memoized; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.callables.RunScriptOnNode; @@ -62,6 +62,7 @@ import org.jclouds.scriptbuilder.functions.InitAdminAccess; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.ListeningExecutorService; @@ -69,7 +70,7 @@ import com.google.common.util.concurrent.ListeningExecutorService; @Singleton public class AzureComputeService extends BaseComputeService { private final CleanupResources cleanupResources; - private final LocationToResourceGroupName locationToResourceGroupName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject protected AzureComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, @@ -88,15 +89,14 @@ public class AzureComputeService extends BaseComputeService { PersistNodeCredentials persistNodeCredentials, Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CleanupResources cleanupResources, Optional<ImageExtension> imageExtension, - Optional<SecurityGroupExtension> securityGroupExtension, - LocationToResourceGroupName locationToResourceGroupName) { + Optional<SecurityGroupExtension> securityGroupExtension, LoadingCache<String, ResourceGroup> resourceGroupMap) { super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy, getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension); this.cleanupResources = cleanupResources; - this.locationToResourceGroupName = locationToResourceGroupName; + this.resourceGroupMap = resourceGroupMap; } @Override @@ -105,11 +105,11 @@ public class AzureComputeService extends BaseComputeService { ImmutableSet.Builder<String> resourceGroups = ImmutableSet.builder(); for (NodeMetadata deadNode : deadNodes) { - String resourceGroup = locationToResourceGroupName.apply(deadNode.getLocation().getId()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(deadNode.getLocation().getId()); - resourceGroups.add(resourceGroup); + resourceGroups.add(resourceGroup.name()); if (deadNode.getGroup() != null) { - regionGroups.put(resourceGroup, deadNode.getGroup()); + regionGroups.put(resourceGroup.name(), deadNode.getGroup()); } try { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/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 269f6b0..5a8204e 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 @@ -26,6 +26,7 @@ import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageE import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsCommaDelimitedValue; import static org.jclouds.util.Closeables2.closeQuietly; @@ -39,10 +40,9 @@ 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.compute.strategy.CleanupResources; import org.jclouds.azurecompute.arm.domain.DataDisk; import org.jclouds.azurecompute.arm.domain.HardwareProfile; import org.jclouds.azurecompute.arm.domain.IdReference; @@ -76,7 +76,6 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.features.OSImageApi; import org.jclouds.azurecompute.arm.features.PublicIPAddressApi; -import org.jclouds.azurecompute.arm.functions.CleanupResources; import org.jclouds.azurecompute.arm.util.BlobHelper; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.domain.Image; @@ -92,6 +91,7 @@ import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -113,21 +113,21 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual private final CleanupResources cleanupResources; private final AzureComputeApi api; - private final AzureComputeConstants azureComputeConstants; + private final List<String> imagePublishers; private final Supplier<Set<String>> regionIds; private final PublicIpAvailablePredicateFactory publicIpAvailable; - private final LocationToResourceGroupName locationToResourceGroupName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject - AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants, + AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers, CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds, - PublicIpAvailablePredicateFactory publicIpAvailable, LocationToResourceGroupName locationToResourceGroupName) { + PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap) { this.api = api; - this.azureComputeConstants = azureComputeConstants; + this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers); this.cleanupResources = cleanupResources; this.regionIds = regionIds; this.publicIpAvailable = publicIpAvailable; - this.locationToResourceGroupName = locationToResourceGroupName; + this.resourceGroupMap = resourceGroupMap; } @Override @@ -135,14 +135,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual final String name, final Template template) { AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class); - String azureGroup = locationToResourceGroupName.apply(template.getLocation().getId()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(template.getLocation().getId()); // TODO ARM specific options // TODO network ids => create one nic in each network String locationName = template.getLocation().getId(); String subnetId = templateOptions.getSubnetId(); - NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, azureGroup, template.getOptions()); + NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroup.name(), + template.getOptions()); StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob()); HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build(); OSProfile osProfile = createOsProfile(name, template); @@ -160,7 +161,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(template.getOptions()); Plan plan = getMarketplacePlanFromImageMetadata(template.getImage()); - VirtualMachine virtualMachine = api.getVirtualMachineApi(azureGroup).create(name, template.getLocation().getId(), + VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroup.name()).create(name, template.getLocation().getId(), virtualMachineProperties, metadataAndTags, plan); // Safe to pass null credentials here, as jclouds will default populate @@ -210,9 +211,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual private List<VMImage> listImagesByLocation(String location) { final List<VMImage> osImages = Lists.newArrayList(); - Iterable<String> publishers = Splitter.on(',').trimResults().omitEmptyStrings() - .split(this.azureComputeConstants.azureImagePublishers()); - for (String publisher : publishers) { + for (String publisher : imagePublishers) { osImages.addAll(getImagesFromPublisher(publisher, location)); } return osImages; @@ -259,11 +258,11 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual @Override public VMImage getImage(final String id) { VMImage image = decodeFieldsFromUniqueId(id); - String azureGroup = locationToResourceGroupName.apply(image.location()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location()); if (image.custom()) { VMImage customImage = null; - StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(image.storage()); + StorageServiceKeys keys = api.getStorageAccountApi(resourceGroup.name()).getKeys(image.storage()); if (keys == null) { // If the storage account for the image does not exist, it means the // image was deleted @@ -273,7 +272,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1()); try { if (blobHelper.customImageExists()) { - List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup, + List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, resourceGroup.name(), CUSTOM_IMAGE_OFFER, image.location()); customImage = find(customImagesInStorage, new Predicate<VMImage>() { @Override @@ -336,8 +335,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual @Override public VirtualMachine getNode(final String id) { RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); - String azureGroup = locationToResourceGroupName.apply(regionAndId.region()); - return api.getVirtualMachineApi(azureGroup).get(regionAndId.id()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + return api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id()); } @Override @@ -348,22 +347,22 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual @Override public void rebootNode(final String id) { RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); - String azureGroup = locationToResourceGroupName.apply(regionAndId.region()); - api.getVirtualMachineApi(azureGroup).restart(regionAndId.id()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + api.getVirtualMachineApi(resourceGroup.name()).restart(regionAndId.id()); } @Override public void resumeNode(final String id) { RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); - String azureGroup = locationToResourceGroupName.apply(regionAndId.region()); - api.getVirtualMachineApi(azureGroup).start(regionAndId.id()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + api.getVirtualMachineApi(resourceGroup.name()).start(regionAndId.id()); } @Override public void suspendNode(final String id) { RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); - String azureGroup = locationToResourceGroupName.apply(regionAndId.region()); - api.getVirtualMachineApi(azureGroup).stop(regionAndId.id()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + api.getVirtualMachineApi(resourceGroup.name()).stop(regionAndId.id()); } @Override http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/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 6a577eb..8ea823b 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 @@ -17,15 +17,7 @@ package org.jclouds.azurecompute.arm.compute.config; import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; -import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; @@ -53,6 +45,7 @@ import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware; import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata; import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded; +import org.jclouds.azurecompute.arm.compute.loaders.ResourceGroupForLocation; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes; import org.jclouds.azurecompute.arm.domain.Location; @@ -60,6 +53,7 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule; import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VirtualMachine; @@ -88,7 +82,6 @@ import com.google.common.base.Predicate; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.inject.Inject; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; @@ -125,8 +118,11 @@ public class AzureComputeServiceContextModule extends bind(TemplateOptions.class).to(AzureTemplateOptions.class); bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class); bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class); + bind(new TypeLiteral<CacheLoader<RegionAndIdAndIngressRules, String>>() { }).to(CreateSecurityGroupIfNeeded.class); + bind(new TypeLiteral<CacheLoader<String, ResourceGroup>>() { + }).to(ResourceGroupForLocation.class); bind(new TypeLiteral<ImageExtension>() { }).to(AzureComputeImageExtension.class); @@ -134,86 +130,16 @@ public class AzureComputeServiceContextModule extends }).to(AzureComputeSecurityGroupExtension.class); } + @Provides @Singleton - public static class AzureComputeConstants { - - @Named(OPERATION_TIMEOUT) - @Inject - private String operationTimeoutProperty; - - @Named(OPERATION_POLL_INITIAL_PERIOD) - @Inject - private String operationPollInitialPeriodProperty; - - @Named(OPERATION_POLL_MAX_PERIOD) - @Inject - private String operationPollMaxPeriodProperty; - - @Named(TCP_RULE_FORMAT) - @Inject - private String tcpRuleFormatProperty; - - @Named(TCP_RULE_REGEXP) - @Inject - private String tcpRuleRegexpProperty; - - @Named(IMAGE_PUBLISHERS) - @Inject - private String azureImagePublishersProperty; - - @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); - } - - public String azureImagePublishers() { - return azureImagePublishersProperty; - } - - public String azureDefaultVnetAddressPrefixProperty() { - return azureDefaultVnetAddressPrefixProperty; - } - - public String azureDefaultSubnetAddressPrefixProperty() { - return azureDefaultSubnetAddressPrefixProperty; - } - - public String azureDefaultDataDiskSizeProperty() { - return azureDefaultDataDiskSizeProperty; - } - - public Integer operationPollInitialPeriod() { - return Integer.parseInt(operationPollInitialPeriodProperty); - } - - public Integer operationPollMaxPeriod() { - return Integer.parseInt(operationPollMaxPeriodProperty); - } - - public String tcpRuleFormat() { - return tcpRuleFormatProperty; - } - - public String tcpRuleRegexp() { - return tcpRuleRegexpProperty; - } + protected final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap( + CacheLoader<RegionAndIdAndIngressRules, String> in) { + return CacheBuilder.newBuilder().build(in); } @Provides @Singleton - protected final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap( - CacheLoader<RegionAndIdAndIngressRules, String> in) { + protected final LoadingCache<String, ResourceGroup> resourceGroupMap(CacheLoader<String, ResourceGroup> in) { return CacheBuilder.newBuilder().build(in); } @@ -259,18 +185,24 @@ public class AzureComputeServiceContextModule extends @Provides protected PublicIpAvailablePredicateFactory providePublicIpAvailablePredicate(final AzureComputeApi api, - final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, final Timeouts timeouts, - final PollPeriod pollPeriod) { - return new PublicIpAvailablePredicateFactory(api, azureComputeConstants.operationTimeout(), - azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod()); + @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) { + return new PublicIpAvailablePredicateFactory(api, operationTimeout, pollPeriod.pollInitialPeriod, + pollPeriod.pollMaxPeriod); } @Provides protected SecurityGroupAvailablePredicateFactory provideSecurityGroupAvailablePredicate(final AzureComputeApi api, - final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, final Timeouts timeouts, - final PollPeriod pollPeriod) { - return new SecurityGroupAvailablePredicateFactory(api, azureComputeConstants.operationTimeout(), - azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod()); + @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) { + return new SecurityGroupAvailablePredicateFactory(api, operationTimeout, pollPeriod.pollInitialPeriod, + pollPeriod.pollMaxPeriod); + } + + @Provides + @Named("STORAGE") + protected Predicate<URI> provideStorageAccountAvailablePredicate(final AzureComputeApi api, + @Named(OPERATION_TIMEOUT) Integer operationTimeout, PollPeriod pollPeriod) { + return retry(new ActionDonePredicate(api), operationTimeout, pollPeriod.pollInitialPeriod, + pollPeriod.pollMaxPeriod); } @VisibleForTesting http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java index 1e57899..7028081 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeImageExtension.java @@ -32,13 +32,13 @@ import javax.annotation.Resource; import org.jclouds.Constants; import org.jclouds.azurecompute.arm.AzureComputeApi; 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.compute.strategy.CleanupResources; import org.jclouds.azurecompute.arm.domain.RegionAndId; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.VMImage; -import org.jclouds.azurecompute.arm.functions.CleanupResources; import org.jclouds.azurecompute.arm.util.BlobHelper; import org.jclouds.compute.domain.CloneImageTemplate; import org.jclouds.compute.domain.Image; @@ -49,6 +49,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import com.google.common.base.Predicate; +import com.google.common.cache.LoadingCache; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.Inject; @@ -68,7 +69,7 @@ public class AzureComputeImageExtension implements ImageExtension { private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate; private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage; private final CleanupResources cleanupResources; - private final LocationToResourceGroupName locationToResourceGroupName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject AzureComputeImageExtension(AzureComputeApi api, @@ -76,14 +77,14 @@ public class AzureComputeImageExtension implements ImageExtension { @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources, - LocationToResourceGroupName locationToResourceGroupName) { + LoadingCache<String, ResourceGroup> resourceGroupMap) { this.api = api; this.imageAvailablePredicate = imageAvailablePredicate; this.nodeSuspendedPredicate = nodeSuspendedPredicate; this.userExecutor = userExecutor; this.resourceDefinitionToImage = resourceDefinitionToImage; this.cleanupResources = cleanupResources; - this.locationToResourceGroupName = locationToResourceGroupName; + this.resourceGroupMap = resourceGroupMap; } @Override @@ -94,23 +95,25 @@ public class AzureComputeImageExtension implements ImageExtension { @Override public ListenableFuture<Image> createImage(ImageTemplate template) { final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; - + final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId()); - final String group = locationToResourceGroupName.apply(regionAndId.region()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + final String resourceGroupName = resourceGroup.name(); logger.debug(">> stopping node %s...", regionAndId.slashEncode()); - api.getVirtualMachineApi(group).stop(regionAndId.id()); - checkState(nodeSuspendedPredicate.create(group).apply(regionAndId.id()), + api.getVirtualMachineApi(resourceGroupName).stop(regionAndId.id()); + checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(regionAndId.id()), "Node %s was not suspended within the configured time limit", regionAndId.slashEncode()); return userExecutor.submit(new Callable<Image>() { @Override public Image call() throws Exception { logger.debug(">> generalizing virtal machine %s...", regionAndId.id()); - api.getVirtualMachineApi(group).generalize(regionAndId.id()); + api.getVirtualMachineApi(resourceGroupName).generalize(regionAndId.id()); 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); + URI uri = api.getVirtualMachineApi(resourceGroupName) + .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()); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java index 12d140b..340e51c 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/extensions/AzureComputeSecurityGroupExtension.java @@ -36,7 +36,6 @@ import javax.inject.Named; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory; -import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; @@ -47,6 +46,7 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol; import org.jclouds.azurecompute.arm.domain.RegionAndId; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi; @@ -65,6 +65,7 @@ import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; @@ -77,23 +78,23 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio private final AzureComputeApi api; private final Function<NetworkSecurityGroup, SecurityGroup> securityGroupConverter; - private final LocationToResourceGroupName locationToResourceGroupName; private final Supplier<Set<? extends Location>> locations; private final SecurityGroupAvailablePredicateFactory securityGroupAvailable; private final Predicate<URI> resourceDeleted; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject AzureComputeSecurityGroupExtension(AzureComputeApi api, @Memoized Supplier<Set<? extends Location>> locations, - LocationToResourceGroupName locationToResourceGroupName, Function<NetworkSecurityGroup, SecurityGroup> groupConverter, SecurityGroupAvailablePredicateFactory securityRuleAvailable, - @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted) { + @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted, + LoadingCache<String, ResourceGroup> resourceGroupMap) { this.api = api; this.locations = locations; this.securityGroupConverter = groupConverter; - this.locationToResourceGroupName = locationToResourceGroupName; this.securityGroupAvailable = securityRuleAvailable; this.resourceDeleted = resourceDeleted; + this.resourceGroupMap = resourceGroupMap; } @Override @@ -109,8 +110,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio @Override public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) { logger.debug(">> getting security groups for %s...", location); - final String resourcegroup = locationToResourceGroupName.apply(location.getId()); - List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourcegroup).list(); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId()); + List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup.name()).list(); return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter)); } @@ -119,19 +120,19 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio logger.debug(">> getting security groups for node %s...", nodeId); final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId); - final String resourceGroup = locationToResourceGroupName.apply(regionAndId.region()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); - VirtualMachine vm = api.getVirtualMachineApi(resourceGroup).get(regionAndId.id()); + VirtualMachine vm = api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id()); List<IdReference> networkInterfacesIdReferences = vm.properties().networkProfile().networkInterfaces(); List<NetworkSecurityGroup> networkGroups = new ArrayList<NetworkSecurityGroup>(); for (IdReference networkInterfaceCardIdReference : networkInterfacesIdReferences) { String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id())); - NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(resourceGroup).get(nicName); + NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(resourceGroup.name()).get(nicName); if (card != null && card.properties().networkSecurityGroup() != null) { String secGroupName = Iterables.getLast(Splitter.on("/").split( card.properties().networkSecurityGroup().id())); - NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(resourceGroup).get(secGroupName); + NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(secGroupName); networkGroups.add(group); } } @@ -143,14 +144,14 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio public SecurityGroup getSecurityGroupById(String id) { logger.debug(">> getting security group %s...", id); final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); - final String resourceGroup = locationToResourceGroupName.apply(regionAndId.region()); - - return securityGroupConverter.apply(api.getNetworkSecurityGroupApi(resourceGroup).get(regionAndId.id())); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(regionAndId.id()); + return securityGroup == null ? null : securityGroupConverter.apply(securityGroup); } @Override public SecurityGroup createSecurityGroup(String name, Location location) { - final String resourceGroup = locationToResourceGroupName.apply(location.getId()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId()); logger.debug(">> creating security group %s in %s...", name, location); @@ -158,7 +159,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio builder.name(name); builder.location(location); - return securityGroupConverter.apply(api.getNetworkSecurityGroupApi(resourceGroup).createOrUpdate(name, + return securityGroupConverter.apply(api.getNetworkSecurityGroupApi(resourceGroup.name()).createOrUpdate(name, location.getId(), null, NetworkSecurityGroupProperties.builder().build())); } @@ -167,8 +168,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio logger.debug(">> deleting security group %s...", id); final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); - final String resourcegroup = locationToResourceGroupName.apply(regionAndId.region()); - URI uri = api.getNetworkSecurityGroupApi(resourcegroup).delete(regionAndId.id()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + URI uri = api.getNetworkSecurityGroupApi(resourceGroup.name()).delete(regionAndId.id()); return resourceDeleted.apply(uri); } @@ -196,35 +197,35 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio // TODO: Support Azure network tags somehow? final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId()); - final String resourceGroup = locationToResourceGroupName.apply(regionAndId.region()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); - NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup); + NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name()); NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id()); if (networkSecurityGroup == null) { throw new IllegalArgumentException("Security group " + group.getName() + " was not found"); } - NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup, networkSecurityGroup.name()); - int nextPriority = getRuleStartingPriority(ruleApi); + NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup.name(), networkSecurityGroup.name()); + int nextPriority = getRuleStartingPriority(networkSecurityGroup); for (String ipRange : ipRanges) { NetworkSecurityRuleProperties properties = NetworkSecurityRuleProperties.builder() - .protocol(Protocol.fromValue(protocol.name())) // - .sourceAddressPrefix(ipRange) // - .sourcePortRange("*") // - .destinationAddressPrefix("*") // - .destinationPortRange(portRange) // - .direction(Direction.Inbound) // - .access(Access.Allow) // - .priority(nextPriority++) // + .protocol(Protocol.fromValue(protocol.name())) + .sourceAddressPrefix(ipRange) + .sourcePortRange("*") + .destinationAddressPrefix("*") + .destinationPortRange(portRange) + .direction(Direction.Inbound) + .access(Access.Allow) + .priority(nextPriority++) .build(); logger.debug(">> creating network security rule %s for %s...", ruleName, ipRange); ruleApi.createOrUpdate(ruleName, properties); - checkState(securityGroupAvailable.create(resourceGroup).apply(networkSecurityGroup.name()), + checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()), "Security group was not updated in the configured timeout"); } @@ -241,16 +242,16 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio logger.debug(">> deleting ip permissions matching [%s] from %s...", ruleName, group.getName()); final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId()); - final String resourceGroup = locationToResourceGroupName.apply(regionAndId.region()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); - NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup); + NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name()); NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id()); if (networkSecurityGroup == null) { throw new IllegalArgumentException("Security group " + group.getName() + " was not found"); } - NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup, networkSecurityGroup.name()); + NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup.name(), networkSecurityGroup.name()); Iterable<NetworkSecurityRule> rules = filter(ruleApi.list(), new Predicate<NetworkSecurityRule>() { @Override public boolean apply(NetworkSecurityRule input) { @@ -266,7 +267,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio for (NetworkSecurityRule matchingRule : rules) { logger.debug(">> deleting network security rule %s from %s...", matchingRule.name(), group.getName()); ruleApi.delete(matchingRule.name()); - checkState(securityGroupAvailable.create(resourceGroup).apply(networkSecurityGroup.name()), + checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()), "Security group was not updated in the configured timeout"); } @@ -298,8 +299,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio return false; } - private int getRuleStartingPriority(NetworkSecurityRuleApi ruleApi) { - List<NetworkSecurityRule> existingRules = ruleApi.list(); + private int getRuleStartingPriority(NetworkSecurityGroup securityGroup) { + List<NetworkSecurityRule> existingRules = securityGroup.properties().securityRules(); return existingRules.isEmpty() ? 100 : rulesByPriority().max(existingRules).properties().priority() + 1; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityRuleToIpPermission.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityRuleToIpPermission.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityRuleToIpPermission.java index e601d59..50a0954 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityRuleToIpPermission.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/NetworkSecurityRuleToIpPermission.java @@ -60,9 +60,9 @@ public class NetworkSecurityRuleToIpPermission implements Function<NetworkSecuri String portRange = rule.properties().destinationPortRange(); if (!"*".equals(portRange)) { - String[] range = portRange.split("-"); + String[] range = portRange.split("-"); // One single element if it is a single port permissions = PortSelection.class.cast(permissions).fromPort(Integer.parseInt(range[0])) - .to(Integer.parseInt(range[1])); + .to(Integer.parseInt(range[range.length - 1])); } if (!"*".equals(rule.properties().sourceAddressPrefix())) { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java index 02fb0f4..dbde188 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/ResourceDefinitionToCustomImage.java @@ -25,12 +25,14 @@ import javax.inject.Inject; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.domain.RegionAndId; import org.jclouds.azurecompute.arm.domain.ResourceDefinition; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName; import org.jclouds.compute.domain.Image; import com.google.common.base.Function; +import com.google.common.cache.LoadingCache; import com.google.inject.assistedinject.Assisted; public class ResourceDefinitionToCustomImage implements Function<ResourceDefinition, Image> { @@ -41,30 +43,35 @@ public class ResourceDefinitionToCustomImage implements Function<ResourceDefinit private final Function<VMImage, Image> vmImageToImage; private final String imageName; - private final String storageAccountName; - private final VirtualMachine vm; - private final String resourceGroup; + private final String nodeId; + private final AzureComputeApi api; + private final StorageProfileToStorageAccountName storageProfileToStorageAccountName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject ResourceDefinitionToCustomImage(AzureComputeApi api, StorageProfileToStorageAccountName storageProfileToStorageAccountName, - Function<VMImage, Image> vmImageToImage, LocationToResourceGroupName locationToResourceGroupName, - @Assisted("nodeId") String nodeId, - @Assisted("imageName") String imageName) { + Function<VMImage, Image> vmImageToImage, LoadingCache<String, ResourceGroup> resourceGroupMap, + @Assisted("nodeId") String nodeId, @Assisted("imageName") String imageName) { + this.api = api; this.vmImageToImage = vmImageToImage; + this.nodeId = nodeId; this.imageName = imageName; - - 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()); + this.storageProfileToStorageAccountName = storageProfileToStorageAccountName; + this.resourceGroupMap = resourceGroupMap; } @SuppressWarnings("unchecked") @Override public Image apply(ResourceDefinition input) { - VMImage.Builder builder = VMImage.customImage().group(resourceGroup).storage(storageAccountName).name(imageName) - .offer(CUSTOM_IMAGE_OFFER).location(vm.location()); + RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + + VirtualMachine vm = api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id()); + String storageAccountName = storageProfileToStorageAccountName.apply(vm.properties().storageProfile()); + + VMImage.Builder builder = VMImage.customImage().group(resourceGroup.name()).storage(storageAccountName) + .name(imageName).offer(CUSTOM_IMAGE_OFFER).location(vm.location()); Map<String, String> properties = (Map<String, String>) input.properties(); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java index 22c818c..92689c2 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/functions/VirtualMachineToNodeMetadata.java @@ -17,6 +17,7 @@ package org.jclouds.azurecompute.arm.compute.functions; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.nullToEmpty; import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.tryFind; @@ -25,6 +26,7 @@ import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageE import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId; import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue; +import static org.jclouds.location.predicates.LocationPredicates.idEquals; import static org.jclouds.util.Closeables2.closeQuietly; import java.util.List; @@ -36,11 +38,11 @@ import javax.inject.Inject; import javax.inject.Named; import org.jclouds.azurecompute.arm.AzureComputeApi; -import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; 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.ResourceGroup; import org.jclouds.azurecompute.arm.domain.StorageProfile; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.VMImage; @@ -71,6 +73,7 @@ import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -120,15 +123,14 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No private final Map<String, Credentials> credentialStore; private final Function<VMImage, Image> vmImageToImge; private final StorageProfileToStorageAccountName storageProfileToStorageAccountName; - private final LocationToResourceGroupName locationToResourceGroupName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention, Supplier<Map<String, ? extends Image>> images, Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Location>> locations, Map<String, Credentials> credentialStore, - final AzureComputeConstants azureComputeConstants, Function<VMImage, Image> vmImageToImge, - StorageProfileToStorageAccountName storageProfileToStorageAccountName, - LocationToResourceGroupName locationToResourceGroupName) { + Function<VMImage, Image> vmImageToImge, StorageProfileToStorageAccountName storageProfileToStorageAccountName, + LoadingCache<String, ResourceGroup> resourceGroupMap) { this.api = api; this.nodeNamingConvention = namingConvention.createWithoutPrefix(); this.images = checkNotNull(images, "images cannot be null"); @@ -137,13 +139,13 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No this.credentialStore = credentialStore; this.vmImageToImge = vmImageToImge; this.storageProfileToStorageAccountName = storageProfileToStorageAccountName; - this.locationToResourceGroupName = locationToResourceGroupName; + this.resourceGroupMap = resourceGroupMap; } @Override public NodeMetadata apply(VirtualMachine virtualMachine) { - String azureGroup = locationToResourceGroupName.apply(virtualMachine.location()); - + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location()); + NodeMetadataBuilder builder = new NodeMetadataBuilder(); builder.id(RegionAndId.fromRegionAndId(virtualMachine.location(), virtualMachine.name()).slashEncode()); builder.providerId(virtualMachine.id()); @@ -154,7 +156,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No if (ProvisioningState.SUCCEEDED.equals(provisioningState)) { // If the provisioning succeeded, we need to query the *real* status of // the VM - VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(azureGroup).getInstanceDetails( + VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup.name()).getInstanceDetails( virtualMachine.name()); if (instanceDetails != null && instanceDetails.powerState() != null) { builder.status(POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState())); @@ -185,15 +187,18 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No addMetadataAndParseTagsFromCommaDelimitedValue(builder, virtualMachine.tags()); groupFromMetadata = virtualMachine.tags().get(GROUP_KEY); } - - // Try to read the group from the virtual machine tags, and parse the name if missing + + // Try to read the group from the virtual machine tags, and parse the name + // if missing builder.group(groupFromMetadata != null ? groupFromMetadata : nodeNamingConvention.extractGroup(virtualMachine .name())); - + String locationName = virtualMachine.location(); builder.location(getLocation(locations, locationName)); - Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName, azureGroup); + Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName, + resourceGroup.name()); + if (image.isPresent()) { builder.imageId(image.get().getId()); builder.operatingSystem(image.get().getOperatingSystem()); @@ -252,15 +257,11 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No } protected static Location getLocation(Supplier<Set<? extends Location>> locations, final String locationName) { - return find(locations.get(), new Predicate<Location>() { - @Override - public boolean apply(Location location) { - return locationName != null && locationName.equals(location.getId()); - } - }, null); + return find(locations.get(), idEquals(nullToEmpty(locationName)), null); } - protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName, String azureGroup) { + protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName, + String azureGroup) { if (storageProfile.imageReference() != null) { return Optional.fromNullable(images.get().get( encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference()))); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java index efb8abc..0ff96d8 100644 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/CreateSecurityGroupIfNeeded.java @@ -29,7 +29,6 @@ import javax.inject.Singleton; import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules; -import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule; @@ -37,10 +36,12 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; @Singleton public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndIdAndIngressRules, String> { @@ -49,18 +50,18 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndIdAndIngre protected Logger logger = Logger.NULL; private final AzureComputeApi api; - private final LocationToResourceGroupName locationToResourceGroupName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; @Inject - CreateSecurityGroupIfNeeded(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) { + CreateSecurityGroupIfNeeded(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) { this.api = api; - this.locationToResourceGroupName = locationToResourceGroupName; + this.resourceGroupMap = resourceGroupMap; } @Override public String load(RegionAndIdAndIngressRules key) throws Exception { - String resourceGroup = locationToResourceGroupName.apply(key.region()); - return createSecurityGroup(key.region(), resourceGroup, key.id(), key.inboundPorts()); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(key.region()); + return createSecurityGroup(key.region(), resourceGroup.name(), key.id(), key.inboundPorts()); } private String createSecurityGroup(String location, String resourceGroup, String name, int[] inboundPorts) { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java new file mode 100644 index 0000000..ddbbb26 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/loaders/ResourceGroupForLocation.java @@ -0,0 +1,62 @@ +/* + * 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.loaders; + +import java.util.Map; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.compute.functions.LocationToResourceGroupName; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.azurecompute.arm.features.ResourceGroupApi; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; + +import com.google.common.cache.CacheLoader; +import com.google.common.collect.ImmutableMap; + +@Singleton +public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final ResourceGroupApi api; + private final LocationToResourceGroupName locationToResourceGroupName; + + @Inject + ResourceGroupForLocation(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) { + this.api = api.getResourceGroupApi(); + this.locationToResourceGroupName = locationToResourceGroupName; + } + + @Override + public ResourceGroup load(String locationId) throws Exception { + String azureGroupName = locationToResourceGroupName.apply(locationId); + ResourceGroup resourceGroup = api.get(azureGroupName); + if (resourceGroup == null) { + logger.debug(">> creating resource group %s", azureGroupName); + final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs"); + resourceGroup = api.create(azureGroupName, locationId, tags); + } + return resourceGroup; + } +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/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 index c71a7da..ecbc237 100644 --- 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 @@ -27,57 +27,11 @@ import static com.google.common.base.Objects.equal; */ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { - - private String customData; - private String virtualNetworkAddressPrefix; - private String subnetAddressPrefix; - private String DNSLabelPrefix; - private String keyVaultIdAndSecret; private String virtualNetworkName; private String subnetId; private String blob; /** - * Custom options for the Azure ARM API - */ - public AzureTemplateOptions customData(String customData) { - this.customData = customData; - return this; - } - - /** - * 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; - } - - /** * Sets the virtual network name */ public AzureTemplateOptions virtualNetworkName(String virtualNetworkName) { @@ -101,11 +55,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { 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; } public String getBlob() { return blob; } @@ -123,11 +72,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { 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); eTo.blob(blob); @@ -136,7 +80,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { @Override public int hashCode() { - return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId, blob); + return Objects.hashCode(super.hashCode(), virtualNetworkName, subnetId, blob); } @Override @@ -152,11 +96,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { } 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) && equal(this.blob, other.blob); @@ -165,11 +104,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { @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); toString.add("blob", blob); @@ -179,46 +113,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable { 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) { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java deleted file mode 100644 index 66590e1..0000000 --- a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/predicates/IsDeploymentInRegions.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jclouds.azurecompute.arm.compute.predicates; - -import java.util.Set; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import org.jclouds.azurecompute.arm.domain.Deployment; -import org.jclouds.azurecompute.arm.domain.Value; -import org.jclouds.location.Region; - -import com.google.common.base.Predicate; -import com.google.common.base.Supplier; - -@Singleton -public class IsDeploymentInRegions implements Predicate<Deployment> { - - private final Supplier<Set<String>> regionIds; - - @Inject - IsDeploymentInRegions(@Region Supplier<Set<String>> regionIds) { - this.regionIds = regionIds; - } - - @Override - public boolean apply(Deployment deployment) { - if (deployment.properties() == null || deployment.properties().parameters() == null || deployment.properties().parameters().get("location") == null) return false; - Value locationValue = deployment.properties().parameters().get("location"); - return regionIds.get().contains(locationValue.value()); - } -} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/fde928eb/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java ---------------------------------------------------------------------- diff --git a/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java new file mode 100644 index 0000000..3914bc0 --- /dev/null +++ b/azurecompute-arm/src/main/java/org/jclouds/azurecompute/arm/compute/strategy/CleanupResources.java @@ -0,0 +1,205 @@ +/* + * 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 static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.transform; +import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; +import static org.jclouds.util.Closeables2.closeQuietly; + +import java.net.URI; +import java.util.List; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.azurecompute.arm.AzureComputeApi; +import org.jclouds.azurecompute.arm.domain.IdReference; +import org.jclouds.azurecompute.arm.domain.IpConfiguration; +import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; +import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; +import org.jclouds.azurecompute.arm.domain.RegionAndId; +import org.jclouds.azurecompute.arm.domain.ResourceGroup; +import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; +import org.jclouds.azurecompute.arm.domain.VirtualMachine; +import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; +import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName; +import org.jclouds.azurecompute.arm.util.BlobHelper; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.compute.reference.ComputeServiceConstants; +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.cache.LoadingCache; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +@Singleton +public class CleanupResources { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final AzureComputeApi api; + private final Predicate<URI> resourceDeleted; + private final StorageProfileToStorageAccountName storageProfileToStorageAccountName; + private final LoadingCache<String, ResourceGroup> resourceGroupMap; + private final GroupNamingConvention.Factory namingConvention; + + @Inject + CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted, + StorageProfileToStorageAccountName storageProfileToStorageAccountName, + LoadingCache<String, ResourceGroup> resourceGroupMap, GroupNamingConvention.Factory namingConvention) { + this.api = azureComputeApi; + this.resourceDeleted = resourceDeleted; + this.storageProfileToStorageAccountName = storageProfileToStorageAccountName; + this.resourceGroupMap = resourceGroupMap; + this.namingConvention = namingConvention; + } + + public boolean cleanupNode(final String id) { + RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); + ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); + String resourceGroupName = resourceGroup.name(); + + VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id()); + if (virtualMachine == null) { + return true; + } + + logger.debug(">> destroying %s ...", regionAndId.slashEncode()); + boolean vmDeleted = deleteVirtualMachine(resourceGroupName, virtualMachine); + + // We don't delete the network here, as it is global to the resource + // group. It will be deleted when the resource group is deleted + + cleanupVirtualMachineNICs(resourceGroupName, virtualMachine); + cleanupVirtualMachineStorage(resourceGroupName, virtualMachine); + + return vmDeleted; + } + + public void cleanupVirtualMachineNICs(String group, VirtualMachine virtualMachine) { + for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) { + NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName); + Iterable<String> publicIps = getPublicIps(group, nic); + + logger.debug(">> destroying nic %s...", nicName); + URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName); + resourceDeleted.apply(nicDeletionURI); + + for (String publicIp : publicIps) { + logger.debug(">> deleting public ip nic %s...", publicIp); + api.getPublicIPAddressApi(group).delete(publicIp); + } + } + } + + public void cleanupVirtualMachineStorage(String group, VirtualMachine virtualMachine) { + String storageAccountName = storageProfileToStorageAccountName + .apply(virtualMachine.properties().storageProfile()); + StorageServiceKeys keys = api.getStorageAccountApi(group).getKeys(storageAccountName); + + // Remove the virtual machine files + logger.debug(">> deleting virtual machine disk storage..."); + BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1()); + try { + blobHelper.deleteContainerIfExists("vhds"); + + if (!blobHelper.customImageExists()) { + logger.debug(">> deleting storage account %s...", storageAccountName); + api.getStorageAccountApi(group).delete(storageAccountName); + } else { + logger.debug(">> the storage account contains custom images. Will not delete it!"); + } + } finally { + closeQuietly(blobHelper); + } + } + + public boolean cleanupSecurityGroupIfOrphaned(String resourceGroup, String group) { + String name = namingConvention.create().sharedNameForGroup(group); + NetworkSecurityGroupApi sgapi = api.getNetworkSecurityGroupApi(resourceGroup); + + boolean deleted = false; + + try { + NetworkSecurityGroup securityGroup = sgapi.get(name); + if (securityGroup != null) { + List<NetworkInterfaceCard> nics = securityGroup.properties().networkInterfaces(); + if (nics == null || nics.isEmpty()) { + logger.debug(">> deleting orphaned security group %s from %s...", name, resourceGroup); + try { + deleted = resourceDeleted.apply(sgapi.delete(name)); + } catch (Exception ex) { + logger.warn(ex, ">> error deleting orphaned security group %s from %s...", name, resourceGroup); + } + } + } + } catch (Exception ex) { + logger.warn(ex, "Error deleting security groups for %s and group %s", resourceGroup, group); + } + + return deleted; + } + + public boolean deleteResourceGroupIfEmpty(String group) { + boolean deleted = false; + if (api.getVirtualMachineApi(group).list().isEmpty() && api.getStorageAccountApi(group).list().isEmpty() + && api.getNetworkInterfaceCardApi(group).list().isEmpty() + && api.getPublicIPAddressApi(group).list().isEmpty() + && api.getNetworkSecurityGroupApi(group).list().isEmpty()) { + logger.debug(">> the resource group %s is empty. Deleting...", group); + deleted = resourceDeleted.apply(api.getResourceGroupApi().delete(group)); + } + return deleted; + } + + private Iterable<String> getPublicIps(String group, NetworkInterfaceCard nic) { + return transform( + filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() { + @Override + public IdReference apply(IpConfiguration input) { + return input.properties().publicIPAddress(); + } + }), notNull()), new Function<IdReference, String>() { + @Override + public String apply(IdReference input) { + return Iterables.getLast(Splitter.on("/").split(input.id())); + } + }); + } + + private List<String> getNetworkCardInterfaceNames(VirtualMachine virtualMachine) { + List<String> nics = Lists.newArrayList(); + for (IdReference idReference : virtualMachine.properties().networkProfile().networkInterfaces()) { + nics.add(Iterables.getLast(Splitter.on("/").split(idReference.id()))); + } + return nics; + } + + private boolean deleteVirtualMachine(String group, VirtualMachine virtualMachine) { + return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name())); + } + +}
