JCLOUDS-1273/JCLOUDS-1226: Support multiple resource groups in ARM

This commit is contained in:
Ignasi Barrera 2017-04-24 14:49:57 +02:00
parent cc13cfeda1
commit 83c0a3c7b2
35 changed files with 577 additions and 488 deletions

View File

@ -17,15 +17,16 @@
package org.jclouds.azurecompute.arm; package org.jclouds.azurecompute.arm;
import java.io.Closeable; import java.io.Closeable;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.azurecompute.arm.features.AvailabilitySetApi; import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
import org.jclouds.azurecompute.arm.features.DeploymentApi; import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.features.DiskApi;
import org.jclouds.azurecompute.arm.features.ImageApi; import org.jclouds.azurecompute.arm.features.ImageApi;
import org.jclouds.azurecompute.arm.features.JobApi; import org.jclouds.azurecompute.arm.features.JobApi;
import org.jclouds.azurecompute.arm.features.LoadBalancerApi; import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
import org.jclouds.azurecompute.arm.features.LocationApi; import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.DiskApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi; import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi; import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
@ -47,7 +48,7 @@ import org.jclouds.rest.annotations.Delegate;
* @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790568.aspx" >doc</a> * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790568.aspx" >doc</a>
*/ */
public interface AzureComputeApi extends Closeable { public interface AzureComputeApi extends Closeable {
/** /**
* The Azure Resource Manager API includes operations for managing resource groups in your subscription. * The Azure Resource Manager API includes operations for managing resource groups in your subscription.
* *
@ -56,6 +57,9 @@ public interface AzureComputeApi extends Closeable {
@Delegate @Delegate
ResourceGroupApi getResourceGroupApi(); ResourceGroupApi getResourceGroupApi();
/**
* Provides access to the Job tracking API.
*/
@Delegate @Delegate
JobApi getJobApi(); JobApi getJobApi();

View File

@ -31,8 +31,8 @@ import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources; import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode; import org.jclouds.compute.callables.RunScriptOnNode;
@ -62,7 +62,6 @@ import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
@ -70,7 +69,6 @@ import com.google.common.util.concurrent.ListeningExecutorService;
@Singleton @Singleton
public class AzureComputeService extends BaseComputeService { public class AzureComputeService extends BaseComputeService {
private final CleanupResources cleanupResources; private final CleanupResources cleanupResources;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject @Inject
protected AzureComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, protected AzureComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@ -89,14 +87,13 @@ public class AzureComputeService extends BaseComputeService {
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts, PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CleanupResources cleanupResources, Optional<ImageExtension> imageExtension, CleanupResources cleanupResources, Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension, LoadingCache<String, ResourceGroup> resourceGroupMap) { Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy, super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension); persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
this.cleanupResources = cleanupResources; this.cleanupResources = cleanupResources;
this.resourceGroupMap = resourceGroupMap;
} }
@Override @Override
@ -105,11 +102,11 @@ public class AzureComputeService extends BaseComputeService {
ImmutableSet.Builder<String> resourceGroups = ImmutableSet.builder(); ImmutableSet.Builder<String> resourceGroups = ImmutableSet.builder();
for (NodeMetadata deadNode : deadNodes) { for (NodeMetadata deadNode : deadNodes) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(deadNode.getLocation().getId()); String resourceGroupName = ResourceGroupAndName.fromSlashEncoded(deadNode.getId()).resourceGroup();
resourceGroups.add(resourceGroupName);
resourceGroups.add(resourceGroup.name());
if (deadNode.getGroup() != null) { if (deadNode.getGroup() != null) {
regionGroups.put(resourceGroup.name(), deadNode.getGroup()); regionGroups.put(resourceGroupName, deadNode.getGroup());
} }
try { try {

View File

@ -19,10 +19,12 @@ package org.jclouds.azurecompute.arm.compute;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.builder; import static com.google.common.collect.ImmutableList.builder;
import static com.google.common.collect.ImmutableList.of; import static com.google.common.collect.ImmutableList.of;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromSlashEncoded;
import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.getMarketplacePlanFromImageMetadata;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
@ -40,6 +42,7 @@ import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage; import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources; import org.jclouds.azurecompute.arm.compute.strategy.CleanupResources;
@ -62,7 +65,6 @@ import org.jclouds.azurecompute.arm.domain.Offer;
import org.jclouds.azurecompute.arm.domain.Plan; import org.jclouds.azurecompute.arm.domain.Plan;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties; 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.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.domain.SKU; import org.jclouds.azurecompute.arm.domain.SKU;
@ -90,7 +92,6 @@ import com.google.common.base.Objects;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -115,20 +116,18 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
private final List<String> imagePublishers; private final List<String> imagePublishers;
private final Supplier<Set<String>> regionIds; private final Supplier<Set<String>> regionIds;
private final PublicIpAvailablePredicateFactory publicIpAvailable; private final PublicIpAvailablePredicateFactory publicIpAvailable;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final CustomImageToVMImage customImagetoVmImage; private final CustomImageToVMImage customImagetoVmImage;
@Inject @Inject
AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers, AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds, CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap, PublicIpAvailablePredicateFactory publicIpAvailable,
CustomImageToVMImage customImagetoVmImage) { CustomImageToVMImage customImagetoVmImage) {
this.api = api; this.api = api;
this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers); this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
this.cleanupResources = cleanupResources; this.cleanupResources = cleanupResources;
this.regionIds = regionIds; this.regionIds = regionIds;
this.publicIpAvailable = publicIpAvailable; this.publicIpAvailable = publicIpAvailable;
this.resourceGroupMap = resourceGroupMap;
this.customImagetoVmImage = customImagetoVmImage; this.customImagetoVmImage = customImagetoVmImage;
} }
@ -138,15 +137,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
String locationName = template.getLocation().getId(); String locationName = template.getLocation().getId();
Image image = template.getImage(); Image image = template.getImage();
String hardwareId = template.getHardware().getId(); String hardwareId = fromSlashEncoded(template.getHardware().getId()).name();
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(locationName);
// TODO ARM specific options // TODO ARM specific options
AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class); AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
String subnetId = templateOptions.getSubnetId(); String subnetId = templateOptions.getSubnetId();
String resourceGroupName = templateOptions.getResourceGroup();
IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet()); IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet());
StorageProfile storageProfile = createStorageProfile(image, templateOptions.getDataDisks()); StorageProfile storageProfile = createStorageProfile(image, templateOptions.getDataDisks());
NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroup.name(), template.getOptions()); NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName, resourceGroupName, template.getOptions());
HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(hardwareId).build(); HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(hardwareId).build();
OSProfile osProfile = createOsProfile(name, template); OSProfile osProfile = createOsProfile(name, template);
NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(of(IdReference.create(nic.id()))).build(); NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(of(IdReference.create(nic.id()))).build();
@ -165,14 +164,14 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(template.getOptions()); Map<String, String> metadataAndTags = metadataAndTagsAsCommaDelimitedValue(template.getOptions());
Plan plan = getMarketplacePlanFromImageMetadata(template.getImage()); Plan plan = getMarketplacePlanFromImageMetadata(template.getImage());
VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroup.name()).createOrUpdate(name, template.getLocation().getId(), VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).createOrUpdate(name, template.getLocation().getId(),
virtualMachineProperties, metadataAndTags, plan); virtualMachineProperties, metadataAndTags, plan);
// Safe to pass null credentials here, as jclouds will default populate // 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 node with the default credentials from the image, or the ones in
// the options, if provided. // the options, if provided.
RegionAndId regionAndId = RegionAndId.fromRegionAndId(locationName, name); ResourceGroupAndName resourceGroupAndName = fromResourceGroupAndName(resourceGroupName, name);
return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, regionAndId.slashEncode(), null); return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, resourceGroupAndName.slashEncode(), null);
} }
@Override @Override
@ -183,8 +182,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
for (VMSize vmSize : vmSizes) { for (VMSize vmSize : vmSizes) {
VMHardware hwProfile = VMHardware VMHardware hwProfile = VMHardware
.create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(), .create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(),
vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name(), vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name());
false);
hwProfiles.add(hwProfile); hwProfiles.add(hwProfile);
} }
} }
@ -221,9 +219,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
return osImages; return osImages;
} }
private List<VMImage> listCustomImagesByLocation(String location) { private List<VMImage> listCustomImagesByResourceGroup(String resourceGroup) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location); List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup).list();
List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup.name()).list();
return Lists.transform(customImages, customImagetoVmImage); return Lists.transform(customImages, customImagetoVmImage);
} }
@ -231,16 +228,29 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
public Iterable<VMImage> listImages() { public Iterable<VMImage> listImages() {
final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder(); final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder();
Iterable<String> availableLocationNames = transform(listLocations(), new Function<Location, String>() { final List<String> availableLocationNames = newArrayList(transform(listLocations(),
@Override new Function<Location, String>() {
public String apply(Location location) { @Override
return location.name(); public String apply(Location location) {
} return location.name();
}); }
}));
for (String locationName : availableLocationNames) { for (String locationName : availableLocationNames) {
osImages.addAll(listImagesByLocation(locationName)); osImages.addAll(listImagesByLocation(locationName));
osImages.addAll(listCustomImagesByLocation(locationName)); }
// We need to look for custom images in all resource groups
Iterable<ResourceGroup> resourceGroupsInLocation = filter(api.getResourceGroupApi().list(),
new Predicate<ResourceGroup>() {
@Override
public boolean apply(ResourceGroup input) {
return availableLocationNames.contains(input.location());
}
});
for (ResourceGroup resourceGroup : resourceGroupsInLocation) {
osImages.addAll(listCustomImagesByResourceGroup(resourceGroup.name()));
} }
return osImages.build(); return osImages.build();
@ -249,10 +259,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override @Override
public VMImage getImage(final String id) { public VMImage getImage(final String id) {
VMImage image = decodeFieldsFromUniqueId(id); VMImage image = decodeFieldsFromUniqueId(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
if (image.custom()) { if (image.custom()) {
org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(resourceGroup.name()).get(image.name()); org.jclouds.azurecompute.arm.domain.Image vmImage = api.getVirtualMachineImageApi(image.resourceGroup()).get(
image.name());
return vmImage == null ? null : customImagetoVmImage.apply(vmImage); return vmImage == null ? null : customImagetoVmImage.apply(vmImage);
} }
@ -304,9 +314,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override @Override
public VirtualMachine getNode(final String id) { public VirtualMachine getNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); return api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(resourceGroupAndName.name());
return api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
} }
@Override @Override
@ -316,23 +325,20 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override @Override
public void rebootNode(final String id) { public void rebootNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).restart(resourceGroupAndName.name());
api.getVirtualMachineApi(resourceGroup.name()).restart(regionAndId.id());
} }
@Override @Override
public void resumeNode(final String id) { public void resumeNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).start(resourceGroupAndName.name());
api.getVirtualMachineApi(resourceGroup.name()).start(regionAndId.id());
} }
@Override @Override
public void suspendNode(final String id) { public void suspendNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).stop(resourceGroupAndName.name());
api.getVirtualMachineApi(resourceGroup.name()).stop(regionAndId.id());
} }
@Override @Override
@ -346,10 +352,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override @Override
public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) { public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<VirtualMachine>() { return transform(ids, new Function<String, VirtualMachine>() {
@Override @Override
public boolean apply(VirtualMachine virtualMachine) { public VirtualMachine apply(String input) {
return contains(ids, virtualMachine.id()); return getNode(input);
} }
}); });
} }

View File

