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;
import java.io.Closeable;
import javax.ws.rs.PathParam;
import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
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.JobApi;
import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
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.NetworkSecurityGroupApi;
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>
*/
public interface AzureComputeApi extends Closeable {
/**
* The Azure Resource Manager API includes operations for managing resource groups in your subscription.
*
@ -56,6 +57,9 @@ public interface AzureComputeApi extends Closeable {
@Delegate
ResourceGroupApi getResourceGroupApi();
/**
* Provides access to the Job tracking API.
*/
@Delegate
JobApi getJobApi();

View File

@ -31,8 +31,8 @@ import javax.inject.Provider;
import javax.inject.Singleton;
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.domain.ResourceGroup;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
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.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListeningExecutorService;
@ -70,7 +69,6 @@ import com.google.common.util.concurrent.ListeningExecutorService;
@Singleton
public class AzureComputeService extends BaseComputeService {
private final CleanupResources cleanupResources;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject
protected AzureComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@ -89,14 +87,13 @@ public class AzureComputeService extends BaseComputeService {
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CleanupResources cleanupResources, Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension, LoadingCache<String, ResourceGroup> resourceGroupMap) {
Optional<SecurityGroupExtension> securityGroupExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
this.cleanupResources = cleanupResources;
this.resourceGroupMap = resourceGroupMap;
}
@Override
@ -105,11 +102,11 @@ public class AzureComputeService extends BaseComputeService {
ImmutableSet.Builder<String> resourceGroups = ImmutableSet.builder();
for (NodeMetadata deadNode : deadNodes) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(deadNode.getLocation().getId());
resourceGroups.add(resourceGroup.name());
String resourceGroupName = ResourceGroupAndName.fromSlashEncoded(deadNode.getId()).resourceGroup();
resourceGroups.add(resourceGroupName);
if (deadNode.getGroup() != null) {
regionGroups.put(resourceGroup.name(), deadNode.getGroup());
regionGroups.put(resourceGroupName, deadNode.getGroup());
}
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.collect.ImmutableList.builder;
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.getOnlyElement;
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.getMarketplacePlanFromImageMetadata;
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.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.options.AzureTemplateOptions;
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.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.domain.SKU;
@ -90,7 +92,6 @@ import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -115,20 +116,18 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
private final List<String> imagePublishers;
private final Supplier<Set<String>> regionIds;
private final PublicIpAvailablePredicateFactory publicIpAvailable;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final CustomImageToVMImage customImagetoVmImage;
@Inject
AzureComputeServiceAdapter(final AzureComputeApi api, @Named(IMAGE_PUBLISHERS) String imagePublishers,
CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
PublicIpAvailablePredicateFactory publicIpAvailable, LoadingCache<String, ResourceGroup> resourceGroupMap,
PublicIpAvailablePredicateFactory publicIpAvailable,
CustomImageToVMImage customImagetoVmImage) {
this.api = api;
this.imagePublishers = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(imagePublishers);
this.cleanupResources = cleanupResources;
this.regionIds = regionIds;
this.publicIpAvailable = publicIpAvailable;
this.resourceGroupMap = resourceGroupMap;
this.customImagetoVmImage = customImagetoVmImage;
}
@ -138,15 +137,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
String locationName = template.getLocation().getId();
Image image = template.getImage();
String hardwareId = template.getHardware().getId();
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(locationName);
String hardwareId = fromSlashEncoded(template.getHardware().getId()).name();
// TODO ARM specific options
AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
String subnetId = templateOptions.getSubnetId();
String resourceGroupName = templateOptions.getResourceGroup();
IdReference availabilitySet = getAvailabilitySetIdReference(templateOptions.getAvailabilitySet());
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();
OSProfile osProfile = createOsProfile(name, template);
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());
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);
// Safe to pass null credentials here, as jclouds will default populate
// the node with the default credentials from the image, or the ones in
// the options, if provided.
RegionAndId regionAndId = RegionAndId.fromRegionAndId(locationName, name);
return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, regionAndId.slashEncode(), null);
ResourceGroupAndName resourceGroupAndName = fromResourceGroupAndName(resourceGroupName, name);
return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, resourceGroupAndName.slashEncode(), null);
}
@Override
@ -183,8 +182,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
for (VMSize vmSize : vmSizes) {
VMHardware hwProfile = VMHardware
.create(vmSize.name(), vmSize.numberOfCores(), vmSize.osDiskSizeInMB(),
vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name(),
false);
vmSize.resourceDiskSizeInMB(), vmSize.memoryInMB(), vmSize.maxDataDiskCount(), location.name());
hwProfiles.add(hwProfile);
}
}
@ -221,9 +219,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
return osImages;
}
private List<VMImage> listCustomImagesByLocation(String location) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup.name()).list();
private List<VMImage> listCustomImagesByResourceGroup(String resourceGroup) {
List<org.jclouds.azurecompute.arm.domain.Image> customImages = api.getVirtualMachineImageApi(resourceGroup).list();
return Lists.transform(customImages, customImagetoVmImage);
}
@ -231,16 +228,29 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
public Iterable<VMImage> listImages() {
final ImmutableList.Builder<VMImage> osImages = ImmutableList.builder();
Iterable<String> availableLocationNames = transform(listLocations(), new Function<Location, String>() {
@Override
public String apply(Location location) {
return location.name();
}
});
final List<String> availableLocationNames = newArrayList(transform(listLocations(),
new Function<Location, String>() {
@Override
public String apply(Location location) {
return location.name();
}
}));
for (String locationName : availableLocationNames) {
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();
@ -249,10 +259,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override
public VMImage getImage(final String id) {
VMImage image = decodeFieldsFromUniqueId(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
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);
}
@ -304,9 +314,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override
public VirtualMachine getNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
return api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
return api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(resourceGroupAndName.name());
}
@Override
@ -316,23 +325,20 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override
public void rebootNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
api.getVirtualMachineApi(resourceGroup.name()).restart(regionAndId.id());
ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).restart(resourceGroupAndName.name());
}
@Override
public void resumeNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
api.getVirtualMachineApi(resourceGroup.name()).start(regionAndId.id());
ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).start(resourceGroupAndName.name());
}
@Override
public void suspendNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
api.getVirtualMachineApi(resourceGroup.name()).stop(regionAndId.id());
ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).stop(resourceGroupAndName.name());
}
@Override
@ -346,10 +352,10 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Virtual
@Override
public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<VirtualMachine>() {
return transform(ids, new Function<String, VirtualMachine>() {
@Override
public boolean apply(VirtualMachine virtualMachine) {
return contains(ids, virtualMachine.id());
public VirtualMachine apply(String input) {
return getNode(input);
}
});
}

View File

@ -34,7 +34,7 @@ import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.AzureComputeService;
import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
import org.jclouds.azurecompute.arm.compute.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.AzureComputeSecurityGroupExtension;
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.VirtualMachineToNodeMetadata;
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.strategy.CreateResourceGroupThenCreateNodes;
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourcesThenCreateNodes;
import org.jclouds.azurecompute.arm.domain.Image;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
@ -116,12 +116,12 @@ public class AzureComputeServiceContextModule extends
bind(TemplateOptions.class).to(AzureTemplateOptions.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);
bind(new TypeLiteral<CacheLoader<String, ResourceGroup>>() {
}).to(ResourceGroupForLocation.class);
}).to(DefaultResourceGroup.class);
bind(new TypeLiteral<ImageExtension>() {
}).to(AzureComputeImageExtension.class);
@ -131,14 +131,14 @@ public class AzureComputeServiceContextModule extends
@Provides
@Singleton
protected final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap(
CacheLoader<RegionAndIdAndIngressRules, String> in) {
protected final LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap(
CacheLoader<ResourceGroupAndNameAndIngressRules, String> in) {
return CacheBuilder.newBuilder().build(in);
}
@Provides
@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);
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* 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.checkNotNull;
@ -24,27 +24,27 @@ import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
@AutoValue
public abstract class RegionAndId {
public abstract class LocationAndName {
public abstract String region();
public abstract String id();
public abstract String location();
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"));
checkArgument(Iterables.size(parts) == 2, "id must be in format regionId/id");
return new AutoValue_RegionAndId(Iterables.get(parts, 0), Iterables.get(parts, 1));
checkArgument(Iterables.size(parts) == 2, "id must be in format location/name");
return new AutoValue_LocationAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
}
public static RegionAndId fromRegionAndId(String region, String id) {
return new AutoValue_RegionAndId(region, id);
public static LocationAndName fromLocationAndName(String location, String name) {
return new AutoValue_LocationAndName(location, name);
}
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;
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.common.base.Objects;
@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();
RegionAndIdAndIngressRules() {
ResourceGroupAndNameAndIngressRules() {
}
public static RegionAndIdAndIngressRules create(String region, String id, int[] inboundPorts) {
return new AutoValue_RegionAndIdAndIngressRules(RegionAndId.fromRegionAndId(region, id), inboundPorts);
public static ResourceGroupAndNameAndIngressRules create(String resourceGroup, String location, String name,
int[] inboundPorts) {
return new AutoValue_ResourceGroupAndNameAndIngressRules(fromResourceGroupAndName(resourceGroup, name), location,
inboundPorts);
}
public String id() {
return regionAndId().id();
public String name() {
return resourceGroupAndName().name();
}
public String region() {
return regionAndId().region();
public String resourceGroup() {
return resourceGroupAndName().resourceGroup();
}
// Intentionally delegate equals and hashcode to the fields in the parent
@ -48,7 +53,7 @@ public abstract class RegionAndIdAndIngressRules {
@Override
public int hashCode() {
return Objects.hashCode(region(), id());
return Objects.hashCode(resourceGroup(), name());
}
@Override
@ -56,11 +61,11 @@ public abstract class RegionAndIdAndIngressRules {
if (obj == this) {
return true;
}
if (!(obj instanceof RegionAndId)) {
if (!(obj instanceof ResourceGroupAndName)) {
return false;
}
RegionAndId that = (RegionAndId) obj;
return Objects.equal(region(), that.region()) && Objects.equal(id(), that.id());
ResourceGroupAndName that = (ResourceGroupAndName) obj;
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.Preconditions.checkArgument;
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.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
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.compute.config.AzureComputeServiceContextModule.ImageAvailablePredicateFactory;
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.domain.IdReference;
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.VirtualMachine;
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.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
@ -66,25 +65,21 @@ public class AzureComputeImageExtension implements ImageExtension {
private final ListeningExecutorService userExecutor;
private final ImageAvailablePredicateFactory imageAvailablePredicate;
private final VirtualMachineInStatePredicateFactory nodeSuspendedPredicate;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final Function<VMImage, Image> vmImageToImage;
private final Predicate<URI> resourceDeleted;
private final CustomImageToVMImage customImagetoVmImage;
@Inject
AzureComputeImageExtension(AzureComputeApi api,
ImageAvailablePredicateFactory imageAvailablePredicate,
AzureComputeImageExtension(AzureComputeApi api, ImageAvailablePredicateFactory imageAvailablePredicate,
@Named(TIMEOUT_NODE_SUSPENDED) VirtualMachineInStatePredicateFactory nodeSuspendedPredicate,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Function<VMImage, Image> vmImageToImage, LoadingCache<String, ResourceGroup> resourceGroupMap,
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
Function<VMImage, Image> vmImageToImage, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
CustomImageToVMImage customImagetoVmImage) {
this.api = api;
this.imageAvailablePredicate = imageAvailablePredicate;
this.nodeSuspendedPredicate = nodeSuspendedPredicate;
this.userExecutor = userExecutor;
this.vmImageToImage = vmImageToImage;
this.resourceGroupMap = resourceGroupMap;
this.resourceDeleted = resourceDeleted;
this.customImagetoVmImage = customImagetoVmImage;
}
@ -97,27 +92,27 @@ public class AzureComputeImageExtension implements ImageExtension {
@Override
public ListenableFuture<Image> createImage(ImageTemplate template) {
final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
final String resourceGroupName = resourceGroup.name();
final ResourceGroupAndName resourceGroupAndName = fromSlashEncoded(cloneTemplate.getSourceNodeId());
final String resourceGroupName = resourceGroupAndName.resourceGroup();
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());
logger.debug(">> stopping node %s...", regionAndId.slashEncode());
api.getVirtualMachineApi(resourceGroupName).stop(regionAndId.id());
checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(regionAndId.id()),
"Node %s was not suspended within the configured time limit", regionAndId.slashEncode());
logger.debug(">> stopping node %s...", cloneTemplate.getSourceNodeId());
api.getVirtualMachineApi(resourceGroupName).stop(vmName);
checkState(nodeSuspendedPredicate.create(resourceGroupName).apply(vmName),
"Node %s was not suspended within the configured time limit", cloneTemplate.getSourceNodeId());
return userExecutor.submit(new Callable<Image>() {
@Override
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)
.createOrUpdate(cloneTemplate.getName(), regionAndId.region(),
.createOrUpdate(cloneTemplate.getName(), vm.location(),
ImageProperties.builder().sourceVirtualMachine(vmIdRef).build());
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");
logger.debug(">> deleting image %s", id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(image.location());
URI uri = api.getVirtualMachineImageApi(resourceGroup.name()).delete(image.name());
URI uri = api.getVirtualMachineImageApi(image.resourceGroup()).delete(image.name());
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.notNull;
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.transform;
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.util.ArrayList;
@ -36,6 +36,7 @@ import javax.inject.Named;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.SecurityGroupAvailablePredicateFactory;
import org.jclouds.azurecompute.arm.compute.domain.ResourceGroupAndName;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
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.Direction;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
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.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
@ -78,64 +74,67 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
private final AzureComputeApi api;
private final Function<NetworkSecurityGroup, SecurityGroup> securityGroupConverter;
private final Supplier<Set<? extends Location>> locations;
private final SecurityGroupAvailablePredicateFactory securityGroupAvailable;
private final Predicate<URI> resourceDeleted;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final LoadingCache<String, ResourceGroup> defaultResourceGroup;
@Inject
AzureComputeSecurityGroupExtension(AzureComputeApi api, @Memoized Supplier<Set<? extends Location>> locations,
AzureComputeSecurityGroupExtension(AzureComputeApi api,
Function<NetworkSecurityGroup, SecurityGroup> groupConverter,
SecurityGroupAvailablePredicateFactory securityRuleAvailable,
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
LoadingCache<String, ResourceGroup> resourceGroupMap) {
LoadingCache<String, ResourceGroup> defaultResourceGroup) {
this.api = api;
this.locations = locations;
this.securityGroupConverter = groupConverter;
this.securityGroupAvailable = securityRuleAvailable;
this.resourceDeleted = resourceDeleted;
this.resourceGroupMap = resourceGroupMap;
this.defaultResourceGroup = defaultResourceGroup;
}
@Override
public Set<SecurityGroup> listSecurityGroups() {
return ImmutableSet.copyOf(concat(transform(locations.get(), new Function<Location, Set<SecurityGroup>>() {
@Override
public Set<SecurityGroup> apply(Location input) {
return listSecurityGroupsInLocation(input);
}
})));
ImmutableSet.Builder<SecurityGroup> securityGroups = ImmutableSet.builder();
for (ResourceGroup rg : api.getResourceGroupApi().list()) {
securityGroups.addAll(securityGroupsInResourceGroup(rg.name()));
}
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
public Set<SecurityGroup> listSecurityGroupsInLocation(Location location) {
logger.debug(">> getting security groups for %s...", location);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location.getId());
List<NetworkSecurityGroup> networkGroups = api.getNetworkSecurityGroupApi(resourceGroup.name()).list();
return ImmutableSet.copyOf(transform(filter(networkGroups, notNull()), securityGroupConverter));
// Even though the resource groups are in a location, each security group
// can be in a different resource group, so we need to inspect all teh
// existing resource groups, and filter afterwards
return ImmutableSet.copyOf(filter(listSecurityGroups(), locationId(location.getId())));
}
@Override
public Set<SecurityGroup> listSecurityGroupsForNode(String nodeId) {
logger.debug(">> getting security groups for node %s...", nodeId);
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(nodeId);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(nodeId);
VirtualMachine vm = api.getVirtualMachineApi(resourceGroup.name()).get(regionAndId.id());
VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
resourceGroupAndName.name());
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<NetworkSecurityGroup> networkGroups = new ArrayList<NetworkSecurityGroup>();
for (IdReference networkInterfaceCardIdReference : networkInterfacesIdReferences) {
String nicName = Iterables.getLast(Splitter.on("/").split(networkInterfaceCardIdReference.id()));
NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(resourceGroup.name()).get(nicName);
String nicName = networkInterfaceCardIdReference.name();
String nicResourceGroup = networkInterfaceCardIdReference.resourceGroup();
NetworkInterfaceCard card = api.getNetworkInterfaceCardApi(nicResourceGroup).get(nicName);
if (card != null && card.properties().networkSecurityGroup() != null) {
String secGroupName = Iterables.getLast(Splitter.on("/").split(
card.properties().networkSecurityGroup().id()));
NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(secGroupName);
String secGroupName = card.properties().networkSecurityGroup().name();
String sgResourceGroup = card.properties().networkSecurityGroup().resourceGroup();
NetworkSecurityGroup group = api.getNetworkSecurityGroupApi(sgResourceGroup).get(secGroupName);
networkGroups.add(group);
}
}
@ -146,15 +145,15 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
@Override
public SecurityGroup getSecurityGroupById(String id) {
logger.debug(">> getting security group %s...", id);
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup.name()).get(regionAndId.id());
final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup()).get(
resourceGroupAndName.name());
return securityGroup == null ? null : securityGroupConverter.apply(securityGroup);
}
@Override
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);
@ -170,9 +169,9 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
public boolean removeSecurityGroup(String id) {
logger.debug(">> deleting security group %s...", id);
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
URI uri = api.getNetworkSecurityGroupApi(resourceGroup.name()).delete(regionAndId.id());
final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
URI uri = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup())
.delete(resourceGroupAndName.name());
return resourceDeleted.apply(uri);
}
@ -199,17 +198,16 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
// TODO: Support Azure network tags somehow?
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(group.getId());
NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name());
NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id());
NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup());
NetworkSecurityGroup networkSecurityGroup = groupApi.get(resourceGroupAndName.name());
if (networkSecurityGroup == null) {
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);
for (String ipRange : ipRanges) {
@ -228,7 +226,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
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");
}
@ -244,17 +243,17 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
logger.debug(">> deleting ip permissions matching [%s] from %s...", ruleName, group.getName());
final RegionAndId regionAndId = RegionAndId.fromSlashEncoded(group.getId());
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
final ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(group.getId());
NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroup.name());
NetworkSecurityGroup networkSecurityGroup = groupApi.get(regionAndId.id());
NetworkSecurityGroupApi groupApi = api.getNetworkSecurityGroupApi(resourceGroupAndName.resourceGroup());
NetworkSecurityGroup networkSecurityGroup = groupApi.get(resourceGroupAndName.name());
if (networkSecurityGroup == null) {
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>() {
@Override
public boolean apply(NetworkSecurityRule input) {
@ -270,7 +269,8 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio
for (NetworkSecurityRule matchingRule : rules) {
logger.debug(">> deleting network security rule %s from %s...", matchingRule.name(), group.getName());
ruleApi.delete(matchingRule.name());
checkState(securityGroupAvailable.create(resourceGroup.name()).apply(networkSecurityGroup.name()),
checkState(
securityGroupAvailable.create(resourceGroupAndName.resourceGroup()).apply(networkSecurityGroup.name()),
"Security group was not updated in the configured timeout");
}

View File

@ -16,6 +16,8 @@
*/
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.VMImage;
@ -25,7 +27,7 @@ public class CustomImageToVMImage implements Function<Image, VMImage> {
@Override
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();
}
}

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.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.VirtualMachineToNodeMetadata.getLocation;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
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.NetworkSecurityRule;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.SecurityGroupBuilder;
@ -54,8 +55,8 @@ public class NetworkSecurityGroupToSecurityGroup implements Function<NetworkSecu
public SecurityGroup apply(NetworkSecurityGroup input) {
SecurityGroupBuilder builder = new SecurityGroupBuilder();
builder.id(RegionAndId.fromRegionAndId(input.location(), input.name()).slashEncode());
builder.providerId(input.properties().resourceGuid());
builder.id(fromResourceGroupAndName(extractResourceGroup(input.id()), input.name()).slashEncode());
builder.providerId(input.id());
builder.name(input.name());
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.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.cache.LoadingCache;
@Singleton
public class TemplateToAvailabilitySet implements Function<Template, AvailabilitySet> {
@ -46,12 +44,10 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
protected Logger logger = Logger.NULL;
private final AzureComputeApi api;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject
TemplateToAvailabilitySet(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) {
TemplateToAvailabilitySet(AzureComputeApi api) {
this.api = api;
this.resourceGroupMap = resourceGroupMap;
}
@Nullable
@ -62,7 +58,7 @@ public class TemplateToAvailabilitySet implements Function<Template, Availabilit
AvailabilitySet availabilitySet = null;
String location = input.getLocation().getId();
String resourceGroup = resourceGroupMap.getUnchecked(location).name();
String resourceGroup = options.getResourceGroup();
if (options.getAvailabilitySetName() != null) {
availabilitySet = api.getAvailabilitySetApi(resourceGroup).get(options.getAvailabilitySetName());

View File

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

View File

@ -16,6 +16,12 @@
*/
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.Set;
@ -40,11 +46,6 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
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> {
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,
ImageReference imageReference) {
return (globallyAvailable ? "global" : locationName) + "/" + imageReference.customImageId()
.substring(imageReference.customImageId().lastIndexOf("/") + 1);
return extractResourceGroup(imageReference.customImageId()) + "/" + (globallyAvailable ? "global" : locationName)
+ "/" + imageReference.customImageId().substring(imageReference.customImageId().lastIndexOf("/") + 1);
}
public static String encodeFieldsToUniqueId(VMImage imageReference) {
@ -74,7 +75,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
}
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) {
@ -82,10 +84,11 @@ public class VMImageToImage implements Function<VMImage, Image> {
String[] fields = checkNotNull(id, "id").split("/");
if (isCustom(id)) {
/* id fields indexes
0: imageReference.location + "/" +
1: imageReference.name
0: imageReference.resourceGroup
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 {
/* id fields indexes
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.collect.Iterables.find;
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.encodeFieldsToUniqueIdCustom;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
import static org.jclouds.location.predicates.LocationPredicates.idEquals;
@ -34,13 +37,12 @@ import javax.inject.Inject;
import javax.inject.Named;
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.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
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.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
@ -74,20 +73,18 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
private final GroupNamingConvention nodeNamingConvention;
private final Supplier<Set<? extends Location>> locations;
private final Supplier<Map<String, ? extends Hardware>> hardwares;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final ImageCacheSupplier imageCache;
private final VirtualMachineToStatus virtualMachineToStatus;
@Inject
VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
Supplier<Map<String, ? extends Hardware>> hardwares, @Memoized Supplier<Set<? extends Location>> locations,
Map<String, Credentials> credentialStore, LoadingCache<String, ResourceGroup> resourceGroupMap,
@Memoized Supplier<Set<? extends Image>> imageCache, VirtualMachineToStatus virtualMachineToStatus) {
Map<String, Credentials> credentialStore, @Memoized Supplier<Set<? extends Image>> imageCache,
VirtualMachineToStatus virtualMachineToStatus) {
this.api = api;
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.locations = locations;
this.hardwares = hardwares;
this.resourceGroupMap = resourceGroupMap;
this.virtualMachineToStatus = virtualMachineToStatus;
checkArgument(imageCache instanceof ImageCacheSupplier,
"This provider needs an instance of the ImageCacheSupplier");
@ -96,10 +93,9 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
@Override
public NodeMetadata apply(VirtualMachine virtualMachine) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location());
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.name(virtualMachine.name());
builder.hostname(virtualMachine.name());
@ -125,8 +121,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
String locationName = virtualMachine.location();
builder.location(getLocation(locations, locationName));
Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName,
resourceGroup.name());
Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName);
if (image.isPresent()) {
builder.imageId(image.get().getId());
@ -137,7 +132,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
virtualMachine.id(), virtualMachine.id());
}
builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize()));
builder.hardware(getHardware(fromLocationAndName(virtualMachine.location(), virtualMachine.properties()
.hardwareProfile().vmSize())));
return builder.build();
}
@ -158,12 +154,8 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
return privateIpAddresses;
}
private NetworkInterfaceCard getNetworkInterfaceCard(IdReference networkInterfaceCardIdReference) {
Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 2);
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 NetworkInterfaceCard getNetworkInterfaceCard(IdReference nic) {
return api.getNetworkInterfaceCardApi(nic.resourceGroup()).get(nic.name());
}
private Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
@ -172,11 +164,11 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
if (networkInterfaceCard != null && networkInterfaceCard.properties() != 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()) {
if (ipConfiguration.properties().publicIPAddress() != null) {
String publicIpId = ipConfiguration.properties().publicIPAddress().id();
PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(Iterables.getLast(Splitter.on("/").split(publicIpId)));
IdReference publicIpId = ipConfiguration.properties().publicIPAddress();
PublicIPAddress publicIp = api.getPublicIPAddressApi(resourceGroup).get(publicIpId.name());
if (publicIp != null && publicIp.properties().ipAddress() != null) {
publicIpAddresses.add(publicIp.properties().ipAddress());
}
@ -191,8 +183,7 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
return find(locations.get(), idEquals(nullToEmpty(locationName)), null);
}
protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName,
String azureGroup) {
protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
if (storageProfile.imageReference() != null) {
// FIXME check this condition
String imageId = storageProfile.imageReference().customImageId() != null ?
@ -205,11 +196,12 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
}
}
protected Hardware getHardware(final String vmSize) {
return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() {
protected Hardware getHardware(final LocationAndName hardwareId) {
final String slashEncoded = hardwareId.slashEncode();
return find(hardwares.get().values(), new Predicate<Hardware>() {
@Override
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;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.azurecompute.arm.domain.IdReference.extractResourceGroup;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
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.VirtualMachine;
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.Functions;
import com.google.common.base.Joiner;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
@Singleton
@ -80,17 +79,15 @@ public class VirtualMachineToStatus implements Function<VirtualMachine, StatusAn
NodeMetadata.Status.UNRECOGNIZED);
private final AzureComputeApi api;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject
VirtualMachineToStatus(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) {
VirtualMachineToStatus(AzureComputeApi api) {
this.api = api;
this.resourceGroupMap = resourceGroupMap;
}
@Override
public StatusAndBackendStatus apply(VirtualMachine virtualMachine) {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(virtualMachine.location());
String resourceGroup = extractResourceGroup(virtualMachine.id());
ProvisioningState provisioningState = virtualMachine.properties().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 the provisioning succeeded, we need to query the *real* status of
// the VM
VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup.name()).getInstanceDetails(
VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(resourceGroup).getInstanceDetails(
virtualMachine.name());
if (instanceDetails != null && instanceDetails.powerState() != null) {
status = POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState());

View File

@ -28,7 +28,7 @@ import javax.inject.Named;
import javax.inject.Singleton;
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.NetworkSecurityGroupProperties;
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.Direction;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties.Protocol;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@Singleton
public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndIdAndIngressRules, String> {
public class CreateSecurityGroupIfNeeded extends CacheLoader<ResourceGroupAndNameAndIngressRules, String> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final AzureComputeApi api;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
@Inject
CreateSecurityGroupIfNeeded(AzureComputeApi api, LoadingCache<String, ResourceGroup> resourceGroupMap) {
CreateSecurityGroupIfNeeded(AzureComputeApi api) {
this.api = api;
this.resourceGroupMap = resourceGroupMap;
}
@Override
public String load(RegionAndIdAndIngressRules key) throws Exception {
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(key.region());
return createSecurityGroup(key.region(), resourceGroup.name(), key.id(), key.inboundPorts());
public String load(ResourceGroupAndNameAndIngressRules key) throws Exception {
return createSecurityGroup(key.location(), key.resourceGroup(), key.name(), key.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;
@Singleton
public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup> {
public class DefaultResourceGroup extends CacheLoader<String, ResourceGroup> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@ -43,7 +43,7 @@ public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup>
private final LocationToResourceGroupName locationToResourceGroupName;
@Inject
ResourceGroupForLocation(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) {
DefaultResourceGroup(AzureComputeApi api, LocationToResourceGroupName locationToResourceGroupName) {
this.api = api.getResourceGroupApi();
this.locationToResourceGroupName = locationToResourceGroupName;
}
@ -54,7 +54,7 @@ public class ResourceGroupForLocation extends CacheLoader<String, ResourceGroup>
ResourceGroup resourceGroup = api.get(azureGroupName);
if (resourceGroup == null) {
logger.debug(">> creating resource group %s", azureGroupName);
final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs");
final Map<String, String> tags = ImmutableMap.of("description", "jclouds default resource group");
resourceGroup = api.create(azureGroupName, locationId, tags);
}
return resourceGroup;

View File

@ -34,10 +34,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
private String virtualNetworkName;
private String subnetId;
private String blob;
private AvailabilitySet availabilitySet;
private String availabilitySetName;
private List<DataDisk> dataDisks = ImmutableList.of();
private String resourceGroup;
/**
* Sets the virtual network name
@ -54,14 +54,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
this.subnetId = subnetId;
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
@ -80,6 +72,14 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
this.availabilitySetName = availabilitySetName;
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) {
for (DataDisk dataDisk : checkNotNull(dataDisks, "dataDisks"))
@ -94,12 +94,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
public String getVirtualNetworkName() { return virtualNetworkName; }
public String getSubnetId() { return subnetId; }
public String getBlob() { return blob; }
public AvailabilitySet getAvailabilitySet() { return availabilitySet; }
public String getAvailabilitySetName() { return availabilitySetName; }
public List<DataDisk> getDataDisks() {
return dataDisks;
}
public List<DataDisk> getDataDisks() { return dataDisks; }
public String getResourceGroup() { return resourceGroup; }
@Override
public AzureTemplateOptions clone() {
@ -115,10 +113,10 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to);
eTo.virtualNetworkName(virtualNetworkName);
eTo.subnetId(subnetId);
eTo.blob(blob);
eTo.availabilitySet(availabilitySet);
eTo.availabilitySet(availabilitySetName);
eTo.dataDisks(dataDisks);
eTo.resourceGroup(resourceGroup);
}
}
@ -129,28 +127,19 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
if (!super.equals(o)) return false;
AzureTemplateOptions that = (AzureTemplateOptions) o;
if (virtualNetworkName != null ? !virtualNetworkName.equals(that.virtualNetworkName) : that.virtualNetworkName != null)
return false;
if (subnetId != null ? !subnetId.equals(that.subnetId) : that.subnetId != null) return false;
if (blob != null ? !blob.equals(that.blob) : that.blob != null) return false;
if (availabilitySet != null ? !availabilitySet.equals(that.availabilitySet) : that.availabilitySet != null)
return false;
if (availabilitySetName != null ? !availabilitySetName.equals(that.availabilitySetName) : that.availabilitySetName != null)
return false;
return dataDisks != null ? dataDisks.equals(that.dataDisks) : that.dataDisks == null;
return Objects.equal(virtualNetworkName, that.virtualNetworkName) &&
Objects.equal(subnetId, that.subnetId) &&
Objects.equal(availabilitySet, that.availabilitySet) &&
Objects.equal(availabilitySetName, that.availabilitySetName) &&
Objects.equal(dataDisks, that.dataDisks) &&
Objects.equal(resourceGroup, that.resourceGroup);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (virtualNetworkName != null ? virtualNetworkName.hashCode() : 0);
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;
return Objects.hashCode(virtualNetworkName, subnetId, availabilitySet, availabilitySetName, dataDisks,
resourceGroup);
}
@Override
@ -160,14 +149,14 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
toString.add("virtualNetworkName", virtualNetworkName);
if (subnetId != null)
toString.add("subnetId", subnetId);
if (blob != null)
toString.add("blob", blob);
if (availabilitySet != null)
toString.add("availabilitySet", availabilitySet);
if (availabilitySetName != null)
toString.add("availabilitySetName", availabilitySetName);
if (!dataDisks.isEmpty())
toString.add("dataDisks", dataDisks);
if (resourceGroup != null)
toString.add("resourceGroup", resourceGroup);
return toString;
}
@ -188,14 +177,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
AzureTemplateOptions options = new AzureTemplateOptions();
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)
@ -214,16 +195,27 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
}
/**
* @see AzureTemplateOptions#dataDisks
* @see AzureTemplateOptions#dataDisks(DataDisk...)
*/
public static AzureTemplateOptions dataDisks(DataDisk... dataDisks) {
AzureTemplateOptions options = new AzureTemplateOptions();
return options.dataDisks(dataDisks);
}
/**
* @see AzureTemplateOptions#dataDisks(Iterable)
*/
public static AzureTemplateOptions dataDisks(Iterable<DataDisk> dataDisks) {
AzureTemplateOptions options = new AzureTemplateOptions();
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 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.IdReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
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.Predicate;
import com.google.common.base.Splitter;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@Singleton
public class CleanupResources {
@ -59,52 +54,55 @@ public class CleanupResources {
private final AzureComputeApi api;
private final Predicate<URI> resourceDeleted;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final GroupNamingConvention.Factory namingConvention;
@Inject
CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
LoadingCache<String, ResourceGroup> resourceGroupMap, GroupNamingConvention.Factory namingConvention) {
GroupNamingConvention.Factory namingConvention) {
this.api = azureComputeApi;
this.resourceDeleted = resourceDeleted;
this.resourceGroupMap = resourceGroupMap;
this.namingConvention = namingConvention;
}
public boolean cleanupNode(final String id) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(regionAndId.region());
String resourceGroupName = resourceGroup.name();
ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(id);
String resourceGroupName = resourceGroupAndName.resourceGroup();
VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
VirtualMachine virtualMachine = api.getVirtualMachineApi(resourceGroupName).get(resourceGroupAndName.name());
if (virtualMachine == null) {
return true;
}
logger.debug(">> destroying %s ...", regionAndId.slashEncode());
logger.debug(">> destroying %s ...", id);
boolean vmDeleted = deleteVirtualMachine(resourceGroupName, virtualMachine);
// We don't delete the network here, as it is global to the resource
// group. It will be deleted when the resource group is deleted
cleanupVirtualMachineNICs(resourceGroupName, virtualMachine);
cleanupAvailabilitySetIfOrphaned(resourceGroupName, virtualMachine);
cleanupVirtualMachineNICs(virtualMachine);
cleanupAvailabilitySetIfOrphaned(virtualMachine);
return vmDeleted;
}
public void cleanupVirtualMachineNICs(String group, VirtualMachine virtualMachine) {
for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) {
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName);
Iterable<String> publicIps = getPublicIps(group, nic);
public void cleanupVirtualMachineNICs(VirtualMachine virtualMachine) {
for (IdReference nicRef : virtualMachine.properties().networkProfile().networkInterfaces()) {
String nicResourceGroup = nicRef.resourceGroup();
String nicName = nicRef.name();
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(nicRef.resourceGroup()).get(nicName);
Iterable<IdReference> publicIps = getPublicIps(nic);
logger.debug(">> destroying nic %s...", nicName);
URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName);
URI nicDeletionURI = api.getNetworkInterfaceCardApi(nicResourceGroup).delete(nicName);
resourceDeleted.apply(nicDeletionURI);
for (String publicIp : publicIps) {
logger.debug(">> deleting public ip nic %s...", publicIp);
api.getPublicIPAddressApi(group).delete(publicIp);
for (IdReference publicIp : publicIps) {
String publicIpResourceGroup = publicIp.resourceGroup();
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;
}
public boolean cleanupAvailabilitySetIfOrphaned(String resourceGroup, VirtualMachine virtualMachine) {
public boolean cleanupAvailabilitySetIfOrphaned(VirtualMachine virtualMachine) {
boolean deleted = false;
IdReference availabilitySetRef = virtualMachine.properties().availabilitySet();
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);
if (isOrphanedJcloudsAvailabilitySet(availabilitySet)) {
@ -162,19 +161,13 @@ public class CleanupResources {
return deleted;
}
private Iterable<String> getPublicIps(String group, NetworkInterfaceCard nic) {
return transform(
filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
@Override
public IdReference apply(IpConfiguration input) {
return input.properties().publicIPAddress();
}
}), notNull()), new Function<IdReference, String>() {
@Override
public String apply(IdReference input) {
return Iterables.getLast(Splitter.on("/").split(input.id()));
}
});
private Iterable<IdReference> getPublicIps(NetworkInterfaceCard nic) {
return filter(transform(nic.properties().ipConfigurations(), new Function<IpConfiguration, IdReference>() {
@Override
public IdReference apply(IpConfiguration input) {
return input.properties().publicIPAddress();
}
}), notNull());
}
private static boolean isOrphanedJcloudsAvailabilitySet(AvailabilitySet availabilitySet) {
@ -187,14 +180,6 @@ public class CleanupResources {
.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) {
return resourceDeleted.apply(api.getVirtualMachineApi(group).delete(virtualMachine.name()));
}

View File

@ -16,6 +16,12 @@
*/
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.Map;
import java.util.Set;
@ -27,12 +33,12 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
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.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet;
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.Subnet;
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.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
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.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
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
public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final AzureComputeApi api;
private final LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap;
private final LoadingCache<String, ResourceGroup> resourceGroupMap;
private final LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap;
private final String defaultVnetAddressPrefix;
private final String defaultSubnetAddressPrefix;
private final TemplateToAvailabilitySet templateToAvailabilitySet;
@Inject
protected CreateResourceGroupThenCreateNodes(
protected CreateResourcesThenCreateNodes(
CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention,
@ -86,15 +85,13 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
AzureComputeApi api, @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) String defaultVnetAddressPrefix,
@Named(DEFAULT_SUBNET_ADDRESS_PREFIX) String defaultSubnetAddressPrefix,
LoadingCache<RegionAndIdAndIngressRules, String> securityGroupMap,
LoadingCache<String, ResourceGroup> resourceGroupMap,
LoadingCache<ResourceGroupAndNameAndIngressRules, String> securityGroupMap,
TemplateToAvailabilitySet templateToAvailabilitySet) {
super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.api = checkNotNull(api, "api cannot be null");
checkNotNull(userExecutor, "userExecutor cannot be null");
this.securityGroupMap = securityGroupMap;
this.resourceGroupMap = resourceGroupMap;
this.defaultVnetAddressPrefix = defaultVnetAddressPrefix;
this.defaultSubnetAddressPrefix = defaultSubnetAddressPrefix;
this.templateToAvailabilitySet = templateToAvailabilitySet;
@ -117,24 +114,22 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
// This sill create the resource group if it does not exist
String location = template.getLocation().getId();
ResourceGroup resourceGroup = resourceGroupMap.getUnchecked(location);
String azureGroupName = resourceGroup.name();
getOrCreateVirtualNetworkWithSubnet(location, options, azureGroupName);
configureSecurityGroupForOptions(group, azureGroupName, template.getLocation(), options);
createResourceGroupIfNeeded(group, location, options);
getOrCreateVirtualNetworkWithSubnet(location, options);
configureSecurityGroupForOptions(group, template.getLocation(), options);
configureAvailabilitySetForTemplate(template);
return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
}
protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options,
final String azureGroupName) {
protected synchronized void getOrCreateVirtualNetworkWithSubnet(final String location, AzureTemplateOptions options) {
String virtualNetworkName = Optional.fromNullable(options.getVirtualNetworkName()).or(
azureGroupName + "virtualnetwork");
String subnetName = azureGroupName + "subnet";
options.getResourceGroup() + "virtualnetwork");
String subnetName = options.getResourceGroup() + "subnet";
// 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);
if (vn == null) {
@ -148,7 +143,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
}
SubnetApi subnetApi = api.getSubnetApi(azureGroupName, virtualNetworkName);
SubnetApi subnetApi = api.getSubnetApi(options.getResourceGroup(), virtualNetworkName);
Subnet subnet = subnetApi.get(subnetName);
options.virtualNetworkName(virtualNetworkName);
@ -160,23 +155,21 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
&& !template.getOptions().hasLoginPrivateKeyOption();
}
private void configureSecurityGroupForOptions(String group, String resourceGroup, Location location,
TemplateOptions options) {
private void configureSecurityGroupForOptions(String group, Location location, AzureTemplateOptions options) {
checkArgument(options.getGroups().size() <= 1,
"Only one security group can be configured for each network interface");
if (!options.getGroups().isEmpty()) {
String groupName = getOnlyElement(options.getGroups());
String groupNameWithourRegion = groupName.indexOf('/') == -1 ? groupName : RegionAndId.fromSlashEncoded(
groupName).id();
NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(resourceGroup).get(groupNameWithourRegion);
checkArgument(securityGroup != null, "Security group %s was not found", groupName);
ResourceGroupAndName securityGroupId = ResourceGroupAndName.fromSlashEncoded(getOnlyElement(options.getGroups()));
NetworkSecurityGroup securityGroup = api.getNetworkSecurityGroupApi(securityGroupId.resourceGroup()).get(
securityGroupId.name());
checkArgument(securityGroup != null, "Security group %s was not found", securityGroupId.slashEncode());
options.securityGroups(securityGroup.id());
} else if (options.getInboundPorts().length > 0) {
String name = namingConvention.create().sharedNameForGroup(group);
RegionAndIdAndIngressRules regionAndIdAndIngressRules = RegionAndIdAndIngressRules.create(location.getId(),
name, options.getInboundPorts());
ResourceGroupAndNameAndIngressRules regionAndIdAndIngressRules = ResourceGroupAndNameAndIngressRules.create(
options.getResourceGroup(), location.getId(), name, options.getInboundPorts());
// this will create if not yet exists.
String securityGroupId = securityGroupMap.getUnchecked(regionAndIdAndIngressRules);
options.securityGroups(securityGroupId);
@ -190,4 +183,17 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
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;
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.json.SerializedNames;
import com.google.auto.value.AutoValue;
// Simple helper class to serialize / deserialize id reference.
@AutoValue
public abstract class IdReference {
private static final Pattern RESOURCE_GROUP_PATTERN = Pattern.compile("^.*/resourceGroups/([^/]+)(/.*)?$");
@Nullable
public abstract String id();
@Nullable
public String resourceGroup() {
return extractResourceGroup(id());
}
@Nullable
public String name() {
return extractName(id());
}
@SerializedNames({"id"})
public static IdReference create(final String 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();
/**
* Specifies if this HW is globally available
*/
public abstract boolean globallyAvailable();
@SerializedNames({ "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) {
@SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location", "globallyAvailable"})
public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location, boolean globallyAvailable) {
return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location, globallyAvailable);
return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location);
}
}

View File

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

View File

@ -15,6 +15,7 @@
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import java.io.Closeable;
import java.net.URI;
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.
*/
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface JobApi extends Closeable {

View File

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

View File

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

View File

@ -16,7 +16,7 @@
*/
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.compute.options.RunScriptOptions.Builder.wrapInInitScript;
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.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.domain.ExecResponse;
@ -43,7 +42,6 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@ -56,30 +54,27 @@ import com.google.inject.name.Names;
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted;
private ResourceGroup testResourceGroup;
private String resourceGroupName;
public AzureComputeImageExtensionLiveTest() {
provider = "azurecompute-arm";
resourceGroupName = getClass().getSimpleName().toLowerCase();
}
@BeforeClass(groups = { "integration", "live" })
public void 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>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED)));
createResourceGroup();
createResourceGroup(resourceGroupName);
}
@AfterClass(groups = { "integration", "live" })
@Override
protected void tearDownContext() {
try {
URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
if (uri != null) {
assertTrue(resourceDeleted.apply(uri),
String.format("Resource %s was not terminated in the configured timeout", uri));
@ -108,7 +103,7 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
AzureLiveTestUtils.defaultProperties(properties);
setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
return properties;
}
@ -122,11 +117,12 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
public TemplateBuilder getNodeTemplate() {
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
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();
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.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.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.net.domain.IpProtocol.TCP;
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.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.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.SecurityGroup;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.BaseSecurityGroupExtensionLiveTest;
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.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
@ -64,23 +63,20 @@ import com.google.inject.name.Names;
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeSecurityGroupExtensionLiveTest")
public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGroupExtensionLiveTest {
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted;
private ResourceGroup testResourceGroup;
private String resourceGroupName;
public AzureComputeSecurityGroupExtensionLiveTest() {
provider = "azurecompute-arm";
resourceGroupName = "sgelivetest";
}
@BeforeClass(groups = { "integration", "live" })
public void 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>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED)));
createResourceGroup();
createResourceGroup(resourceGroupName);
}
@Test(groups = { "integration", "live" }, singleThreaded = true, dependsOnMethods = "testAddIpPermissionsFromSpec")
@ -104,7 +100,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
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 {
Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
@ -121,8 +118,8 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
Optional<SecurityGroupExtension> securityGroupExtension = computeService.getSecurityGroupExtension();
assertTrue(securityGroupExtension.isPresent(), "security group extension was not present");
NodeMetadata node = getOnlyElement(computeService
.createNodesInGroup(nodeGroup, 1, inboundPorts(22, 23, 24, 8000)));
NodeMetadata node = getOnlyElement(computeService.createNodesInGroup(nodeGroup, 1,
options().inboundPorts(22, 23, 24, 8000)));
try {
Set<SecurityGroup> groups = securityGroupExtension.get().listSecurityGroupsForNode(node.getId());
@ -141,7 +138,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
@Override
protected void tearDownContext() {
try {
URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(testResourceGroup.name());
URI uri = view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().delete(resourceGroupName);
if (uri != null) {
assertTrue(resourceDeleted.apply(uri),
String.format("Resource %s was not terminated in the configured timeout", uri));
@ -154,7 +151,7 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, "sgelivetest");
AzureLiveTestUtils.defaultProperties(properties);
setIfTestSystemPropertyPresent(properties, "oauth.endpoint");
return properties;
}
@ -163,9 +160,18 @@ public class AzureComputeSecurityGroupExtensionLiveTest extends BaseSecurityGrou
protected ProviderMetadata createProviderMetadata() {
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();
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.assertNull;
import static org.testng.Assert.assertTrue;
import static org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions.Builder.resourceGroup;
import java.net.URI;
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.Image;
import org.jclouds.azurecompute.arm.domain.ImageProperties;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.domain.Location;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.cache.LoadingCache;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
@ -54,11 +51,9 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
private static final String imageName = "imageFromRest";
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted;
private AzureComputeApi api;
private String resourceGroupName;
private String location;
private ImageApi imageApi;
private Image image;
@ -73,7 +68,7 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties;
}
@ -83,9 +78,6 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
super.initializeContext();
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED)));
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
api = view.unwrapApi(AzureComputeApi.class);
}
@ -94,10 +86,9 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
public void setupContext() {
super.setupContext();
// Use the resource name conventions used in the abstraction
ResourceGroup resourceGroup = createResourceGroup();
resourceGroupName = resourceGroup.name();
location = resourceGroup.location();
imageApi = api.getVirtualMachineImageApi(resourceGroupName);
location = view.getComputeService().templateBuilder().build().getLocation().getId();
view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
imageApi = api.getVirtualMachineImageApi(group);
}
@Override
@ -107,7 +98,7 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
view.getComputeService().destroyNodesMatching(inGroup(group));
} finally {
try {
URI uri = api.getResourceGroupApi().delete(resourceGroupName);
URI uri = api.getResourceGroupApi().delete(group);
assertResourceDeleted(uri);
} finally {
super.tearDownContext();
@ -122,11 +113,11 @@ public class ImageApiLiveTest extends BaseComputeServiceContextLiveTest {
@Test
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());
view.getComputeService().suspendNode(node.getId());
api.getVirtualMachineApi(resourceGroupName).generalize(node.getName());
api.getVirtualMachineApi(group).generalize(node.getName());
image = imageApi.createOrUpdate(imageName, location, ImageProperties.builder()
.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;
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.checkState;
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.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.domain.InboundNatRuleProperties.Protocol.Tcp;
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.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.AvailabilitySetProperties;
import org.jclouds.azurecompute.arm.domain.BackendAddressPool;
import org.jclouds.azurecompute.arm.domain.BackendAddressPoolProperties;
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.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.RegionAndId;
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.AvailabilitySet.AvailabilitySetProperties;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.domain.Location;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
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()
.toLowerCase(), System.getProperty("user.name"));
private LoadingCache<String, ResourceGroup> resourceGroupMap;
private Predicate<URI> resourceDeleted;
private PublicIpAvailablePredicateFactory publicIpAvailable;
private Predicate<Supplier<Provisionable>> resourceAvailable;
private AzureComputeApi api;
private String resourceGroupName;
private String location;
private LoadBalancerApi lbApi;
private NetworkInterfaceCardApi nicApi;
@ -116,7 +109,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
AzureLiveTestUtils.defaultProperties(properties, getClass().getSimpleName().toLowerCase());
AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties;
}
@ -126,9 +119,6 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
super.initializeContext();
resourceDeleted = context.utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
}, Names.named(TIMEOUT_RESOURCE_DELETED)));
resourceGroupMap = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<String, ResourceGroup>>() {
}));
publicIpAvailable = context.utils().injector().getInstance(PublicIpAvailablePredicateFactory.class);
resourceAvailable = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<Predicate<Supplier<Provisionable>>>() {
@ -142,11 +132,10 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
super.setupContext();
// Use the resource name conventions used in the abstraction so the nodes
// can see the load balancer
ResourceGroup resourceGroup = createResourceGroup();
resourceGroupName = resourceGroup.name();
location = resourceGroup.location();
lbApi = api.getLoadBalancerApi(resourceGroupName);
nicApi = api.getNetworkInterfaceCardApi(resourceGroupName);
location = view.getComputeService().templateBuilder().build().getLocation().getId();
view.unwrapApi(AzureComputeApi.class).getResourceGroupApi().create(group, location, null);
lbApi = api.getLoadBalancerApi(group);
nicApi = api.getNetworkInterfaceCardApi(group);
}
@Override
@ -156,7 +145,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
view.getComputeService().destroyNodesMatching(inGroup(group));
} finally {
try {
URI uri = api.getResourceGroupApi().delete(resourceGroupName);
URI uri = api.getResourceGroupApi().delete(group);
assertResourceDeleted(uri);
} finally {
super.tearDownContext();
@ -316,7 +305,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
}
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);
if (publicIPAddress == null) {
@ -325,7 +314,7 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
.idleTimeoutInMinutes(4).build();
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");
}
@ -358,16 +347,16 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
.platformFaultDomainCount(count).build();
AvailabilitySet as = AvailabilitySet.managed().name(group).properties(props).build();
Set<? extends NodeMetadata> nodes = view.getComputeService()
.createNodesInGroup(group, count, availabilitySet(as));
Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(group, count,
availabilitySet(as).resourceGroup(this.group));
List<String> nicNames = new ArrayList<String>();
for (NodeMetadata node : nodes) {
RegionAndId regionAndId = RegionAndId.fromSlashEncoded(node.getId());
VirtualMachine vm = api.getVirtualMachineApi(resourceGroupName).get(regionAndId.id());
ResourceGroupAndName resourceGroupAndName = ResourceGroupAndName.fromSlashEncoded(node.getId());
VirtualMachine vm = api.getVirtualMachineApi(resourceGroupAndName.resourceGroup()).get(
resourceGroupAndName.name());
String nicName = getLast(Splitter.on("/").split(
vm.properties().networkProfile().networkInterfaces().get(0).id()));
String nicName = vm.properties().networkProfile().networkInterfaces().get(0).name();
nicNames.add(nicName);
}
@ -426,11 +415,6 @@ public class LoadBalancerApiLiveTest extends BaseComputeServiceContextLiveTest {
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) {
lbApi.createOrUpdate(name, location, null, props);
resourceAvailable.apply(new Supplier<Provisionable>() {

View File

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

View File

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