@ -34,7 +34,7 @@ import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.AzureComputeService; import org.jclouds.azurecompute.arm.compute.AzureComputeService;
import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter; import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules; import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension; import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeSecurityGroupExtension; import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeSecurityGroupExtension;
import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation; import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
@ -44,9 +44,9 @@ import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata; import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata;
import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded; import org.jclouds.azurecompute.arm.compute.loaders.CreateSecurityGroupIfNeeded;
import org.jclouds.azurecompute.arm.compute.loaders.ResourceGroupForLocation; import org.jclouds.azurecompute.arm.compute.loaders.DefaultResourceGroup;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes; import org.jclouds.azurecompute.arm.compute.strategy.CreateResourcesThenCreateNodes;
import org.jclouds.azurecompute.arm.domain.Image; import org.jclouds.azurecompute.arm.domain.Image;
import org.jclouds.azurecompute.arm.domain.Location; import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
@ -116,12 +116,12 @@ public class AzureComputeServiceContextModule extends
bind(TemplateOptions.class).to(AzureTemplateOptions.class); bind(TemplateOptions.class).to(AzureTemplateOptions.class);
bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class); bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class); bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourcesThenCreateNodes.class);
bind(new TypeLiteral<CacheLoader<RegionAndIdAndIngressRules, String>>() { bind(new TypeLiteral<CacheLoader<ResourceGroupAndNameAndIngressRules, String>>() {
}).to(CreateSecurityGroupIfNeeded.class); }).to(CreateSecurityGroupIfNeeded.class);
bind(new TypeLiteral<CacheLoader<String, ResourceGroup>>() { bind(new TypeLiteral<CacheLoader<String, ResourceGroup>>() {
}).to(ResourceGroupForLocation.class); }).to(DefaultResourceGroup.class);
bind(new TypeLiteral<ImageExtension>() { bind(new TypeLiteral<ImageExtension>() {
}).to(AzureComputeImageExtension.class); }).to(AzureComputeImageExtension.class);
@ -131,14 +131,14 @@ public class AzureComputeServiceContextModule extends
@Provides @Provides
@Singleton @Singleton
protected final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap( protected final LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap(
CacheLoader<RegionAndIdAndIngressRules, String> in) { CacheLoader<ResourceGroupAndNameAndIngressRules, String> in) {
return CacheBuilder.newBuilder().build(in); return CacheBuilder.newBuilder().build(in);
} }
@Provides @Provides
@Singleton @Singleton
protected final LoadingCache<String, ResourceGroup> resourceGroupMap(CacheLoader<String, ResourceGroup> in) { protected final LoadingCache<String, ResourceGroup> defaultResourceGroup(CacheLoader<String, ResourceGroup> in) {
return CacheBuilder.newBuilder().build(in); return CacheBuilder.newBuilder().build(in);
} }

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.compute.domain;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -24,27 +24,27 @@ import com.google.common.base.Splitter;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@AutoValue @AutoValue
public abstract class RegionAndId { public abstract class LocationAndName {
public abstract String region(); public abstract String location();
public abstract String id(); public abstract String name();
protected RegionAndId() { protected LocationAndName() {
} }
public static RegionAndId fromSlashEncoded(String id) { public static LocationAndName fromSlashEncoded(String id) {
Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id")); Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
checkArgument(Iterables.size(parts) == 2, "id must be in format regionId/id"); checkArgument(Iterables.size(parts) == 2, "id must be in format location/name");
return new AutoValue_RegionAndId(Iterables.get(parts, 0), Iterables.get(parts, 1)); return new AutoValue_LocationAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
} }
public static RegionAndId fromRegionAndId(String region, String id) { public static LocationAndName fromLocationAndName(String location, String name) {
return new AutoValue_RegionAndId(region, id); return new AutoValue_LocationAndName(location, name);
} }
public String slashEncode() { public String slashEncode() {
return region() + "/" + id(); return location() + "/" + name();
} }
} }

View File

@ -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.compute.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 ResourceGroupAndName {
public abstract String resourceGroup();
public abstract String name();
protected ResourceGroupAndName() {
}
public static ResourceGroupAndName fromSlashEncoded(String id) {
Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
checkArgument(Iterables.size(parts) == 2, "id must be in format resourcegroup/name");
return new AutoValue_ResourceGroupAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
}
public static ResourceGroupAndName fromResourceGroupAndName(String resourceGroup, String name) {
return new AutoValue_ResourceGroupAndName(resourceGroup, name);
}
public String slashEncode() {
return resourceGroup() + "/" + name();
}
}

View File

@ -16,31 +16,36 @@
*/ */
package org.jclouds.azurecompute.arm.compute.domain; package org.jclouds.azurecompute.arm.compute.domain;
import org.jclouds.azurecompute.arm.domain.RegionAndId; import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import com.google.common.base.Objects; import com.google.common.base.Objects;
@AutoValue @AutoValue
public abstract class RegionAndIdAndIngressRules { public abstract class ResourceGroupAndNameAndIngressRules {
abstract ResourceGroupAndName resourceGroupAndName(); // Intentionally hidden
public abstract String location();
abstract RegionAndId regionAndId(); // Intentionally hidden
public abstract int[] inboundPorts(); public abstract int[] inboundPorts();
RegionAndIdAndIngressRules() { ResourceGroupAndNameAndIngressRules() {
} }
public static RegionAndIdAndIngressRules create(String region, String id, int[] inboundPorts) { public static ResourceGroupAndNameAndIngressRules create(String resourceGroup, String location, String name,
return new AutoValue_RegionAndIdAndIngressRules(RegionAndId.fromRegionAndId(region, id), inboundPorts); int[] inboundPorts) {
return new AutoValue_ResourceGroupAndNameAndIngressRules(fromResourceGroupAndName(resourceGroup, name), location,
inboundPorts);
} }
public String id() { public String name() {
return regionAndId().id(); return resourceGroupAndName().name();
} }
public String region() { public String resourceGroup() {
return regionAndId().region(); return resourceGroupAndName().resourceGroup();
} }
// Intentionally delegate equals and hashcode to the fields in the parent // Intentionally delegate equals and hashcode to the fields in the parent
@ -48,7 +53,7 @@ public abstract class RegionAndIdAndIngressRules {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(region(), id()); return Objects.hashCode(resourceGroup(), name());
} }
@Override @Override
@ -56,11 +61,11 @@ public abstract class RegionAndIdAndIngressRules {
if (obj == this) { if (obj == this) {
return true; return true;
} }
if (!(obj instanceof RegionAndId)) { if (!(obj instanceof ResourceGroupAndName)) {
return false; return false;
} }
RegionAndId that = (RegionAndId) obj; ResourceGroupAndName that = (ResourceGroupAndName) obj;
return Objects.equal(region(), that.region()) && Objects.equal(id(), that.id()); return Objects.equal(resourceGroup(), that.resourceGroup()) && Objects.equal(name(), that.name());
} }
} }

View File

@ -19,6 +19,7 @@ package org.jclouds.azurecompute.arm.compute.extensions;
import static com.google.common.base.Functions.compose; import static com.google.common.base.Functions.compose;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromSlashEncoded;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
@ -32,11 +33,10 @@ import org.jclouds.Constants;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.VirtualMachineInStatePredicateFactory;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage; import org.jclouds.azurecompute.arm.compute.functions.CustomImageToVMImage;
import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageProperties; import org.jclouds.azurecompute.arm.domain.ImageProperties;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.compute.domain.CloneImageTemplate; import org.jclouds.compute.domain.CloneImageTemplate;
@ -49,7 +49,6 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; 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.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -66,25 +65,21 @@ public class AzureComputeImageExtension implements ImageExtension {
private final ListeningExecutorService userExecutor; private final ListeningExecutorService userExecutor;
private final ImageAvailablePredicateFactory imageAvailablePredicate; private final ImageAvailablePredicateFactory imageAvailablePredicate;
private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate; private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final Function<VMImage, Image> vmImageToImage; private final Function<VMImage, Image> vmImageToImage;
private final Predicate<URI> resourceDeleted; private final Predicate<URI> resourceDeleted;
private final CustomImageToVMImage customImagetoVmImage; private final CustomImageToVMImage customImagetoVmImage;
@Inject @Inject
AzureComputeImageExtension(AzureComputeApi api, AzureComputeImageExtension(AzureComputeApi api, ImageAvailablePredicateFactory imageAvailablePredicate,
ImageAvailablePredicateFactory imageAvailablePredicate,
@Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate, @Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Function<VMImage, Image> vmImageToImage, LoadingCache<String, ResourceGroup> resourceGroupMap, Function<VMImage, Image> vmImageToImage, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
CustomImageToVMImage customImagetoVmImage) { CustomImageToVMImage customImagetoVmImage) {
this.api = api; this.api = api;
this.imageAvailablePredicate = imageAvailablePredicate; this.imageAvailablePredicate = imageAvailablePredicate;
this.nodeSuspendedPredicate = nodeSuspendedPredicate; this.nodeSuspendedPredicate = nodeSuspendedPredicate;
this.userExecutor = userExecutor; this.userExecutor = userExecutor;
this.vmImageToImage = vmImageToImage; this.vmImageToImage = vmImageToImage;
this.resourceGroupMap = resourceGroupMap;
this.resourceDeleted = resourceDeleted; this.resourceDeleted = resourceDeleted;
this.customImagetoVmImage = customImagetoVmImage; this.customImagetoVmImage = customImagetoVmImage;
} }
@ -97,27 +92,27 @@ public class AzureComputeImageExtension implements ImageExtension {
@Override @Override
public ListenableFuture<Image> createImage(ImageTemplate template) { public ListenableFuture<Image> createImage(ImageTemplate template) {
final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId()); final ResourceGroupAndName resourceGroupAndName = fromSlashEncoded(cloneTemplate.getSourceNodeId());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); final String resourceGroupName = resourceGroupAndName.resourceGroup();
final String resourceGroupName = resourceGroup.name(); final String vmName = resourceGroupAndName.name();
final VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id()); final VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(vmName);
final IdReference vmIdRef = IdReference.create(vm.id()); final IdReference vmIdRef = IdReference.create(vm.id());
logger.debug(">> stopping node %s...", regionAndId.slashEncode()); logger.debug(">> stopping node %s...", cloneTemplate.getSourceNodeId());
api.getVirtualMachineApi(resourceGroupName).stop(regionAndId.id()); api.getVirtualMachineApi(resourceGroupName).stop(vmName);
checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(regionAndId.id()), checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(vmName),
"Node %s was not suspended within the configured time limit", regionAndId.slashEncode()); "Node %s was not suspended within the configured time limit", cloneTemplate.getSourceNodeId());
return userExecutor.submit(new Callable<Image>() { return userExecutor.submit(new Callable<Image>() {
@Override @Override
public Image call() throws Exception { public Image call() throws Exception {
logger.debug(">> generalizing virtal machine %s...", regionAndId.id()); logger.debug(">> generalizing virtal machine %s...", vmName);
api.getVirtualMachineApi(resourceGroupName).generalize(regionAndId.id()); api.getVirtualMachineApi(resourceGroupName).generalize(vmName);
org.jclouds.azurecompute.arm.domain.Image imageFromVM = api.getVirtualMachineImageApi(resourceGroupName) org.jclouds.azurecompute.arm.domain.Image imageFromVM = api.getVirtualMachineImageApi(resourceGroupName)
.createOrUpdate(cloneTemplate.getName(), regionAndId.region(), .createOrUpdate(cloneTemplate.getName(), vm.location(),
ImageProperties.builder().sourceVirtualMachine(vmIdRef).build()); ImageProperties.builder().sourceVirtualMachine(vmIdRef).build());
checkState(imageAvailablePredicate.create(resourceGroupName).apply(imageFromVM.name()), checkState(imageAvailablePredicate.create(resourceGroupName).apply(imageFromVM.name()),
@ -134,9 +129,7 @@ public class AzureComputeImageExtension implements ImageExtension {
checkArgument(image.custom(), "Only custom images can be deleted"); checkArgument(image.custom(), "Only custom images can be deleted");
logger.debug(">> deleting image %s", id); logger.debug(">> deleting image %s", id);
URI uri = api.getVirtualMachineImageApi(image.resourceGroup()).delete(image.name());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
URI uri = api.getVirtualMachineImageApi(resourceGroup.name()).delete(image.name());
return resourceDeleted.apply(uri); return resourceDeleted.apply(uri);
} }
} }

View File

@ -20,10 +20,10 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.equalTo; import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.notNull; import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.predicates.NodePredicates.locationId;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
@ -36,6 +36,7 @@ import javax.inject.Named;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
@ -45,12 +46,10 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol; 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.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi; import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup; import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder; import org.jclouds.compute.domain.SecurityGroupBuilder;
import org.jclouds.compute.extensions.SecurityGroupExtension; import org.jclouds.compute.extensions.SecurityGroupExtension;
@ -63,11 +62,8 @@ import org.jclouds.net.domain.IpProtocol;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.base.Predicate; 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.cache.LoadingCache;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
@ -78,64 +74,67 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
private final AzureComputeApi api; private final AzureComputeApi api;
private final Function<NetworkSecurityGroup, SecurityGroup> securityGroupConverter; private final Function<NetworkSecurityGroup, SecurityGroup> securityGroupConverter;
private final Supplier<Set<? extends Location>> locations;
private final SecurityGroupAvailablePredicateFactory securityGroupAvailable; private final SecurityGroupAvailablePredicateFactory securityGroupAvailable;
private final Predicate<URI> resourceDeleted; private final Predicate<URI> resourceDeleted;
private final LoadingCache<String, ResourceGroup> resourceGroupMap; private final LoadingCache<String, ResourceGroup> defaultResourceGroup;
@Inject @Inject
AzureComputeSecurityGroupExtension(AzureComputeApi api, @Memoized Supplier<Set<? extends Location>> locations, AzureComputeSecurityGroupExtension(AzureComputeApi api,
Function<NetworkSecurityGroup, SecurityGroup> groupConverter, Function<NetworkSecurityGroup, SecurityGroup> groupConverter,
SecurityGroupAvailablePredicateFactory securityRuleAvailable, SecurityGroupAvailablePredicateFactory securityRuleAvailable,
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
LoadingCache<String, ResourceGroup> resourceGroupMap) { LoadingCache<String, ResourceGroup> defaultResourceGroup) {
this.api = api; this.api = api;
this.locations = locations;
this.securityGroupConverter = groupConverter; this.securityGroupConverter = groupConverter;
this.securityGroupAvailable = securityRuleAvailable; this.securityGroupAvailable = securityRuleAvailable;
this.resourceDeleted = resourceDeleted; this.resourceDeleted = resourceDeleted;
this.resourceGroupMap = resourceGroupMap; this.defaultResourceGroup = defaultResourceGroup;
} }
@Override @Override
public Set<SecurityGroup> listSecurityGroups() { public Set<SecurityGroup> listSecurityGroups() {
return ImmutableSet.copyOf(concat(transform(locations.get(), new Function<Location, Set<SecurityGroup>>() { ImmutableSet.Builder<SecurityGroup> securityGroups = ImmutableSet.builder();
@Override for (ResourceGroup rg : api.getResourceGroupApi().list()) {
public Set<SecurityGroup> apply(Location input) { securityGroups.addAll(securityGroupsInResourceGroup(rg.name()));
return listSecurityGroupsInLocation(input); }
} return securityGroups.build();
}))); }
private Set<SecurityGroup> securityGroupsInResourceGroup(String resourceGroup) {
List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup).list();
return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter));
} }
@Override @Override
public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) { public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) {
logger.debug(">> getting security groups for %s...", location); // Even though the resource groups are in a location, each security group
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId()); // can be in a different resource group, so we need to inspect all teh
List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup.name()).list(); // existing resource groups, and filter afterwards
return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter)); return ImmutableSet.copyOf(filter(listSecurityGroups(), locationId(location.getId())));
} }
@Override @Override
public Set<SecurityGroup> listSecurityGroupsForNode(String nodeId) { public Set<SecurityGroup> listSecurityGroupsForNode(String nodeId) {
logger.debug(">> getting security groups for node %s...", nodeId); logger.debug(">> getting security groups for node %s...", nodeId);
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId); final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(nodeId);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
VirtualMachine vm = api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id()); VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
resourceGroupAndName.name());
if (vm == null) { if (vm == null) {
throw new IllegalArgumentException("Node " + regionAndId.id() + " was not found"); throw new IllegalArgumentException("Node " + nodeId + " was not found");
} }
List<IdReference> networkInterfacesIdReferences = vm.properties().networkProfile().networkInterfaces(); List<IdReference> networkInterfacesIdReferences = vm.properties().networkProfile().networkInterfaces();
List<NetworkSecurityGroup> networkGroups = new ArrayList<NetworkSecurityGroup>(); List<NetworkSecurityGroup> networkGroups = new ArrayList<NetworkSecurityGroup>();
for (IdReference networkInterfaceCardIdReference : networkInterfacesIdReferences) { for (IdReference networkInterfaceCardIdReference : networkInterfacesIdReferences) {
String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id())); String nicName = networkInterfaceCardIdReference.name();
NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(resourceGroup.name()).get(nicName); String nicResourceGroup = networkInterfaceCardIdReference.resourceGroup();
NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(nicResourceGroup).get(nicName);
if (card != null && card.properties().networkSecurityGroup() != null) { if (card != null && card.properties().networkSecurityGroup() != null) {
String secGroupName = Iterables.getLast(Splitter.on("/").split( String secGroupName = card.properties().networkSecurityGroup().name();
card.properties().networkSecurityGroup().id())); String sgResourceGroup = card.properties().networkSecurityGroup().resourceGroup();
NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(secGroupName); NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(sgResourceGroup).get(secGroupName);
networkGroups.add(group); networkGroups.add(group);
} }
} }
@ -146,15 +145,15 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
@Override @Override
public SecurityGroup getSecurityGroupById(String id) { public SecurityGroup getSecurityGroupById(String id) {
logger.debug(">> getting security group %s...", id); logger.debug(">> getting security group %s...", id);
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup()).get(
NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(regionAndId.id()); resourceGroupAndName.name());
return securityGroup == null ? null : securityGroupConverter.apply(securityGroup); return securityGroup == null ? null : securityGroupConverter.apply(securityGroup);
} }
@Override @Override
public SecurityGroup createSecurityGroup(String name, Location location) { public SecurityGroup createSecurityGroup(String name, Location location) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId()); ResourceGroup resourceGroup = defaultResourceGroup.getUnchecked(location.getId());
logger.debug(">> creating security group %s in %s...", name, location); logger.debug(">> creating security group %s in %s...", name, location);
@ -170,9 +169,9 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
public boolean removeSecurityGroup(String id) { public boolean removeSecurityGroup(String id) {
logger.debug(">> deleting security group %s...", id); logger.debug(">> deleting security group %s...", id);
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); URI uri = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup())
URI uri = api.getNetworkSecurityGroupApi(resourceGroup.name()).delete(regionAndId.id()); .delete(resourceGroupAndName.name());
return resourceDeleted.apply(uri); return resourceDeleted.apply(uri);
} }
@ -199,17 +198,16 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
// TODO: Support Azure network tags somehow? // TODO: Support Azure network tags somehow?
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId()); final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(group.getId());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name()); NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup());
NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id()); NetworkSecurityGroup networkSecurityGroup = groupApi.get(resourceGroupAndName.name());
if (networkSecurityGroup == null) { if (networkSecurityGroup == null) {
throw new IllegalArgumentException("Security group " + group.getName() + " was not found"); throw new IllegalArgumentException("Security group " + group.getName() + " was not found");
} }
NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup.name(), networkSecurityGroup.name()); NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroupAndName.resourceGroup(), networkSecurityGroup.name());
int nextPriority = getRuleStartingPriority(networkSecurityGroup); int nextPriority = getRuleStartingPriority(networkSecurityGroup);
for (String ipRange : ipRanges) { for (String ipRange : ipRanges) {
@ -228,7 +226,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
ruleApi.createOrUpdate(ruleName, properties); ruleApi.createOrUpdate(ruleName, properties);
checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()), checkState(
securityGroupAvailable.create(resourceGroupAndName.resourceGroup()).apply(networkSecurityGroup.name()),
"Security group was not updated in the configured timeout"); "Security group was not updated in the configured timeout");
} }
@ -244,17 +243,17 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
logger.debug(">> deleting ip permissions matching [%s] from %s...", ruleName, group.getName()); logger.debug(">> deleting ip permissions matching [%s] from %s...", ruleName, group.getName());
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId()); final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(group.getId());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name()); NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup());
NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id()); NetworkSecurityGroup networkSecurityGroup = groupApi.get(resourceGroupAndName.name());
if (networkSecurityGroup == null) { if (networkSecurityGroup == null) {
throw new IllegalArgumentException("Security group " + group.getName() + " was not found"); throw new IllegalArgumentException("Security group " + group.getName() + " was not found");
} }
NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroup.name(), networkSecurityGroup.name()); NetworkSecurityRuleApi ruleApi = api.getNetworkSecurityRuleApi(resourceGroupAndName.resourceGroup(),
networkSecurityGroup.name());
Iterable<NetworkSecurityRule> rules = filter(ruleApi.list(), new Predicate<NetworkSecurityRule>() { Iterable<NetworkSecurityRule> rules = filter(ruleApi.list(), new Predicate<NetworkSecurityRule>() {
@Override @Override
public boolean apply(NetworkSecurityRule input) { public boolean apply(NetworkSecurityRule input) {
@ -270,7 +269,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
for (NetworkSecurityRule matchingRule : rules) { for (NetworkSecurityRule matchingRule : rules) {
logger.debug(">> deleting network security rule %s from %s...", matchingRule.name(), group.getName()); logger.debug(">> deleting network security rule %s from %s...", matchingRule.name(), group.getName());
ruleApi.delete(matchingRule.name()); ruleApi.delete(matchingRule.name());
checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()), checkState(
securityGroupAvailable.create(resourceGroupAndName.resourceGroup()).apply(networkSecurityGroup.name()),
"Security group was not updated in the configured timeout"); "Security group was not updated in the configured timeout");
} }

View File

@ -16,6 +16,8 @@
*/ */
package org.jclouds.azurecompute.arm.compute.functions; package org.jclouds.azurecompute.arm.compute.functions;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import org.jclouds.azurecompute.arm.domain.Image; import org.jclouds.azurecompute.arm.domain.Image;
import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMImage;
@ -25,7 +27,7 @@ public class CustomImageToVMImage implements Function<Image, VMImage> {
@Override @Override
public VMImage apply(Image input) { public VMImage apply(Image input) {
return VMImage.customImage().customImageId(input.id()).location(input.location()).name(input.name()) return VMImage.customImage().resourceGroup(extractResourceGroup(input.id())).customImageId(input.id()).location(input.location()).name(input.name())
.offer(input.properties().storageProfile().osDisk().osType()).build(); .offer(input.properties().storageProfile().osDisk().osType()).build();
} }
} }

View File

@ -18,8 +18,10 @@ package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
import static org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityRuleToIpPermission.InboundRule; import static org.jclouds.azurecompute.arm.compute.functions.NetworkSecurityRuleToIpPermission.InboundRule;
import static org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata.getLocation; import static org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToNodeMetadata.getLocation;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import java.util.Set; import java.util.Set;
@ -27,7 +29,6 @@ import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup; import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder; import org.jclouds.compute.domain.SecurityGroupBuilder;
@ -54,8 +55,8 @@ public class NetworkSecurityGroupToSecurityGroup implements Function<NetworkSecu
public SecurityGroup apply(NetworkSecurityGroup input) { public SecurityGroup apply(NetworkSecurityGroup input) {
SecurityGroupBuilder builder = new SecurityGroupBuilder(); SecurityGroupBuilder builder = new SecurityGroupBuilder();
builder.id(RegionAndId.fromRegionAndId(input.location(), input.name()).slashEncode()); builder.id(fromResourceGroupAndName(extractResourceGroup(input.id()), input.name()).slashEncode());
builder.providerId(input.properties().resourceGuid()); builder.providerId(input.id());
builder.name(input.name()); builder.name(input.name());
builder.location(getLocation(locations, input.location())); builder.location(getLocation(locations, input.location()));

View File

@ -29,14 +29,12 @@ import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet; import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.cache.LoadingCache;
@Singleton @Singleton
public class TemplateToAvailabilitySet implements Function<Template, AvailabilitySet> { public class TemplateToAvailabilitySet implements Function<Template, AvailabilitySet> {
@ -46,12 +44,10 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final AzureComputeApi api; private final AzureComputeApi api;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject @Inject
TemplateToAvailabilitySet(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) { TemplateToAvailabilitySet(AzureComputeApi api) {
this.api = api; this.api = api;
this.resourceGroupMap = resourceGroupMap;
} }
@Nullable @Nullable
@ -62,7 +58,7 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
AvailabilitySet availabilitySet = null; AvailabilitySet availabilitySet = null;
String location = input.getLocation().getId(); String location = input.getLocation().getId();
String resourceGroup = resourceGroupMap.getUnchecked(location).name(); String resourceGroup = options.getResourceGroup();
if (options.getAvailabilitySetName() != null) { if (options.getAvailabilitySetName() != null) {
availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(options.getAvailabilitySetName()); availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(options.getAvailabilitySetName());

View File

@ -16,9 +16,10 @@
*/ */
package org.jclouds.azurecompute.arm.compute.functions; package org.jclouds.azurecompute.arm.compute.functions;
import com.google.common.base.Supplier; import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromLocationAndName;
import com.google.common.collect.FluentIterable;
import com.google.inject.Inject; import java.util.Set;
import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
@ -26,14 +27,15 @@ import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.VolumeBuilder; import org.jclouds.compute.domain.VolumeBuilder;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.predicates.LocationPredicates; import org.jclouds.location.predicates.LocationPredicates;
import java.util.Set; import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
public class VMHardwareToHardware implements Function<VMHardware, Hardware> { public class VMHardwareToHardware implements Function<VMHardware, Hardware> {
@ -49,10 +51,10 @@ public class VMHardwareToHardware implements Function<VMHardware, Hardware> {
final HardwareBuilder builder = new HardwareBuilder() final HardwareBuilder builder = new HardwareBuilder()
.name(from.name()) .name(from.name())
.providerId(from.name()) .providerId(from.name())
.id(from.name()) .id(fromLocationAndName(from.location(), from.name()).slashEncode())
.processors(ImmutableList.of(new Processor(from.numberOfCores(), 2))) .processors(ImmutableList.of(new Processor(from.numberOfCores(), 2)))
.ram(from.memoryInMB()) .ram(from.memoryInMB())
.location(from.globallyAvailable() ? null : FluentIterable.from(locations.get()) .location(FluentIterable.from(locations.get())
.firstMatch(LocationPredicates.idEquals(from.location())) .firstMatch(LocationPredicates.idEquals(from.location()))
.get()); .get());

View File

@ -16,6 +16,12 @@
*/ */
package org.jclouds.azurecompute.arm.compute.functions; package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.tryFind;
import static java.util.Arrays.asList;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -40,11 +46,6 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject; import com.google.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.tryFind;
import static java.util.Arrays.asList;
import static org.jclouds.azurecompute.arm.util.VMImages.isCustom;
public class VMImageToImage implements Function<VMImage, Image> { public class VMImageToImage implements Function<VMImage, Image> {
private static final Map<String, OsFamily> OTHER_OS_MAP = ImmutableMap.<String, OsFamily> builder() private static final Map<String, OsFamily> OTHER_OS_MAP = ImmutableMap.<String, OsFamily> builder()
@ -64,8 +65,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
public static String encodeFieldsToUniqueIdCustom(boolean globallyAvailable, String locationName, public static String encodeFieldsToUniqueIdCustom(boolean globallyAvailable, String locationName,
ImageReference imageReference) { ImageReference imageReference) {
return (globallyAvailable ? "global" : locationName) + "/" + imageReference.customImageId() return extractResourceGroup(imageReference.customImageId()) + "/" + (globallyAvailable ? "global" : locationName)
.substring(imageReference.customImageId().lastIndexOf("/") + 1); + "/" + imageReference.customImageId().substring(imageReference.customImageId().lastIndexOf("/") + 1);
} }
public static String encodeFieldsToUniqueId(VMImage imageReference) { public static String encodeFieldsToUniqueId(VMImage imageReference) {
@ -74,7 +75,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
} }
public static String encodeFieldsToUniqueIdCustom(VMImage imageReference) { public static String encodeFieldsToUniqueIdCustom(VMImage imageReference) {
return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.name(); return imageReference.resourceGroup() + "/"
+ (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.name();
} }
public static VMImage decodeFieldsFromUniqueId(final String id) { public static VMImage decodeFieldsFromUniqueId(final String id) {
@ -82,10 +84,11 @@ public class VMImageToImage implements Function<VMImage, Image> {
String[] fields = checkNotNull(id, "id").split("/"); String[] fields = checkNotNull(id, "id").split("/");
if (isCustom(id)) { if (isCustom(id)) {
/* id fields indexes /* id fields indexes
0: imageReference.location + "/" + 0: imageReference.resourceGroup
1: imageReference.name 1: imageReference.location + "/" +
2: imageReference.name
*/ */
vmImage = VMImage.customImage().location(fields[0]).name(fields[1]).build(); vmImage = VMImage.customImage().resourceGroup(fields[0]).location(fields[1]).name(fields[2]).build();
} else { } else {
/* id fields indexes /* id fields indexes
0: imageReference.location + "/" + 0: imageReference.location + "/" +

View File

@ -20,8 +20,11 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.nullToEmpty; import static com.google.common.base.Strings.nullToEmpty;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY; import static org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter.GROUP_KEY;
import static org.jclouds.azurecompute.arm.compute.domain.LocationAndName.fromLocationAndName;
import static org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName.fromResourceGroupAndName;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue; import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
import static org.jclouds.location.predicates.LocationPredicates.idEquals; import static org.jclouds.location.predicates.LocationPredicates.idEquals;
@ -34,13 +37,12 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.domain.LocationAndName;
import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.StatusAndBackendStatus; import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.StatusAndBackendStatus;
import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration; import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
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.StorageProfile;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
@ -58,10 +60,7 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> { public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
@ -74,20 +73,18 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
private final GroupNamingConvention nodeNamingConvention; private final GroupNamingConvention nodeNamingConvention;
private final Supplier<Set<? extends Location>> locations; private final Supplier<Set<? extends Location>> locations;
private final Supplier<Map<String, ? extends Hardware>> hardwares; private final Supplier<Map<String, ? extends Hardware>> hardwares;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final ImageCacheSupplier imageCache; private final ImageCacheSupplier imageCache;
private final VirtualMachineToStatus virtualMachineToStatus; private final VirtualMachineToStatus virtualMachineToStatus;
@Inject @Inject
VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention, VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Location>> locations, Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Location>> locations,
Map<String, Credentials> credentialStore, LoadingCache<String, ResourceGroup> resourceGroupMap, Map<String, Credentials> credentialStore, @Memoized Supplier<Set<? extends Image>> imageCache,
@Memoized Supplier<Set<? extends Image>> imageCache, VirtualMachineToStatus virtualMachineToStatus) { VirtualMachineToStatus virtualMachineToStatus) {
this.api = api; this.api = api;
this.nodeNamingConvention = namingConvention.createWithoutPrefix(); this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.locations = locations; this.locations = locations;
this.hardwares = hardwares; this.hardwares = hardwares;
this.resourceGroupMap = resourceGroupMap;
this.virtualMachineToStatus = virtualMachineToStatus; this.virtualMachineToStatus = virtualMachineToStatus;
checkArgument(imageCache instanceof ImageCacheSupplier, checkArgument(imageCache instanceof ImageCacheSupplier,
"This provider needs an instance of the ImageCacheSupplier"); "This provider needs an instance of the ImageCacheSupplier");
@ -96,10 +93,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
@Override @Override
public NodeMetadata apply(VirtualMachine virtualMachine) { public NodeMetadata apply(VirtualMachine virtualMachine) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location());
NodeMetadataBuilder builder = new NodeMetadataBuilder(); NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.id(RegionAndId.fromRegionAndId(virtualMachine.location(), virtualMachine.name()).slashEncode()); builder.id(fromResourceGroupAndName(extractResourceGroup(virtualMachine.id()), virtualMachine.name())
.slashEncode());
builder.providerId(virtualMachine.id()); builder.providerId(virtualMachine.id());
builder.name(virtualMachine.name()); builder.name(virtualMachine.name());
builder.hostname(virtualMachine.name()); builder.hostname(virtualMachine.name());
@ -125,8 +121,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
String locationName = virtualMachine.location(); String locationName = virtualMachine.location();
builder.location(getLocation(locations, locationName)); builder.location(getLocation(locations, locationName));
Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName, Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName);
resourceGroup.name());
if (image.isPresent()) { if (image.isPresent()) {
builder.imageId(image.get().getId()); builder.imageId(image.get().getId());
@ -137,7 +132,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
virtualMachine.id(), virtualMachine.id()); virtualMachine.id(), virtualMachine.id());
} }
builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize())); builder.hardware(getHardware(fromLocationAndName(virtualMachine.location(), virtualMachine.properties()
.hardwareProfile().vmSize())));
return builder.build(); return builder.build();
} }
@ -158,12 +154,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
return privateIpAddresses; return privateIpAddresses;
} }
private NetworkInterfaceCard getNetworkInterfaceCard(IdReference networkInterfaceCardIdReference) { private NetworkInterfaceCard getNetworkInterfaceCard(IdReference nic) {
Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2); return api.getNetworkInterfaceCardApi(nic.resourceGroup()).get(nic.name());
String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id()));
return api.getNetworkInterfaceCardApi(resourceGroup).get(nicName);
} }
private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) { private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
@ -172,11 +164,11 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference); NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
if (networkInterfaceCard != null && networkInterfaceCard.properties() != null if (networkInterfaceCard != null && networkInterfaceCard.properties() != null
&& networkInterfaceCard.properties().ipConfigurations() != null) { && networkInterfaceCard.properties().ipConfigurations() != null) {
String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4); String resourceGroup = networkInterfaceCardIdReference.resourceGroup();
for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) { for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
if (ipConfiguration.properties().publicIPAddress() != null) { if (ipConfiguration.properties().publicIPAddress() != null) {
String publicIpId = ipConfiguration.properties().publicIPAddress().id(); IdReference publicIpId = ipConfiguration.properties().publicIPAddress();
PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(Iterables.getLast(Splitter.on("/").split(publicIpId))); PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(publicIpId.name());
if (publicIp != null && publicIp.properties().ipAddress() != null) { if (publicIp != null && publicIp.properties().ipAddress() != null) {
publicIpAddresses.add(publicIp.properties().ipAddress()); publicIpAddresses.add(publicIp.properties().ipAddress());
} }
@ -191,8 +183,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
return find(locations.get(), idEquals(nullToEmpty(locationName)), null); return find(locations.get(), idEquals(nullToEmpty(locationName)), null);
} }
protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName, protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
String azureGroup) {
if (storageProfile.imageReference() != null) { if (storageProfile.imageReference() != null) {
// FIXME check this condition // FIXME check this condition
String imageId = storageProfile.imageReference().customImageId() != null ? String imageId = storageProfile.imageReference().customImageId() != null ?
@ -205,11 +196,12 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
} }
} }
protected Hardware getHardware(final String vmSize) { protected Hardware getHardware(final LocationAndName hardwareId) {
return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() { final String slashEncoded = hardwareId.slashEncode();
return find(hardwares.get().values(), new Predicate<Hardware>() {
@Override @Override
public boolean apply(Hardware input) { public boolean apply(Hardware input) {
return input.getId().equals(vmSize); return input.getId().equals(slashEncoded);
} }
}); });
} }

View File

@ -17,13 +17,13 @@
package org.jclouds.azurecompute.arm.compute.functions; package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.StatusAndBackendStatus; import org.jclouds.azurecompute.arm.compute.functions.VirtualMachineToStatus.StatusAndBackendStatus;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.Status; import org.jclouds.azurecompute.arm.domain.Status;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
@ -36,7 +36,6 @@ import com.google.auto.value.AutoValue;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Functions; import com.google.common.base.Functions;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@Singleton @Singleton
@ -80,17 +79,15 @@ public class VirtualMachineToStatus implements Function<VirtualMachine, StatusAn
NodeMetadata.Status.UNRECOGNIZED); NodeMetadata.Status.UNRECOGNIZED);
private final AzureComputeApi api; private final AzureComputeApi api;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject @Inject
VirtualMachineToStatus(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) { VirtualMachineToStatus(AzureComputeApi api) {
this.api = api; this.api = api;
this.resourceGroupMap = resourceGroupMap;
} }
@Override @Override
public StatusAndBackendStatus apply(VirtualMachine virtualMachine) { public StatusAndBackendStatus apply(VirtualMachine virtualMachine) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location()); String resourceGroup = extractResourceGroup(virtualMachine.id());
ProvisioningState provisioningState = virtualMachine.properties().provisioningState(); ProvisioningState provisioningState = virtualMachine.properties().provisioningState();
NodeMetadata.Status status = PROVISIONINGSTATE_TO_NODESTATUS.apply(provisioningState); NodeMetadata.Status status = PROVISIONINGSTATE_TO_NODESTATUS.apply(provisioningState);
@ -99,7 +96,7 @@ public class VirtualMachineToStatus implements Function<VirtualMachine, StatusAn
if (ProvisioningState.SUCCEEDED.equals(provisioningState)) { if (ProvisioningState.SUCCEEDED.equals(provisioningState)) {
// If the provisioning succeeded, we need to query the *real* status of // If the provisioning succeeded, we need to query the *real* status of
// the VM // the VM
VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup.name()).getInstanceDetails( VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup).getInstanceDetails(
virtualMachine.name()); virtualMachine.name());
if (instanceDetails != null && instanceDetails.powerState() != null) { if (instanceDetails != null && instanceDetails.powerState() != null) {
status = POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState()); status = POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState());

View File

@ -28,7 +28,7 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules; import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties; import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
@ -36,32 +36,27 @@ import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Access;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Direction;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@Singleton @Singleton
public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndIdAndIngressRules, String> { public class CreateSecurityGroupIfNeeded extends CacheLoader<ResourceGroupAndNameAndIngressRules, String> {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final AzureComputeApi api; private final AzureComputeApi api;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject @Inject
CreateSecurityGroupIfNeeded(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) { CreateSecurityGroupIfNeeded(AzureComputeApi api) {
this.api = api; this.api = api;
this.resourceGroupMap = resourceGroupMap;
} }
@Override @Override
public String load(RegionAndIdAndIngressRules key) throws Exception { public String load(ResourceGroupAndNameAndIngressRules key) throws Exception {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(key.region()); return createSecurityGroup(key.location(), key.resourceGroup(), key.name(), key.inboundPorts());
return createSecurityGroup(key.region(), resourceGroup.name(), key.id(), key.inboundPorts());
} }
private String createSecurityGroup(String location, String resourceGroup, String name, int[] inboundPorts) { private String createSecurityGroup(String location, String resourceGroup, String name, int[] inboundPorts) {

View File

@ -34,7 +34,7 @@ import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@Singleton @Singleton
public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup> { public class DefaultResourceGroup extends CacheLoader<String, ResourceGroup> {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -43,7 +43,7 @@ public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup>
private final LocationToResourceGroupName locationToResourceGroupName; private final LocationToResourceGroupName locationToResourceGroupName;
@Inject @Inject
ResourceGroupForLocation(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) { DefaultResourceGroup(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) {
this.api = api.getResourceGroupApi(); this.api = api.getResourceGroupApi();
this.locationToResourceGroupName = locationToResourceGroupName; this.locationToResourceGroupName = locationToResourceGroupName;
} }
@ -54,7 +54,7 @@ public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup>
ResourceGroup resourceGroup = api.get(azureGroupName); ResourceGroup resourceGroup = api.get(azureGroupName);
if (resourceGroup == null) { if (resourceGroup == null) {
logger.debug(">> creating resource group %s", azureGroupName); logger.debug(">> creating resource group %s", azureGroupName);
final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs"); final Map<String, String> tags = ImmutableMap.of("description", "jclouds default resource group");
resourceGroup = api.create(azureGroupName, locationId, tags); resourceGroup = api.create(azureGroupName, locationId, tags);
} }
return resourceGroup; return resourceGroup;

View File

@ -34,10 +34,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
private String virtualNetworkName; private String virtualNetworkName;
private String subnetId; private String subnetId;
private String blob;
private AvailabilitySet availabilitySet; private AvailabilitySet availabilitySet;
private String availabilitySetName; private String availabilitySetName;
private List<DataDisk> dataDisks = ImmutableList.of(); private List<DataDisk> dataDisks = ImmutableList.of();
private String resourceGroup;
/** /**
* Sets the virtual network name * Sets the virtual network name
@ -54,14 +54,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
this.subnetId = subnetId; this.subnetId = subnetId;
return this; return this;
} }
/**
* Sets the blob name
*/
public AzureTemplateOptions blob(String blob) {
this.blob = blob;
return this;
}
/** /**
* Sets the availability set where the nodes will be configured. If it does * Sets the availability set where the nodes will be configured. If it does
@ -80,6 +72,14 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
this.availabilitySetName = availabilitySetName; this.availabilitySetName = availabilitySetName;
return this; return this;
} }
/**
* The resource group where the new resources will be created.
*/
public AzureTemplateOptions resourceGroup(String resourceGroup) {
this.resourceGroup = resourceGroup;
return this;
}
public AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) { public AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
for (DataDisk dataDisk : checkNotNull(dataDisks, "dataDisks")) for (DataDisk dataDisk : checkNotNull(dataDisks, "dataDisks"))
@ -94,12 +94,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
public String getVirtualNetworkName() { return virtualNetworkName; } public String getVirtualNetworkName() { return virtualNetworkName; }
public String getSubnetId() { return subnetId; } public String getSubnetId() { return subnetId; }
public String getBlob() { return blob; }
public AvailabilitySet getAvailabilitySet() { return availabilitySet; } public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
public String getAvailabilitySetName() { return availabilitySetName; } public String getAvailabilitySetName() { return availabilitySetName; }
public List<DataDisk> getDataDisks() { public List<DataDisk> getDataDisks() { return dataDisks; }
return dataDisks; public String getResourceGroup() { return resourceGroup; }
}
@Override @Override
public AzureTemplateOptions clone() { public AzureTemplateOptions clone() {
@ -115,10 +113,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to); AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to);
eTo.virtualNetworkName(virtualNetworkName); eTo.virtualNetworkName(virtualNetworkName);
eTo.subnetId(subnetId); eTo.subnetId(subnetId);
eTo.blob(blob);
eTo.availabilitySet(availabilitySet); eTo.availabilitySet(availabilitySet);
eTo.availabilitySet(availabilitySetName); eTo.availabilitySet(availabilitySetName);
eTo.dataDisks(dataDisks); eTo.dataDisks(dataDisks);
eTo.resourceGroup(resourceGroup);
} }
} }
@ -129,28 +127,19 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
if (!super.equals(o)) return false; if (!super.equals(o)) return false;
AzureTemplateOptions that = (AzureTemplateOptions) o; AzureTemplateOptions that = (AzureTemplateOptions) o;
if (virtualNetworkName != null ? !virtualNetworkName.equals(that.virtualNetworkName) : that.virtualNetworkName != null) return Objects.equal(virtualNetworkName, that.virtualNetworkName) &&
return false; Objects.equal(subnetId, that.subnetId) &&
if (subnetId != null ? !subnetId.equals(that.subnetId) : that.subnetId != null) return false; Objects.equal(availabilitySet, that.availabilitySet) &&
if (blob != null ? !blob.equals(that.blob) : that.blob != null) return false; Objects.equal(availabilitySetName, that.availabilitySetName) &&
if (availabilitySet != null ? !availabilitySet.equals(that.availabilitySet) : that.availabilitySet != null) Objects.equal(dataDisks, that.dataDisks) &&
return false; Objects.equal(resourceGroup, that.resourceGroup);
if (availabilitySetName != null ? !availabilitySetName.equals(that.availabilitySetName) : that.availabilitySetName != null)
return false;
return dataDisks != null ? dataDisks.equals(that.dataDisks) : that.dataDisks == null;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = super.hashCode(); return Objects.hashCode(virtualNetworkName, subnetId, availabilitySet, availabilitySetName, dataDisks,
result = 31 * result + (virtualNetworkName != null ? virtualNetworkName.hashCode() : 0); resourceGroup);
result = 31 * result + (subnetId != null ? subnetId.hashCode() : 0);
result = 31 * result + (blob != null ? blob.hashCode() : 0);
result = 31 * result + (availabilitySet != null ? availabilitySet.hashCode() : 0);
result = 31 * result + (availabilitySetName != null ? availabilitySetName.hashCode() : 0);
result = 31 * result + (dataDisks != null ? dataDisks.hashCode() : 0);
return result;
} }
@Override @Override
@ -160,14 +149,14 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
toString.add("virtualNetworkName", virtualNetworkName); toString.add("virtualNetworkName", virtualNetworkName);
if (subnetId != null) if (subnetId != null)
toString.add("subnetId", subnetId); toString.add("subnetId", subnetId);
if (blob != null)
toString.add("blob", blob);
if (availabilitySet != null) if (availabilitySet != null)
toString.add("availabilitySet", availabilitySet); toString.add("availabilitySet", availabilitySet);
if (availabilitySetName != null) if (availabilitySetName != null)
toString.add("availabilitySetName", availabilitySetName); toString.add("availabilitySetName", availabilitySetName);
if (!dataDisks.isEmpty()) if (!dataDisks.isEmpty())
toString.add("dataDisks", dataDisks); toString.add("dataDisks", dataDisks);
if (resourceGroup != null)
toString.add("resourceGroup", resourceGroup);
return toString; return toString;
} }
@ -188,14 +177,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
AzureTemplateOptions options = new AzureTemplateOptions(); AzureTemplateOptions options = new AzureTemplateOptions();
return options.subnetId(subnetId); return options.subnetId(subnetId);
} }
/**
* @see AzureTemplateOptions#blob(String)
*/
public static AzureTemplateOptions blob(String blob) {
AzureTemplateOptions options = new AzureTemplateOptions();
return options.blob(blob);
}
/** /**
* @see AzureTemplateOptions#availabilitySet(AvailabilitySet) * @see AzureTemplateOptions#availabilitySet(AvailabilitySet)
@ -214,16 +195,27 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
} }
/** /**
* @see AzureTemplateOptions#dataDisks * @see AzureTemplateOptions#dataDisks(DataDisk...)
*/ */
public static AzureTemplateOptions dataDisks(DataDisk... dataDisks) { public static AzureTemplateOptions dataDisks(DataDisk... dataDisks) {
AzureTemplateOptions options = new AzureTemplateOptions(); AzureTemplateOptions options = new AzureTemplateOptions();
return options.dataDisks(dataDisks); return options.dataDisks(dataDisks);
} }
/**
* @see AzureTemplateOptions#dataDisks(Iterable)
*/
public static AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) { public static AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
AzureTemplateOptions options = new AzureTemplateOptions(); AzureTemplateOptions options = new AzureTemplateOptions();
return options.dataDisks(dataDisks); return options.dataDisks(dataDisks);
} }
/**
* @see AzureTemplateOptions#resourceGroup(String)
*/
public static AzureTemplateOptions resourceGroup(String resourceGroup) {
AzureTemplateOptions options = new AzureTemplateOptions();
return options.resourceGroup(resourceGroup);
}
} }
} }

View File

@ -30,13 +30,12 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet; import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration; import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; 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.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi; import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
@ -45,10 +44,6 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; 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 @Singleton
public class CleanupResources { public class CleanupResources {
@ -59,52 +54,55 @@ public class CleanupResources {
private final AzureComputeApi api; private final AzureComputeApi api;
private final Predicate<URI> resourceDeleted; private final Predicate<URI> resourceDeleted;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final GroupNamingConvention.Factory namingConvention; private final GroupNamingConvention.Factory namingConvention;
@Inject @Inject
CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted, CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
LoadingCache<String, ResourceGroup> resourceGroupMap, GroupNamingConvention.Factory namingConvention) { GroupNamingConvention.Factory namingConvention) {
this.api = azureComputeApi; this.api = azureComputeApi;
this.resourceDeleted = resourceDeleted; this.resourceDeleted = resourceDeleted;
this.resourceGroupMap = resourceGroupMap;
this.namingConvention = namingConvention; this.namingConvention = namingConvention;
} }
public boolean cleanupNode(final String id) { public boolean cleanupNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id); ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region()); String resourceGroupName = resourceGroupAndName.resourceGroup();
String resourceGroupName = resourceGroup.name();
VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id()); VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(resourceGroupAndName.name());
if (virtualMachine == null) { if (virtualMachine == null) {
return true; return true;
} }
logger.debug(">> destroying %s ...", regionAndId.slashEncode()); logger.debug(">> destroying %s ...", id);
boolean vmDeleted = deleteVirtualMachine(resourceGroupName, virtualMachine); boolean vmDeleted = deleteVirtualMachine(resourceGroupName, virtualMachine);
// We don't delete the network here, as it is global to the resource // 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 // group. It will be deleted when the resource group is deleted
cleanupVirtualMachineNICs(resourceGroupName, virtualMachine); cleanupVirtualMachineNICs(virtualMachine);
cleanupAvailabilitySetIfOrphaned(resourceGroupName, virtualMachine); cleanupAvailabilitySetIfOrphaned(virtualMachine);
return vmDeleted; return vmDeleted;
} }
public void cleanupVirtualMachineNICs(String group, VirtualMachine virtualMachine) { public void cleanupVirtualMachineNICs(VirtualMachine virtualMachine) {
for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) { for (IdReference nicRef : virtualMachine.properties().networkProfile().networkInterfaces()) {
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName); String nicResourceGroup = nicRef.resourceGroup();
Iterable<String> publicIps = getPublicIps(group, nic); String nicName = nicRef.name();
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(nicRef.resourceGroup()).get(nicName);
Iterable<IdReference> publicIps = getPublicIps(nic);
logger.debug(">> destroying nic %s...", nicName); logger.debug(">> destroying nic %s...", nicName);
URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName); URI nicDeletionURI = api.getNetworkInterfaceCardApi(nicResourceGroup).delete(nicName);
resourceDeleted.apply(nicDeletionURI); resourceDeleted.apply(nicDeletionURI);
for (String publicIp : publicIps) { for (IdReference publicIp : publicIps) {
logger.debug(">> deleting public ip nic %s...", publicIp); String publicIpResourceGroup = publicIp.resourceGroup();
api.getPublicIPAddressApi(group).delete(publicIp); String publicIpName = publicIp.name();
logger.debug(">> deleting public ip nic %s...", publicIpName);
api.getPublicIPAddressApi(publicIpResourceGroup).delete(publicIpName);
} }
} }
} }
@ -135,12 +133,13 @@ public class CleanupResources {
return deleted; return deleted;
} }
public boolean cleanupAvailabilitySetIfOrphaned(String resourceGroup, VirtualMachine virtualMachine) { public boolean cleanupAvailabilitySetIfOrphaned(VirtualMachine virtualMachine) {
boolean deleted = false; boolean deleted = false;
IdReference availabilitySetRef = virtualMachine.properties().availabilitySet(); IdReference availabilitySetRef = virtualMachine.properties().availabilitySet();
if (availabilitySetRef != null) { if (availabilitySetRef != null) {
String name = Iterables.getLast(Splitter.on("/").split(availabilitySetRef.id())); String name = availabilitySetRef.name();
String resourceGroup = availabilitySetRef.resourceGroup();
AvailabilitySet availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(name); AvailabilitySet availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(name);
if (isOrphanedJcloudsAvailabilitySet(availabilitySet)) { if (isOrphanedJcloudsAvailabilitySet(availabilitySet)) {
@ -162,19 +161,13 @@ public class CleanupResources {
return deleted; return deleted;
} }
private Iterable<String> getPublicIps(String group, NetworkInterfaceCard nic) { private Iterable<IdReference> getPublicIps(NetworkInterfaceCard nic) {
return transform( return filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() { @Override
@Override public IdReference apply(IpConfiguration input) {
public IdReference apply(IpConfiguration input) { return input.properties().publicIPAddress();
return input.properties().publicIPAddress(); }
} }), notNull());
}), notNull()), new Function<IdReference, String>() {
@Override
public String apply(IdReference input) {
return Iterables.getLast(Splitter.on("/").split(input.id()));
}
});
} }
private static boolean isOrphanedJcloudsAvailabilitySet(AvailabilitySet availabilitySet) { private static boolean isOrphanedJcloudsAvailabilitySet(AvailabilitySet availabilitySet) {
@ -187,14 +180,6 @@ public class CleanupResources {
.virtualMachines().isEmpty()); .virtualMachines().isEmpty());
} }
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) { private boolean deleteVirtualMachine(String group, VirtualMachine virtualMachine) {
return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name())); return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name()));
} }

View File

@ -16,6 +16,12 @@
*/ */
package org.jclouds.azurecompute.arm.compute.strategy; package org.jclouds.azurecompute.arm.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
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 java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -27,12 +33,12 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.domain.RegionAndIdAndIngressRules; import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndNameAndIngressRules;
import org.jclouds.azurecompute.arm.compute.functions.TemplateToAvailabilitySet; import org.jclouds.azurecompute.arm.compute.functions.TemplateToAvailabilitySet;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet; import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; 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.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.Subnet; import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork; import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
@ -42,7 +48,6 @@ import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName; import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap; import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
@ -53,32 +58,26 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
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;
@Singleton @Singleton
public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet { public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final AzureComputeApi api; private final AzureComputeApi api;
private final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap; private final LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final String defaultVnetAddressPrefix; private final String defaultVnetAddressPrefix;
private final String defaultSubnetAddressPrefix; private final String defaultSubnetAddressPrefix;
private final TemplateToAvailabilitySet templateToAvailabilitySet; private final TemplateToAvailabilitySet templateToAvailabilitySet;
@Inject @Inject
protected CreateResourceGroupThenCreateNodes( protected CreateResourcesThenCreateNodes(
CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy, CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
ListNodesStrategy listNodesStrategy, ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention, GroupNamingConvention.Factory namingConvention,
@ -86,15 +85,13 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix, AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix,
@Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix, @Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix,
LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap, LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap,
LoadingCache<String, ResourceGroup> resourceGroupMap,
TemplateToAvailabilitySet templateToAvailabilitySet) { TemplateToAvailabilitySet templateToAvailabilitySet) {
super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor, super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory); customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.api = checkNotNull(api, "api cannot be null"); this.api = checkNotNull(api, "api cannot be null");
checkNotNull(userExecutor, "userExecutor cannot be null"); checkNotNull(userExecutor, "userExecutor cannot be null");
this.securityGroupMap = securityGroupMap; this.securityGroupMap = securityGroupMap;
this.resourceGroupMap = resourceGroupMap;
this.defaultVnetAddressPrefix = defaultVnetAddressPrefix; this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix; this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
this.templateToAvailabilitySet = templateToAvailabilitySet; this.templateToAvailabilitySet = templateToAvailabilitySet;
@ -117,24 +114,22 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
// This sill create the resource group if it does not exist // This sill create the resource group if it does not exist
String location = template.getLocation().getId(); String location = template.getLocation().getId();
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
String azureGroupName = resourceGroup.name();
getOrCreateVirtualNetworkWithSubnet(location, options, azureGroupName); createResourceGroupIfNeeded(group, location, options);
configureSecurityGroupForOptions(group, azureGroupName, template.getLocation(), options); getOrCreateVirtualNetworkWithSubnet(location, options);
configureSecurityGroupForOptions(group, template.getLocation(), options);
configureAvailabilitySetForTemplate(template); configureAvailabilitySetForTemplate(template);
return super.execute(group, count, template, goodNodes, badNodes, customizationResponses); return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
} }
protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options, protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options) {
final String azureGroupName) {
String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or( String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or(
azureGroupName + "virtualnetwork"); options.getResourceGroup() + "virtualnetwork");
String subnetName = azureGroupName + "subnet"; String subnetName = options.getResourceGroup() + "subnet";
// Subnets belong to a virtual network so that needs to be created first // Subnets belong to a virtual network so that needs to be created first
VirtualNetworkApi vnApi = api.getVirtualNetworkApi(azureGroupName); VirtualNetworkApi vnApi = api.getVirtualNetworkApi(options.getResourceGroup());
VirtualNetwork vn = vnApi.get(virtualNetworkName); VirtualNetwork vn = vnApi.get(virtualNetworkName);
if (vn == null) { if (vn == null) {
@ -148,7 +143,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties); vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
} }
SubnetApi subnetApi = api.getSubnetApi(azureGroupName, virtualNetworkName); SubnetApi subnetApi = api.getSubnetApi(options.getResourceGroup(), virtualNetworkName);
Subnet subnet = subnetApi.get(subnetName); Subnet subnet = subnetApi.get(subnetName);
options.virtualNetworkName(virtualNetworkName); options.virtualNetworkName(virtualNetworkName);
@ -160,23 +155,21 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
&& !template.getOptions().hasLoginPrivateKeyOption(); && !template.getOptions().hasLoginPrivateKeyOption();
} }
private void configureSecurityGroupForOptions(String group, String resourceGroup, Location location, private void configureSecurityGroupForOptions(String group, Location location, AzureTemplateOptions options) {
TemplateOptions options) {
checkArgument(options.getGroups().size() <= 1, checkArgument(options.getGroups().size() <= 1,
"Only one security group can be configured for each network interface"); "Only one security group can be configured for each network interface");
if (!options.getGroups().isEmpty()) { if (!options.getGroups().isEmpty()) {
String groupName = getOnlyElement(options.getGroups()); ResourceGroupAndName securityGroupId = ResourceGroupAndName.fromSlashEncoded(getOnlyElement(options.getGroups()));
String groupNameWithourRegion = groupName.indexOf('/') == -1 ? groupName : RegionAndId.fromSlashEncoded( NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(securityGroupId.resourceGroup()).get(
groupName).id(); securityGroupId.name());
NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup).get(groupNameWithourRegion); checkArgument(securityGroup != null, "Security group %s was not found", securityGroupId.slashEncode());
checkArgument(securityGroup != null, "Security group %s was not found", groupName);
options.securityGroups(securityGroup.id()); options.securityGroups(securityGroup.id());
} else if (options.getInboundPorts().length > 0) { } else if (options.getInboundPorts().length > 0) {
String name = namingConvention.create().sharedNameForGroup(group); String name = namingConvention.create().sharedNameForGroup(group);
RegionAndIdAndIngressRules regionAndIdAndIngressRules = RegionAndIdAndIngressRules.create(location.getId(), ResourceGroupAndNameAndIngressRules regionAndIdAndIngressRules = ResourceGroupAndNameAndIngressRules.create(
name, options.getInboundPorts()); options.getResourceGroup(), location.getId(), name, options.getInboundPorts());
// this will create if not yet exists. // this will create if not yet exists.
String securityGroupId = securityGroupMap.getUnchecked(regionAndIdAndIngressRules); String securityGroupId = securityGroupMap.getUnchecked(regionAndIdAndIngressRules);
options.securityGroups(securityGroupId); options.securityGroups(securityGroupId);
@ -190,4 +183,17 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
template.getOptions().as(AzureTemplateOptions.class).availabilitySet(availabilitySet); template.getOptions().as(AzureTemplateOptions.class).availabilitySet(availabilitySet);
} }
} }
private void createResourceGroupIfNeeded(String group, String location, AzureTemplateOptions options) {
if (options.getResourceGroup() == null) {
options.resourceGroup(group);
}
logger.debug(">> using resource group [%s]", options.getResourceGroup());
ResourceGroup rg = api.getResourceGroupApi().get(options.getResourceGroup());
if (rg == null) {
logger.debug(">> resource group [%s] does not exist. Creating!", options.getResourceGroup());
api.getResourceGroupApi().create(options.getResourceGroup(), location,
ImmutableMap.of("description", "jclouds default resource group"));
}
}
} }

View File

@ -16,19 +16,56 @@
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue; import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames; import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
// Simple helper class to serialize / deserialize id reference. // Simple helper class to serialize / deserialize id reference.
@AutoValue @AutoValue
public abstract class IdReference { public abstract class IdReference {
private static final Pattern RESOURCE_GROUP_PATTERN = Pattern.compile("^.*/resourceGroups/([^/]+)(/.*)?$");
@Nullable @Nullable
public abstract String id(); public abstract String id();
@Nullable
public String resourceGroup() {
return extractResourceGroup(id());
}
@Nullable
public String name() {
return extractName(id());
}
@SerializedNames({"id"}) @SerializedNames({"id"})
public static IdReference create(final String id) { public static IdReference create(final String id) {
return new AutoValue_IdReference(id); return new AutoValue_IdReference(id);
} }
/**
* Extracts the name from the given URI.
*/
public static String extractName(String uri) {
if (uri == null)
return null;
String noSlashAtEnd = uri.replaceAll("/+$", "");
return noSlashAtEnd.substring(noSlashAtEnd.lastIndexOf('/') + 1);
}
/**
* Extracts the resource group name from the given URI.
*/
public static String extractResourceGroup(String uri) {
if (uri == null)
return null;
Matcher m = RESOURCE_GROUP_PATTERN.matcher(uri);
return m.matches() ? m.group(1) : null;
}
} }

View File

@ -62,14 +62,9 @@ public abstract class VMHardware {
*/ */
public abstract String location(); public abstract String location();
/** @SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location"})
* Specifies if this HW is globally available public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location) {
*/
public abstract boolean globallyAvailable();
@SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location", "globallyAvailable"}) return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location);
public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location, boolean globallyAvailable) {
return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location, globallyAvailable);
} }
} }

View File

@ -98,6 +98,13 @@ public abstract class VMImage {
*/ */
@Nullable @Nullable
public abstract String customImageId(); public abstract String customImageId();
/**
* The resource group for the image in case of custom images.
* @return
*/
@Nullable
public abstract String resourceGroup();
/** /**
* Extended version properties. * Extended version properties.
@ -127,6 +134,7 @@ public abstract class VMImage {
public abstract static class Builder { public abstract static class Builder {
public abstract Builder customImageId(String id); public abstract Builder customImageId(String id);
public abstract Builder resourceGroup(String resourceGroup);
public abstract Builder publisher(String published); public abstract Builder publisher(String published);
public abstract Builder offer(String offer); public abstract Builder offer(String offer);
public abstract Builder sku(String sku); public abstract Builder sku(String sku);

View File

@ -15,6 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import java.io.Closeable; import java.io.Closeable;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
@ -37,7 +38,6 @@ import org.jclouds.rest.annotations.SelectJson;
/** /**
* The Azure Resource Manager API checks for job status and progress. * The Azure Resource Manager API checks for job status and progress.
*/ */
@RequestFilters(OAuthFilter.class) @RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface JobApi extends Closeable { public interface JobApi extends Closeable {

View File

@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class VMImages { public class VMImages {
public static boolean isCustom(String imageId) { public static boolean isCustom(String imageId) {
return checkNotNull(imageId, "id").split("/").length == 2; return checkNotNull(imageId, "id").split("/").length == 3;
} }
} }

View File

@ -16,8 +16,8 @@
*/ */
package org.jclouds.azurecompute.arm.compute; package org.jclouds.azurecompute.arm.compute;
import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import java.net.URI; import java.net.URI;
@ -25,7 +25,6 @@ import java.util.Properties;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
@ -42,7 +41,6 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -54,19 +52,17 @@ import com.google.inject.name.Names;
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest") @Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest")
public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest { public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted; private Predicate<URI> resourceDeleted;
private String resourceGroupName;
public AzureComputeServiceLiveTest() { public AzureComputeServiceLiveTest() {
provider = "azurecompute-arm"; provider = "azurecompute-arm";
resourceGroupName = getClass().getSimpleName().toLowerCase();
} }
@Override @Override
public void initializeContext() { public void initializeContext() {
super.initializeContext(); super.initializeContext();
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() { resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED))); }, Names.named(TIMEOUT_RESOURCE_DELETED)));
} }
@ -75,16 +71,10 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@AfterClass(groups = "live", alwaysRun = true) @AfterClass(groups = "live", alwaysRun = true)
protected void tearDownContext() { protected void tearDownContext() {
try { try {
if (template != null) { URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
ResourceGroup rg = resourceGroupMap.getIfPresent(template.getLocation().getId()); if (uri != null) {
if (rg != null) { assertTrue(resourceDeleted.apply(uri),
AzureComputeApi api = view.unwrapApi(AzureComputeApi.class); String.format("Resource %s was not terminated in the configured timeout", uri));
URI uri = api.getResourceGroupApi().delete(rg.name());
if (uri != null) {
assertTrue(resourceDeleted.apply(uri),
String.format("Resource %s was not terminated in the configured timeout", uri));
}
}
} }
} finally { } finally {
super.tearDownContext(); super.tearDownContext();
@ -109,7 +99,7 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase()); AzureLiveTestUtils.defaultProperties(properties);
setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
return properties; return properties;
} }
@ -117,7 +107,8 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override @Override
protected TemplateBuilder templateBuilder() { protected TemplateBuilder templateBuilder() {
return super.templateBuilder().options( return super.templateBuilder().options(
authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private"))); resourceGroup(resourceGroupName).authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(
keyPair.get("private")));
} }
@Override @Override

View File

@ -56,7 +56,7 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase()); AzureLiveTestUtils.defaultProperties(properties);
setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
return properties; return properties;
} }

View File

@ -16,7 +16,7 @@
*/ */
package org.jclouds.azurecompute.arm.compute.extensions; package org.jclouds.azurecompute.arm.compute.extensions;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey; import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript; import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -28,7 +28,6 @@ import java.util.Properties;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.ComputeTestUtils; import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.ExecResponse;
@ -43,7 +42,6 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -56,30 +54,27 @@ import com.google.inject.name.Names;
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest") @Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest { public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted; private Predicate<URI> resourceDeleted;
private ResourceGroup testResourceGroup; private String resourceGroupName;
public AzureComputeImageExtensionLiveTest() { public AzureComputeImageExtensionLiveTest() {
provider = "azurecompute-arm"; provider = "azurecompute-arm";
resourceGroupName = getClass().getSimpleName().toLowerCase();
} }
@BeforeClass(groups = { "integration", "live" }) @BeforeClass(groups = { "integration", "live" })
public void setupContext() { public void setupContext() {
super.setupContext(); super.setupContext();
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() { resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED))); }, Names.named(TIMEOUT_RESOURCE_DELETED)));
createResourceGroup(); createResourceGroup(resourceGroupName);
} }
@AfterClass(groups = { "integration", "live" }) @AfterClass(groups = { "integration", "live" })
@Override @Override
protected void tearDownContext() { protected void tearDownContext() {
try { try {
URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name()); URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
if (uri != null) { if (uri != null) {
assertTrue(resourceDeleted.apply(uri), assertTrue(resourceDeleted.apply(uri),
String.format("Resource %s was not terminated in the configured timeout", uri)); String.format("Resource %s was not terminated in the configured timeout", uri));
@ -108,7 +103,7 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase()); AzureLiveTestUtils.defaultProperties(properties);
setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
return properties; return properties;
} }
@ -122,11 +117,12 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
public TemplateBuilder getNodeTemplate() { public TemplateBuilder getNodeTemplate() {
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair(); Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
return super.getNodeTemplate().options( return super.getNodeTemplate().options(
authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private"))); resourceGroup(resourceGroupName).authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(
keyPair.get("private")));
} }
private void createResourceGroup() { private void createResourceGroup(String name) {
Location location = getNodeTemplate().build().getLocation(); Location location = getNodeTemplate().build().getLocation();
testResourceGroup = resourceGroupMap.getUnchecked(location.getId()); view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(name, location.getId(), null);
} }
} }

View File

@ -18,9 +18,8 @@ package org.jclouds.azurecompute.arm.compute.extensions;
import static com.google.common.collect.Iterables.get; import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
import static org.jclouds.compute.options.TemplateOptions.Builder.securityGroups;
import static org.jclouds.compute.predicates.NodePredicates.inGroup; import static org.jclouds.compute.predicates.NodePredicates.inGroup;
import static org.jclouds.net.domain.IpProtocol.TCP; import static org.jclouds.net.domain.IpProtocol.TCP;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -34,12 +33,13 @@ import java.util.concurrent.ExecutionException;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException; import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.SecurityGroup; import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.extensions.SecurityGroupExtension; import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest; import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -52,7 +52,6 @@ import org.testng.annotations.Test;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.name.Names; import com.google.inject.name.Names;
@ -64,23 +63,20 @@ import com.google.inject.name.Names;
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeSecurityGroupExtensionLiveTest") @Test(groups = "live", singleThreaded = true, testName = "AzureComputeSecurityGroupExtensionLiveTest")
public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest { public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted; private Predicate<URI> resourceDeleted;
private ResourceGroup testResourceGroup; private String resourceGroupName;
public AzureComputeSecurityGroupExtensionLiveTest() { public AzureComputeSecurityGroupExtensionLiveTest() {
provider = "azurecompute-arm"; provider = "azurecompute-arm";
resourceGroupName = "sgelivetest";
} }
@BeforeClass(groups = { "integration", "live" }) @BeforeClass(groups = { "integration", "live" })
public void setupContext() { public void setupContext() {
super.setupContext(); super.setupContext();
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() { resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED))); }, Names.named(TIMEOUT_RESOURCE_DELETED)));
createResourceGroup(); createResourceGroup(resourceGroupName);
} }
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec") @Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec")
@ -104,7 +100,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension(); Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present"); assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1, securityGroups(groupId))); NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1,
options().securityGroups(groupId)));
try { try {
Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId()); Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
@ -121,8 +118,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension(); Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present"); assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
NodeMetadata node = getOnlyElement(computeService NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1,
.createNodesInGroup(nodeGroup, 1, inboundPorts(22, 23, 24, 8000))); options().inboundPorts(22, 23, 24, 8000)));
try { try {
Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId()); Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
@ -141,7 +138,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
@Override @Override
protected void tearDownContext() { protected void tearDownContext() {
try { try {
URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name()); URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
if (uri != null) { if (uri != null) {
assertTrue(resourceDeleted.apply(uri), assertTrue(resourceDeleted.apply(uri),
String.format("Resource %s was not terminated in the configured timeout", uri)); String.format("Resource %s was not terminated in the configured timeout", uri));
@ -154,7 +151,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, "sgelivetest"); AzureLiveTestUtils.defaultProperties(properties);
setIfTestSystemPropertyPresent(properties, "oauth.endpoint"); setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
return properties; return properties;
} }
@ -163,9 +160,18 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
protected ProviderMetadata createProviderMetadata() { protected ProviderMetadata createProviderMetadata() {
return AzureComputeProviderMetadata.builder().build(); return AzureComputeProviderMetadata.builder().build();
} }
private AzureTemplateOptions options() {
return resourceGroup(resourceGroupName);
}
@Override
public Template getNodeTemplate() {
return view.getComputeService().templateBuilder().options(options()).build();
}
private void createResourceGroup() { private void createResourceGroup(String name) {
Location location = getNodeTemplate().getLocation(); Location location = getNodeTemplate().getLocation();
testResourceGroup = resourceGroupMap.getUnchecked(location.getId()); view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(name, location.getId(), null);
} }
} }

View File

@ -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.domain;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractName;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
public class IdReferenceTest {
@Test
public void testExtractResourceGroup() {
assertEquals(extractResourceGroup(null), null);
assertEquals(extractResourceGroup(""), null);
assertEquals(
extractResourceGroup("/subscriptions/subscription/resourceGroups/jclouds-northeurope/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
"jclouds-northeurope");
assertEquals(extractResourceGroup("/subscriptions/subscription/resourceGroups/jclouds-west"), "jclouds-west");
assertEquals(extractResourceGroup("/resourceGroups/jclouds-west2"), "jclouds-west2");
assertEquals(
extractResourceGroup("/resourceGroups/jclouds-northeurope2/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
"jclouds-northeurope2");
assertEquals(extractResourceGroup("resourceGroups/jclouds-west2"), null);
assertEquals(
extractResourceGroup("resourceGroups/jclouds-northeurope2/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
null);
assertEquals(
extractResourceGroup("/subscriptions/subscription/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
null);
assertEquals(
extractResourceGroup("/subscriptions/subscription/resourceGroups//jclouds-northeurope/providers/Microsoft.Compute/virtualMachines/resources-8c5"),
null);
}
@Test
public void testExtractName() {
assertEquals(extractName(null), null);
assertEquals(extractName(""), "");
assertEquals(extractName("foo"), "foo");
assertEquals(extractName("/foo/bar"), "bar");
assertEquals(extractName("/foo/bar/"), "bar");
assertEquals(extractName("/foo/bar////"), "bar");
assertEquals(extractName("/foo///bar////"), "bar");
assertEquals(extractName("////bar"), "bar");
}
}

View File

@ -24,7 +24,7 @@ import static org.jclouds.compute.predicates.NodePredicates.inGroup;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
@ -32,18 +32,15 @@ import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.Image; import org.jclouds.azurecompute.arm.domain.Image;
import org.jclouds.azurecompute.arm.domain.ImageProperties; import org.jclouds.azurecompute.arm.domain.ImageProperties;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.RunNodesException; import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.domain.Location;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.name.Names; import com.google.inject.name.Names;
@ -54,11 +51,9 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
private static final String imageName = "imageFromRest"; private static final String imageName = "imageFromRest";
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted; private Predicate<URI> resourceDeleted;
private AzureComputeApi api; private AzureComputeApi api;
private String resourceGroupName;
private String location; private String location;
private ImageApi imageApi; private ImageApi imageApi;
private Image image; private Image image;
@ -73,7 +68,7 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase()); AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties; return properties;
} }
@ -83,9 +78,6 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
super.initializeContext(); super.initializeContext();
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() { resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED))); }, Names.named(TIMEOUT_RESOURCE_DELETED)));
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
api = view.unwrapApi(AzureComputeApi.class); api = view.unwrapApi(AzureComputeApi.class);
} }
@ -94,10 +86,9 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
public void setupContext() { public void setupContext() {
super.setupContext(); super.setupContext();
// Use the resource name conventions used in the abstraction // Use the resource name conventions used in the abstraction
ResourceGroup resourceGroup = createResourceGroup(); location = view.getComputeService().templateBuilder().build().getLocation().getId();
resourceGroupName = resourceGroup.name(); view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
location = resourceGroup.location(); imageApi = api.getVirtualMachineImageApi(group);
imageApi = api.getVirtualMachineImageApi(resourceGroupName);
} }
@Override @Override
@ -107,7 +98,7 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
view.getComputeService().destroyNodesMatching(inGroup(group)); view.getComputeService().destroyNodesMatching(inGroup(group));
} finally { } finally {
try { try {
URI uri = api.getResourceGroupApi().delete(resourceGroupName); URI uri = api.getResourceGroupApi().delete(group);
assertResourceDeleted(uri); assertResourceDeleted(uri);
} finally { } finally {
super.tearDownContext(); super.tearDownContext();
@ -122,11 +113,11 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
@Test @Test
public void testCreateImage() throws RunNodesException { public void testCreateImage() throws RunNodesException {
NodeMetadata node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1)); NodeMetadata node = getOnlyElement(view.getComputeService().createNodesInGroup(group, 1, resourceGroup(group)));
IdReference vmIdRef = IdReference.create(node.getProviderId()); IdReference vmIdRef = IdReference.create(node.getProviderId());
view.getComputeService().suspendNode(node.getId()); view.getComputeService().suspendNode(node.getId());
api.getVirtualMachineApi(resourceGroupName).generalize(node.getName()); api.getVirtualMachineApi(group).generalize(node.getName());
image = imageApi.createOrUpdate(imageName, location, ImageProperties.builder() image = imageApi.createOrUpdate(imageName, location, ImageProperties.builder()
.sourceVirtualMachine(vmIdRef).build()); .sourceVirtualMachine(vmIdRef).build());
@ -161,9 +152,4 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
} }
} }
private ResourceGroup createResourceGroup() {
Location location = view.getComputeService().templateBuilder().build().getLocation();
return resourceGroupMap.getUnchecked(location.getId());
}
} }

View File

@ -16,13 +16,12 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.availabilitySet;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.getLast;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;
import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.availabilitySet;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.azurecompute.arm.domain.InboundNatRuleProperties.Protocol.Tcp; import static org.jclouds.azurecompute.arm.domain.InboundNatRuleProperties.Protocol.Tcp;
import static org.jclouds.compute.predicates.NodePredicates.inGroup; import static org.jclouds.compute.predicates.NodePredicates.inGroup;
@ -40,7 +39,9 @@ import java.util.Set;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.PublicIpAvailablePredicateFactory;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet; import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
import org.jclouds.azurecompute.arm.domain.BackendAddressPool; import org.jclouds.azurecompute.arm.domain.BackendAddressPool;
import org.jclouds.azurecompute.arm.domain.BackendAddressPoolProperties; import org.jclouds.azurecompute.arm.domain.BackendAddressPoolProperties;
import org.jclouds.azurecompute.arm.domain.FrontendIPConfigurations; import org.jclouds.azurecompute.arm.domain.FrontendIPConfigurations;
@ -62,24 +63,18 @@ import org.jclouds.azurecompute.arm.domain.ProbeProperties;
import org.jclouds.azurecompute.arm.domain.Provisionable; import org.jclouds.azurecompute.arm.domain.Provisionable;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties; 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.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.RunNodesException; import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.domain.Location;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.Key; import com.google.inject.Key;
@ -93,13 +88,11 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
private static final String lbName = String.format("lb-%s-%s", LoadBalancerApiLiveTest.class.getSimpleName() private static final String lbName = String.format("lb-%s-%s", LoadBalancerApiLiveTest.class.getSimpleName()
.toLowerCase(), System.getProperty("user.name")); .toLowerCase(), System.getProperty("user.name"));
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted; private Predicate<URI> resourceDeleted;
private PublicIpAvailablePredicateFactory publicIpAvailable; private PublicIpAvailablePredicateFactory publicIpAvailable;
private Predicate<Supplier<Provisionable>> resourceAvailable; private Predicate<Supplier<Provisionable>> resourceAvailable;
private AzureComputeApi api; private AzureComputeApi api;
private String resourceGroupName;
private String location; private String location;
private LoadBalancerApi lbApi; private LoadBalancerApi lbApi;
private NetworkInterfaceCardApi nicApi; private NetworkInterfaceCardApi nicApi;
@ -116,7 +109,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase()); AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties; return properties;
} }
@ -126,9 +119,6 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
super.initializeContext(); super.initializeContext();
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() { resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED))); }, Names.named(TIMEOUT_RESOURCE_DELETED)));
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
publicIpAvailable = context.utils().injector().getInstance(PublicIpAvailablePredicateFactory.class); publicIpAvailable = context.utils().injector().getInstance(PublicIpAvailablePredicateFactory.class);
resourceAvailable = context.utils().injector() resourceAvailable = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<Predicate<Supplier<Provisionable>>>() { .getInstance(Key.get(new TypeLiteral<Predicate<Supplier<Provisionable>>>() {
@ -142,11 +132,10 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
super.setupContext(); super.setupContext();
// Use the resource name conventions used in the abstraction so the nodes // Use the resource name conventions used in the abstraction so the nodes
// can see the load balancer // can see the load balancer
ResourceGroup resourceGroup = createResourceGroup(); location = view.getComputeService().templateBuilder().build().getLocation().getId();
resourceGroupName = resourceGroup.name(); view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
location = resourceGroup.location(); lbApi = api.getLoadBalancerApi(group);
lbApi = api.getLoadBalancerApi(resourceGroupName); nicApi = api.getNetworkInterfaceCardApi(group);
nicApi = api.getNetworkInterfaceCardApi(resourceGroupName);
} }
@Override @Override
@ -156,7 +145,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
view.getComputeService().destroyNodesMatching(inGroup(group)); view.getComputeService().destroyNodesMatching(inGroup(group));
} finally { } finally {
try { try {
URI uri = api.getResourceGroupApi().delete(resourceGroupName); URI uri = api.getResourceGroupApi().delete(group);
assertResourceDeleted(uri); assertResourceDeleted(uri);
} finally { } finally {
super.tearDownContext(); super.tearDownContext();
@ -316,7 +305,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
} }
private PublicIPAddress createPublicIPAddress(final String publicIpAddressName) { private PublicIPAddress createPublicIPAddress(final String publicIpAddressName) {
final PublicIPAddressApi ipApi = view.unwrapApi(AzureComputeApi.class).getPublicIPAddressApi(resourceGroupName); final PublicIPAddressApi ipApi = view.unwrapApi(AzureComputeApi.class).getPublicIPAddressApi(group);
PublicIPAddress publicIPAddress = ipApi.get(publicIpAddressName); PublicIPAddress publicIPAddress = ipApi.get(publicIpAddressName);
if (publicIPAddress == null) { if (publicIPAddress == null) {
@ -325,7 +314,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
.idleTimeoutInMinutes(4).build(); .idleTimeoutInMinutes(4).build();
publicIPAddress = ipApi.createOrUpdate(publicIpAddressName, location, tags, properties); publicIPAddress = ipApi.createOrUpdate(publicIpAddressName, location, tags, properties);
checkState(publicIpAvailable.create(resourceGroupName).apply(publicIpAddressName), checkState(publicIpAvailable.create(group).apply(publicIpAddressName),
"Public IP was not provisioned in the configured timeout"); "Public IP was not provisioned in the configured timeout");
} }
@ -358,16 +347,16 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
.platformFaultDomainCount(count).build(); .platformFaultDomainCount(count).build();
AvailabilitySet as = AvailabilitySet.managed().name(group).properties(props).build(); AvailabilitySet as = AvailabilitySet.managed().name(group).properties(props).build();
Set<? extends NodeMetadata> nodes = view.getComputeService() Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(group, count,
.createNodesInGroup(group, count, availabilitySet(as)); availabilitySet(as).resourceGroup(this.group));
List<String> nicNames = new ArrayList<String>(); List<String> nicNames = new ArrayList<String>();
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(node.getId()); ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(node.getId());
VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id()); VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
resourceGroupAndName.name());
String nicName = getLast(Splitter.on("/").split( String nicName = vm.properties().networkProfile().networkInterfaces().get(0).name();
vm.properties().networkProfile().networkInterfaces().get(0).id()));
nicNames.add(nicName); nicNames.add(nicName);
} }
@ -426,11 +415,6 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
return nicApi.get(nicName); return nicApi.get(nicName);
} }
private ResourceGroup createResourceGroup() {
Location location = view.getComputeService().templateBuilder().build().getLocation();
return resourceGroupMap.getUnchecked(location.getId());
}
private LoadBalancer updateLoadBalancer(final String name, LoadBalancerProperties props) { private LoadBalancer updateLoadBalancer(final String name, LoadBalancerProperties props) {
lbApi.createOrUpdate(name, location, null, props); lbApi.createOrUpdate(name, location, null, props);
resourceAvailable.apply(new Supplier<Provisionable>() { resourceAvailable.apply(new Supplier<Provisionable>() {

View File

@ -16,11 +16,7 @@
*/ */
package org.jclouds.azurecompute.arm.internal; package org.jclouds.azurecompute.arm.internal;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_PREFIX;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; 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_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
@ -30,14 +26,16 @@ 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.CredentialType.CLIENT_CREDENTIALS_SECRET;
import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
public class AzureLiveTestUtils { public class AzureLiveTestUtils {
public static Properties defaultProperties(Properties properties, String resourceNamePrefix) { public static Properties defaultProperties(Properties properties) {
properties = properties == null ? new Properties() : properties; properties = properties == null ? new Properties() : properties;
properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
properties.put(PROPERTY_REGIONS, "westeurope"); properties.put(PROPERTY_REGIONS, "westeurope");
properties.put(IMAGE_PUBLISHERS, "Canonical"); properties.put(IMAGE_PUBLISHERS, "Canonical");
properties.put(RESOURCENAME_PREFIX, resourceNamePrefix);
String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES)); String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout); properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);

View File

@ -97,7 +97,7 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
@Override protected Properties setupProperties() { @Override protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
// for oauth // for oauth
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase()); AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties; return properties;
} }