Refactored Azure ARM to not use Deployments

* Simplified ImageExtension
* Fixed access to deployed VMS
* Made api-version configurable for all apis"
* Fixed all feature live tests
* Fixed the AzureComputeServiceLiveTest
* Fixed the AzureTemplateBuilderLiveTest
* Fixed the AzureComputeImageExtensionLiveTest
This commit is contained in:
Andrea Turli 2016-09-28 18:20:26 +02:00 committed by Ignasi Barrera
parent 8df58654b8
commit cd16826dca
60 changed files with 1912 additions and 2635 deletions

View File

@ -32,8 +32,7 @@ azure ad app create --name <name> --password <password> --home-page <home-page>
# Create a Service Principal # Create a Service Principal
azure ad sp create <Application-id> azure ad sp create <Application-id>
# Output will include a value for `Object Id` # Output will include a value for `Object Id`, to be used in the next step
``` ```
Run the following commands to assign roles to the service principal Run the following commands to assign roles to the service principal
@ -58,7 +57,8 @@ mvn -Dtest=<name of the live test> \
-Dtest.azurecompute-arm.identity="<Application-id>" \ -Dtest.azurecompute-arm.identity="<Application-id>" \
-Dtest.azurecompute-arm.credential="<password>" \ -Dtest.azurecompute-arm.credential="<password>" \
-Dtest.azurecompute-arm.endpoint="https://management.azure.com/subscriptions/<Subscription-id>" \ -Dtest.azurecompute-arm.endpoint="https://management.azure.com/subscriptions/<Subscription-id>" \
-Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token" test -Dtest.oauth.endpoint="https://login.microsoftonline.com/<Tenant-id>/oauth2/token"
integration-test -Plive
``` ```

View File

@ -46,7 +46,7 @@
<dependency> <dependency>
<groupId>org.apache.jclouds</groupId> <groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId> <artifactId>jclouds-compute</artifactId>
<version>${project.parent.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.auto.service</groupId> <groupId>com.google.auto.service</groupId>
@ -76,11 +76,6 @@
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.jclouds</groupId> <groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId> <artifactId>jclouds-compute</artifactId>

View File

@ -16,28 +16,27 @@
*/ */
package org.jclouds.azurecompute.arm; package org.jclouds.azurecompute.arm;
import java.io.Closeable;
import javax.ws.rs.PathParam;
import org.jclouds.azurecompute.arm.features.DeploymentApi; import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.azurecompute.arm.features.JobApi; import org.jclouds.azurecompute.arm.features.JobApi;
import org.jclouds.azurecompute.arm.features.LocationApi; import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi; import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.OSImageApi; import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi; import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi; import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi; import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi; import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi; import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi; import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi; import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import com.google.inject.Provides;
import javax.ws.rs.PathParam;
import java.io.Closeable;
/** /**
* The Azure Resource Manager API is a REST API for managing your services and deployments. * The Azure Resource Manager API is a REST API for managing your services and deployments.
* <p> * <p>
@ -165,6 +164,4 @@ public interface AzureComputeApi extends Closeable {
@Delegate @Delegate
ResourceProviderApi getResourceProviderApi(); ResourceProviderApi getResourceProviderApi();
@Provides
DeploymentTemplateBuilder.Factory deploymentTemplateFactory();
} }

View File

@ -17,31 +17,47 @@
package org.jclouds.azurecompute.arm; package org.jclouds.azurecompute.arm;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_TIMEOUT;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_FORMAT;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_AUTHENTICATE_SUDO;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET; import static org.jclouds.oauth.v2.config.CredentialType.CLIENT_CREDENTIALS_SECRET;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.azurecompute.arm.domain.Region; import org.jclouds.azurecompute.arm.domain.Region;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata; import org.jclouds.providers.internal.BaseProviderMetadata;
import org.jclouds.compute.config.ComputeServiceProperties;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
@ -72,13 +88,37 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}"); properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
properties.put(RESOURCE, "https://management.azure.com/"); properties.put(RESOURCE, "https://management.azure.com/");
properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString()); properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup"); properties.put(RESOURCE_GROUP_NAME, "jclouds");
properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16"); properties.put(DEFAULT_VNET_ADDRESS_SPACE_PREFIX, "10.0.0.0/16");
properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24"); properties.put(DEFAULT_SUBNET_ADDRESS_PREFIX, "10.0.0.0/24");
properties.put(DEFAULT_DATADISKSIZE, "100"); properties.put(DEFAULT_DATADISKSIZE, "100");
properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat"); properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat");
properties.put(DEFAULT_IMAGE_LOGIN, "jclouds:Password1!"); // Default credentials for all images
properties.put(IMAGE_LOGIN_USER, "jclouds:Password12345!");
properties.put(IMAGE_AUTHENTICATE_SUDO, "true");
properties.put(TEMPLATE, "imageNameMatches=UbuntuServer,osVersionMatches=1[45]\\.[01][04]\\.[0-9]-LTS");
properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000); properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000);
// Api versions used in each API
properties.put(API_VERSION_PREFIX + DeploymentApi.class.getSimpleName(), "2016-02-01");
properties.put(API_VERSION_PREFIX + LocationApi.class.getSimpleName(), "2015-11-01");
properties.put(API_VERSION_PREFIX + NetworkInterfaceCardApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + NetworkSecurityGroupApi.class.getSimpleName(), "2016-03-30");
properties.put(API_VERSION_PREFIX + NetworkSecurityRuleApi.class.getSimpleName(), "2016-03-30");
properties.put(API_VERSION_PREFIX + OSImageApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + PublicIPAddressApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + ResourceGroupApi.class.getSimpleName(), "2015-01-01");
properties.put(API_VERSION_PREFIX + ResourceProviderApi.class.getSimpleName(), "2015-01-01");
properties.put(API_VERSION_PREFIX + StorageAccountApi.class.getSimpleName(), STORAGE_API_VERSION);
properties.put(API_VERSION_PREFIX + SubnetApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + VirtualNetworkApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + VMSizeApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + VirtualMachineApi.class.getSimpleName(), "2015-06-15");
properties.put(API_VERSION_PREFIX + "GetVirtualMachine", "2016-03-30");
properties.put(API_VERSION_PREFIX + "GetVirtualMachineInstance", "2016-03-30");
properties.put(API_VERSION_PREFIX + "CreateVirtualMachine", "2016-03-30");
properties.put(API_VERSION_PREFIX + "ListVirtualMachines", "2015-06-15");
properties.put(API_VERSION_PREFIX + "DeleteVirtualMachine", "2016-03-30");
return properties; return properties;
} }

View File

@ -17,164 +17,139 @@
package org.jclouds.azurecompute.arm.compute; package org.jclouds.azurecompute.arm.compute;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format; import static com.google.common.collect.Iterables.contains;
import static java.util.concurrent.TimeUnit.SECONDS; import static com.google.common.collect.Iterables.filter;
import static org.jclouds.util.Predicates2.retry; import static com.google.common.collect.Iterables.find;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueIdCustom;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import org.jclouds.azurecompute.arm.compute.functions.DeploymentToVMDeployment; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.compute.predicates.IsDeploymentInRegions; import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.Deployment; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.DeploymentBody; import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties; import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.Location; import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.Offer; import org.jclouds.azurecompute.arm.domain.Offer;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.domain.SKU; import org.jclouds.azurecompute.arm.domain.SKU;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.StorageService; import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.VMDeployment; import org.jclouds.azurecompute.arm.domain.StorageService.Status;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VMHardware; import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VMSize; import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.domain.Value;
import org.jclouds.azurecompute.arm.domain.Version; import org.jclouds.azurecompute.arm.domain.Version;
import org.jclouds.azurecompute.arm.features.DeploymentApi; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.features.OSImageApi; import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.functions.CleanupResources; import org.jclouds.azurecompute.arm.functions.CleanupResources;
import org.jclouds.azurecompute.arm.util.BlobHelper; import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.Region; import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.net.UrlEscapers;
/** /**
* Defines the connection between the {@link AzureComputeApi} implementation and the jclouds * Defines the connection between the {@link AzureComputeApi} implementation and the jclouds
* {@link org.jclouds.compute.ComputeService}. * {@link org.jclouds.compute.ComputeService}.
*/ */
@Singleton @Singleton
public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location> { public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location> {
private String azureGroup; private final String azureGroup;
protected final CleanupResources cleanupResources; private final CleanupResources cleanupResources;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
private Logger logger = Logger.NULL;
private final AzureComputeApi api; private final AzureComputeApi api;
private final AzureComputeConstants azureComputeConstants; private final AzureComputeConstants azureComputeConstants;
private final Supplier<Set<String>> regionIds; private final Supplier<Set<String>> regionIds;
private final IsDeploymentInRegions isDeploymentInRegions; private final Predicate<String> publicIpAvailable;
private final DeploymentToVMDeployment deploymentToVMDeployment;
@Inject @Inject
AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants, AzureComputeServiceAdapter(final AzureComputeApi api, final AzureComputeConstants azureComputeConstants,
CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds, CleanupResources cleanupResources, @Region Supplier<Set<String>> regionIds,
IsDeploymentInRegions isDeploymentInRegions, DeploymentToVMDeployment deploymentToVMDeployment) { @Named("PublicIpAvailable") Predicate<String> publicIpAvailable) {
this.api = api; this.api = api;
this.azureComputeConstants = azureComputeConstants; this.azureComputeConstants = azureComputeConstants;
this.azureGroup = azureComputeConstants.azureResourceGroup(); this.azureGroup = azureComputeConstants.azureResourceGroup();
logger.debug("AzureComputeServiceAdapter set azuregroup to: " + azureGroup);
this.cleanupResources = cleanupResources; this.cleanupResources = cleanupResources;
this.regionIds = regionIds; this.regionIds = regionIds;
this.isDeploymentInRegions = isDeploymentInRegions; this.publicIpAvailable = publicIpAvailable;
this.deploymentToVMDeployment = deploymentToVMDeployment;
} }
@Override @Override
public NodeAndInitialCredentials<VMDeployment> createNodeWithGroupEncodedIntoName( public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(
final String group, final String name, final Template template) { final String group, final String name, final Template template) {
DeploymentTemplateBuilder deploymentTemplateBuilder = api.deploymentTemplateFactory().create(group, name, template); AzureTemplateOptions templateOptions = template.getOptions().as(AzureTemplateOptions.class);
final String loginUser = DeploymentTemplateBuilder.getLoginUserUsername(); // TODO Store group apart from the name to be able to identify nodes with custom names in the configured group
final String loginPassword = DeploymentTemplateBuilder.getLoginPassword(); // TODO ARM specific options
// TODO user metadata and tags
// TODO network ids => create one nic in each network
// TODO inbound ports
DeploymentBody deploymentTemplateBody = deploymentTemplateBuilder.getDeploymentTemplate(); String locationName = template.getLocation().getId();
String subnetId = templateOptions.getSubnetId();
NetworkInterfaceCard nic = createNetworkInterfaceCard(subnetId, name, locationName);
StorageProfile storageProfile = createStorageProfile(name, template.getImage(), templateOptions.getBlob());
HardwareProfile hardwareProfile = HardwareProfile.builder().vmSize(template.getHardware().getId()).build();
OSProfile osProfile = createOsProfile(name, template);
NetworkProfile networkProfile = NetworkProfile.builder().networkInterfaces(ImmutableList.of(IdReference.create(nic.id()))).build();
VirtualMachineProperties virtualMachineProperties = VirtualMachineProperties.builder()
.licenseType(null) // TODO
.availabilitySet(null) // TODO
.hardwareProfile(hardwareProfile)
.storageProfile(storageProfile)
.osProfile(osProfile)
.networkProfile(networkProfile)
.build();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody); VirtualMachine virtualMachine = api.getVirtualMachineApi(azureGroup).create(name, template.getLocation().getId(), virtualMachineProperties);
final String deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplateBuilder.getDeploymentTemplateJson(properties)); // Safe to pass null credentials here, as jclouds will default populate the node with the default credentials from the image, or the ones in the options, if provided.
return new NodeAndInitialCredentials<VirtualMachine>(virtualMachine, name, null);
logger.debug("Deployment created with name: %s group: %s", name, group);
final Set<VMDeployment> deployments = Sets.newHashSet();
final DeploymentApi deploymentApi = api.getDeploymentApi(azureGroup);
if (!retry(new Predicate<String>() {
@Override
public boolean apply(final String name) {
Deployment deployment = deploymentApi.create(name, deploymentTemplate);
if (deployment != null) {
VMDeployment vmDeployment = VMDeployment.create(deployment);
deployments.add(vmDeployment);
} else {
logger.debug("Failed to create deployment!");
}
return !deployments.isEmpty();
}
}, azureComputeConstants.operationTimeout(), 1, SECONDS).apply(name)) {
final String illegalStateExceptionMessage = format("Deployment %s was not created within %sms so it will be destroyed.",
name, azureComputeConstants.operationTimeout());
logger.warn(illegalStateExceptionMessage);
destroyNode(name);
throw new IllegalStateException(illegalStateExceptionMessage);
}
final VMDeployment deployment = deployments.iterator().next();
NodeAndInitialCredentials<VMDeployment> credential;
if (template.getOptions().getPublicKey() != null){
String privateKey = template.getOptions().getPrivateKey();
credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name,
LoginCredentials.builder().user(loginUser).privateKey(privateKey).authenticateSudo(true).build());
} else {
credential = new NodeAndInitialCredentials<VMDeployment>(deployment, name,
LoginCredentials.builder().user(loginUser).password(loginPassword).authenticateSudo(true).build());
}
return credential;
} }
@Override @Override
public Iterable<VMHardware> listHardwareProfiles() { public Iterable<VMHardware> listHardwareProfiles() {
final List<VMHardware> hwProfiles = Lists.newArrayList(); final List<VMHardware> hwProfiles = Lists.newArrayList();
final List<String> locationIds = Lists.newArrayList(); for (Location location : listLocations()) {
Iterable<Location> locations = listLocations();
for (Location location : locations){
locationIds.add(location.name());
Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list(); Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
for (VMSize vmSize : vmSizes){ for (VMSize vmSize : vmSizes){
VMHardware hwProfile = VMHardware.create( VMHardware hwProfile = VMHardware.create(
vmSize.name(), vmSize.name(),
@ -188,22 +163,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
hwProfiles.add(hwProfile); hwProfiles.add(hwProfile);
} }
} }
checkAndSetHwAvailability(hwProfiles, Sets.newHashSet(locationIds));
return hwProfiles; return hwProfiles;
} }
private void checkAndSetHwAvailability(List<VMHardware> hwProfiles, Collection<String> locations) {
Multimap<String, String> hwMap = ArrayListMultimap.create();
for (VMHardware hw : hwProfiles) {
hwMap.put(hw.name(), hw.location());
}
/// TODO
// for (VMHardware hw : hwProfiles) {
// hw.globallyAvailable() = hwMap.get(hw.name()).containsAll(locations);
// }
}
private List<VMImage> getImagesFromPublisher(String publisherName, String location) { private List<VMImage> getImagesFromPublisher(String publisherName, String location) {
List<VMImage> osImagesRef = Lists.newArrayList(); List<VMImage> osImagesRef = Lists.newArrayList();
@ -216,7 +177,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
for (SKU sku : skuList) { for (SKU sku : skuList) {
Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name()); Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name());
for (Version version : versionList) { for (Version version : versionList) {
VMImage vmImage = VMImage.create(publisherName, offer.name(), sku.name(), version.name(), location); VMImage vmImage = VMImage.azureImage().publisher(publisherName).offer(offer.name()).sku(sku.name())
.version(version.name()).location(location).build();
osImagesRef.add(vmImage); osImagesRef.add(vmImage);
} }
} }
@ -235,7 +197,6 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
@Override @Override
public Iterable<VMImage> listImages() { public Iterable<VMImage> listImages() {
final List<VMImage> osImages = Lists.newArrayList(); final List<VMImage> osImages = Lists.newArrayList();
for (Location location : listLocations()){ for (Location location : listLocations()){
@ -245,24 +206,51 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
List<StorageService> storages = api.getStorageAccountApi(azureGroup).list(); List<StorageService> storages = api.getStorageAccountApi(azureGroup).list();
for (StorageService storage : storages) { for (StorageService storage : storages) {
String name = storage.name(); String name = storage.name();
StorageService storageService = api.getStorageAccountApi(azureGroup).get(name);
if (storageService != null
&& Status.Succeeded == storageService.storageServiceProperties().provisioningState()) {
String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1(); String key = api.getStorageAccountApi(azureGroup).getKeys(name).key1();
List<VMImage> images = BlobHelper.getImages("jclouds", azureGroup, storage.name(), key, BlobHelper blobHelper = new BlobHelper(storage.name(), key);
"custom", storage.location()); try {
List<VMImage> images = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
storage.location());
osImages.addAll(images); osImages.addAll(images);
} finally {
closeQuietly(blobHelper);
} }
}
}
return osImages; return osImages;
} }
@Override @Override
public VMImage getImage(final String id) { public VMImage getImage(final String id) {
VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id); VMImage image = decodeFieldsFromUniqueId(id);
if (image.custom()) { if (image.custom()) {
String key = api.getStorageAccountApi(azureGroup).getKeys(image.storage()).key1(); VMImage customImage = null;
if (BlobHelper.customImageExists(image.storage(), key)) StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(image.storage());
return image; if (keys == null) {
else // If the storage account for the image does not exist, it means the image was deleted
return null; return null;
}
BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
try {
if (blobHelper.customImageExists()) {
List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup,
CUSTOM_IMAGE_OFFER, image.location());
customImage = find(customImagesInStorage, new Predicate<VMImage>() {
@Override
public boolean apply(VMImage input) {
return id.equals(encodeFieldsToUniqueIdCustom(input));
}
}, null);
}
} finally {
closeQuietly(blobHelper);
}
return customImage;
} }
String location = image.location(); String location = image.location();
@ -273,7 +261,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
OSImageApi osImageApi = api.getOSImageApi(location); OSImageApi osImageApi = api.getOSImageApi(location);
List<Version> versions = osImageApi.listVersions(publisher, offer, sku); List<Version> versions = osImageApi.listVersions(publisher, offer, sku);
if (!versions.isEmpty()) { if (!versions.isEmpty()) {
return VMImage.create(publisher, offer, sku, versions.get(0).name(), location); return VMImage.azureImage().publisher(publisher).offer(offer).sku(sku).version(versions.get(0).name())
.location(location).build();
} }
return null; return null;
} }
@ -313,13 +302,8 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
} }
@Override @Override
public VMDeployment getNode(final String id) { public VirtualMachine getNode(final String id) {
Deployment deployment = api.getDeploymentApi(azureGroup).get(id); return api.getVirtualMachineApi(azureGroup).get(id);
if (deployment == null) return null;
if (isDeploymentInRegions.apply(deployment)) {
return deploymentToVMDeployment.apply(deployment);
}
return null;
} }
@Override @Override
@ -343,29 +327,99 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
} }
@Override @Override
public Iterable<VMDeployment> listNodes() { public Iterable<VirtualMachine> listNodes() {
return FluentIterable.from(api.getDeploymentApi(azureGroup).list()) return api.getVirtualMachineApi(azureGroup).list();
.filter(isDeploymentInRegions)
.filter(new Predicate<Deployment>() {
@Override
public boolean apply(Deployment deployment) {
Value storageAccountNameValue = deployment.properties().parameters().get("storageAccountName");
String storageAccountName = storageAccountNameValue.value();
String key = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName).key1();
return !BlobHelper.customImageExists(storageAccountName, key);
}
})
.transform(deploymentToVMDeployment)
.toList();
} }
@Override @Override
public Iterable<VMDeployment> listNodesByIds(final Iterable<String> ids) { public Iterable<VirtualMachine> listNodesByIds(final Iterable<String> ids) {
return Iterables.filter(listNodes(), new Predicate<VMDeployment>() { return filter(listNodes(), new Predicate<VirtualMachine>() {
@Override @Override
public boolean apply(final VMDeployment input) { public boolean apply(VirtualMachine virtualMachine) {
return Iterables.contains(ids, input.deployment().name()); return contains(ids, virtualMachine.id());
} }
}); });
} }
private OSProfile createOsProfile(String computerName, Template template) {
String defaultLoginUser = template.getImage().getDefaultCredentials().getUser();
String defaultLoginPassword = template.getImage().getDefaultCredentials().getOptionalPassword().get();
String adminUsername = Objects.firstNonNull(template.getOptions().getLoginUser(), defaultLoginUser);
String adminPassword = Objects.firstNonNull(template.getOptions().getLoginPassword(), defaultLoginPassword);
OSProfile.Builder builder = OSProfile.builder().adminUsername(adminUsername).computerName(computerName);
// prefer public key over password
if (template.getOptions().getPublicKey() != null) {
OSProfile.LinuxConfiguration linuxConfiguration = OSProfile.LinuxConfiguration.create("true",
OSProfile.LinuxConfiguration.SSH.create(ImmutableList.of(
OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
String.format("/home/%s/.ssh/authorized_keys", adminUsername),
template.getOptions().getPublicKey())
))
);
builder.linuxConfiguration(linuxConfiguration);
} else {
builder.adminPassword(adminPassword);
}
return builder.build();
}
private NetworkInterfaceCard createNetworkInterfaceCard(String subnetId, String name, String locationName) {
final PublicIPAddressApi ipApi = api.getPublicIPAddressApi(azureGroup);
PublicIPAddressProperties properties =
PublicIPAddressProperties.builder()
.publicIPAllocationMethod("Static")
.idleTimeoutInMinutes(4)
.build();
String publicIpAddressName = "public-address-" + name;
PublicIPAddress ip = ipApi.createOrUpdate(publicIpAddressName, locationName, ImmutableMap.of("jclouds", name), properties);
checkState(publicIpAvailable.apply(publicIpAddressName),
"Public IP was not provisioned in the configured timeout");
final NetworkInterfaceCardProperties networkInterfaceCardProperties =
NetworkInterfaceCardProperties.builder()
.ipConfigurations(ImmutableList.of(
IpConfiguration.builder()
.name("ipConfig-" + name)
.properties(IpConfigurationProperties.builder()
.privateIPAllocationMethod("Dynamic")
.publicIPAddress(IdReference.create(ip.id()))
.subnet(IdReference.create(subnetId))
.build())
.build()))
.build();
String networkInterfaceCardName = "jc-nic-" + name;
return api.getNetworkInterfaceCardApi(azureGroup).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, ImmutableMap.of("jclouds", name));
}
private StorageProfile createStorageProfile(String name, Image image, String blob) {
VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
ImageReference imageReference = null;
VHD sourceImage = null;
String osType = null;
if (!imageRef.custom()) {
imageReference = ImageReference.builder()
.publisher(image.getProviderId())
.offer(image.getName())
.sku(image.getVersion())
.version("latest")
.build();
} else {
sourceImage = VHD.create(image.getProviderId());
// TODO: read the ostype from the image blob
OsFamily osFamily = image.getOperatingSystem().getFamily();
osType = osFamily == OsFamily.WINDOWS ? "Windows" : "Linux";
}
VHD vhd = VHD.create(blob + "vhds/" + name + ".vhd");
OSDisk osDisk = OSDisk.create(osType, name, vhd, "ReadWrite", "FromImage", sourceImage);
return StorageProfile.create(imageReference, osDisk, ImmutableList.<DataDisk>of());
}
} }

View File

@ -16,55 +16,8 @@
*/ */
package org.jclouds.azurecompute.arm.compute.config; package org.jclouds.azurecompute.arm.compute.config;
import java.net.URI;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Named;
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.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata;
import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.strategy.AzurePopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.VMDeployment;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
@ -76,38 +29,87 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RUL
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TCP_RULE_REGEXP;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.util.Predicates2.retry; import static org.jclouds.util.Predicates2.retry;
public class AzureComputeServiceContextModule import java.net.URI;
extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> { import java.util.List;
@Resource import javax.inject.Named;
@Named(ComputeServiceConstants.COMPUTE_LOGGER) import javax.inject.Singleton;
protected Logger logger = Logger.NULL;
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.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
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.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
public class AzureComputeServiceContextModule
extends ComputeServiceAdapterContextModule<VirtualMachine, VMHardware, VMImage, Location> {
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VMDeployment, VMHardware, VMImage, Location>>() {
bind(new TypeLiteral<ComputeServiceAdapter<VirtualMachine, VMHardware, VMImage, Location>>() {
}).to(AzureComputeServiceAdapter.class); }).to(AzureComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VMImage, org.jclouds.compute.domain.Image>>() { bind(new TypeLiteral<Function<VMImage, org.jclouds.compute.domain.Image>>() {
}).to(VMImageToImage.class); }).to(VMImageToImage.class);
bind(new TypeLiteral<Function<VMHardware, Hardware>>() { bind(new TypeLiteral<Function<VMHardware, Hardware>>() {
}).to(VMHardwareToHardware.class); }).to(VMHardwareToHardware.class);
bind(new TypeLiteral<Function<VMDeployment, NodeMetadata>>() { bind(new TypeLiteral<Function<VirtualMachine, NodeMetadata>>() {
}).to(DeploymentToNodeMetadata.class); }).to(VirtualMachineToNodeMetadata.class);
bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() { bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() {
}).to(LocationToLocation.class); }).to(LocationToLocation.class);
bind(ComputeService.class).to(AzureComputeService.class); bind(ComputeService.class).to(AzureComputeService.class);
install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() {
install(new LocationsFromComputeServiceAdapterModule<VirtualMachine, VMHardware, VMImage, Location>() {
}); });
install(new FactoryModuleBuilder().build(ResourceDefinitionToCustomImage.Factory.class));
bind(TemplateOptions.class).to(AzureTemplateOptions.class); bind(TemplateOptions.class).to(AzureTemplateOptions.class);
bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(AzurePopulateDefaultLoginCredentialsForImageStrategy.class); bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
//bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class);
bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class); bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
bind(new TypeLiteral<ImageExtension>() { bind(new TypeLiteral<ImageExtension>() {
}).to(AzureComputeImageExtension.class); }).to(AzureComputeImageExtension.class);
} }
@ -143,10 +145,6 @@ public class AzureComputeServiceContextModule
@Inject @Inject
private String azureImagePublishersProperty; private String azureImagePublishersProperty;
@Named(DEFAULT_IMAGE_LOGIN)
@Inject
private String azureDefaultImageLoginProperty;
@Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX) @Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX)
@Inject @Inject
private String azureDefaultVnetAddressPrefixProperty; private String azureDefaultVnetAddressPrefixProperty;
@ -171,10 +169,6 @@ public class AzureComputeServiceContextModule
return azureImagePublishersProperty; return azureImagePublishersProperty;
} }
public String azureDefaultImageLogin() {
return azureDefaultImageLoginProperty;
}
public String azureDefaultVnetAddressPrefixProperty() { public String azureDefaultVnetAddressPrefixProperty() {
return azureDefaultVnetAddressPrefixProperty; return azureDefaultVnetAddressPrefixProperty;
} }
@ -204,6 +198,14 @@ public class AzureComputeServiceContextModule
} }
} }
@Provides
@com.google.inject.name.Named(TIMEOUT_NODE_RUNNING)
protected Predicate<String> provideVirtualMachineRunningPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, Timeouts timeouts, PollPeriod pollPeriod) {
String azureGroup = azureComputeConstants.azureResourceGroup();
return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.RUNNING), timeouts.nodeRunning,
pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
}
@Provides @Provides
@Named(TIMEOUT_NODE_TERMINATED) @Named(TIMEOUT_NODE_TERMINATED)
protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, Timeouts timeouts, PollPeriod pollPeriod) { protected Predicate<URI> provideNodeTerminatedPredicate(final AzureComputeApi api, Timeouts timeouts, PollPeriod pollPeriod) {
@ -230,7 +232,17 @@ public class AzureComputeServiceContextModule
protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
Timeouts timeouts, PollPeriod pollPeriod) { Timeouts timeouts, PollPeriod pollPeriod) {
String azureGroup = azureComputeConstants.azureResourceGroup(); String azureGroup = azureComputeConstants.azureResourceGroup();
return retry(new NodeSuspendedPredicate(api, azureGroup), timeouts.nodeSuspended, pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod); return retry(new VirtualMachineInStatePredicate(api, azureGroup, PowerState.STOPPED), timeouts.nodeTerminated,
pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
}
@Provides
@Named("PublicIpAvailable")
protected Predicate<String> providePublicIpAvailablePredicate(final AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
Timeouts timeouts, PollPeriod pollPeriod) {
String azureGroup = azureComputeConstants.azureResourceGroup();
return retry(new PublicIpAvailablePredicate(api, azureGroup), azureComputeConstants.operationTimeout(),
azureComputeConstants.operationPollInitialPeriod(), azureComputeConstants.operationPollMaxPeriod());
} }
@VisibleForTesting @VisibleForTesting
@ -269,12 +281,34 @@ public class AzureComputeServiceContextModule
} }
@VisibleForTesting @VisibleForTesting
static class NodeSuspendedPredicate implements Predicate<String> { static class VirtualMachineInStatePredicate implements Predicate<String> {
private final AzureComputeApi api;
private final String azureGroup;
private final PowerState powerState;
public VirtualMachineInStatePredicate(AzureComputeApi api, String azureGroup, PowerState powerState) {
this.api = checkNotNull(api, "api must not be null");
this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
this.powerState = checkNotNull(powerState, "powerState must not be null");
}
@Override
public boolean apply(String name) {
checkNotNull(name, "name cannot be null");
VirtualMachineInstance vmInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name);
if (vmInstance == null) return false;
return powerState == vmInstance.powerState();
}
}
@VisibleForTesting
static class PublicIpAvailablePredicate implements Predicate<String> {
private final AzureComputeApi api; private final AzureComputeApi api;
private final String azureGroup; private final String azureGroup;
public NodeSuspendedPredicate(AzureComputeApi api, String azureGroup) { public PublicIpAvailablePredicate(AzureComputeApi api, String azureGroup) {
this.api = checkNotNull(api, "api must not be null"); this.api = checkNotNull(api, "api must not be null");
this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null"); this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
} }
@ -282,17 +316,10 @@ public class AzureComputeServiceContextModule
@Override @Override
public boolean apply(String name) { public boolean apply(String name) {
checkNotNull(name, "name cannot be null"); checkNotNull(name, "name cannot be null");
String status = ""; PublicIPAddress publicIp = api.getPublicIPAddressApi(azureGroup).get(name);
VirtualMachineInstance virtualMachineInstance = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name); if (publicIp == null) return false;
if (virtualMachineInstance == null) return false; return publicIp.properties().provisioningState().equalsIgnoreCase("Succeeded");
List<VirtualMachineInstance.VirtualMachineStatus> statuses = virtualMachineInstance.statuses();
for (int c = 0; c < statuses.size(); c++) {
if (statuses.get(c).code().substring(0, 10).equals("PowerState")) {
status = statuses.get(c).displayStatus();
break;
}
}
return status.equals("VM stopped");
} }
} }
} }

View File

@ -16,141 +16,137 @@
*/ */
package org.jclouds.azurecompute.arm.compute.extensions; package org.jclouds.azurecompute.arm.compute.extensions;
import com.google.common.base.Predicate; import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.Supplier; import static com.google.common.base.Preconditions.checkState;
import com.google.common.util.concurrent.ListenableFuture; import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import com.google.common.util.concurrent.ListeningExecutorService; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import com.google.common.util.concurrent.UncheckedTimeoutException; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import com.google.gson.internal.LinkedTreeMap; import static org.jclouds.util.Closeables2.closeQuietly;
import com.google.inject.Inject;
import com.google.inject.name.Named; import java.net.URI;
import java.util.List;
import java.util.concurrent.Callable;
import javax.annotation.Resource;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.View;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage; import org.jclouds.azurecompute.arm.compute.functions.ResourceDefinitionToCustomImage;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition; import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.functions.CleanupResources;
import static java.lang.String.format;
import org.jclouds.azurecompute.arm.util.BlobHelper; import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.compute.domain.CloneImageTemplate; import org.jclouds.compute.domain.CloneImageTemplate;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageTemplate; import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.domain.ImageTemplateBuilder; import org.jclouds.compute.domain.ImageTemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension; import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
import com.google.inject.name.Named;
public class AzureComputeImageExtension implements ImageExtension { public class AzureComputeImageExtension implements ImageExtension {
public static final String CONTAINER_NAME = "jclouds";
public static final String CUSTOM_IMAGE_OFFER = "custom";
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final AzureComputeApi api; private final AzureComputeApi api;
private final ListeningExecutorService userExecutor;
private final Supplier<View> blobstore = null;
private final String group; private final String group;
private final ListeningExecutorService userExecutor;
private final Predicate<URI> imageAvailablePredicate; private final Predicate<URI> imageAvailablePredicate;
private final Predicate<String> nodeSuspendedPredicate; private final Predicate<String> nodeSuspendedPredicate;
private final AzureComputeConstants azureComputeConstants; private final ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage;
private final VMImageToImage imageReferenceToImage; private final CleanupResources cleanupResources;
public static final String CONTAINER_NAME = "jclouds";
public static final String CUSTOM_IMAGE_PREFIX = "#";
@Inject @Inject
AzureComputeImageExtension(AzureComputeApi api, AzureComputeImageExtension(AzureComputeApi api,
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate, @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate, @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate,
final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, AzureComputeConstants azureComputeConstants,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
VMImageToImage imageReferenceToImage) { ResourceDefinitionToCustomImage.Factory resourceDefinitionToImage, CleanupResources cleanupResources) {
this.userExecutor = userExecutor; this.api = api;
this.group = azureComputeConstants.azureResourceGroup();
this.imageReferenceToImage = imageReferenceToImage;
this.imageAvailablePredicate = imageAvailablePredicate; this.imageAvailablePredicate = imageAvailablePredicate;
this.nodeSuspendedPredicate = nodeSuspendedPredicate; this.nodeSuspendedPredicate = nodeSuspendedPredicate;
this.azureComputeConstants = azureComputeConstants; this.group = azureComputeConstants.azureResourceGroup();
this.api = api; this.userExecutor = userExecutor;
this.resourceDefinitionToImage = resourceDefinitionToImage;
this.cleanupResources = cleanupResources;
} }
@Override @Override
public ImageTemplate buildImageTemplateFromNode(String name, String id) { public ImageTemplate buildImageTemplateFromNode(String name, String id) {
String nameLowerCase = name.toLowerCase(); return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name.toLowerCase()).build();
return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(nameLowerCase).build();
} }
@Override @Override
public ListenableFuture<Image> createImage(ImageTemplate template) { public ListenableFuture<Image> createImage(ImageTemplate template) {
final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
final String id = cloneTemplate.getSourceNodeId(); final String id = cloneTemplate.getSourceNodeId();
final String name = cloneTemplate.getName(); final String name = cloneTemplate.getName();
final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
logger.debug(">> stopping node %s...", id);
api.getVirtualMachineApi(group).stop(id); api.getVirtualMachineApi(group).stop(id);
if (nodeSuspendedPredicate.apply(id)) { checkState(nodeSuspendedPredicate.apply(id), "Node %s was not suspended within the configured time limit", id);
return userExecutor.submit(new Callable<Image>() { return userExecutor.submit(new Callable<Image>() {
@Override @Override
public Image call() throws Exception { public Image call() throws Exception {
logger.debug(">> generalizing virtal machine %s...", id);
api.getVirtualMachineApi(group).generalize(id); api.getVirtualMachineApi(group).generalize(id);
final String[] disks = new String[2]; logger.debug(">> capturing virtual machine %s to container %s...", id, CONTAINER_NAME);
URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME); URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME);
if (uri != null) { checkState(uri != null && imageAvailablePredicate.apply(uri),
if (imageAvailablePredicate.apply(uri)) { "Image %s was not created within the configured time limit", cloneTemplate.getName());
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri); List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
if (definitions != null) { checkState(definitions.size() == 1,
for (ResourceDefinition definition : definitions) { "Expected one resource definition after creating the image but %s were returned", definitions.size());
LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties();
Object storageObject = properties.get("storageProfile");
LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject;
Object osDiskObject = properties2.get("osDisk");
LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject;
Object dataDisksObject = properties2.get("dataDisks");
ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject;
LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0);
disks[0] = osProperties.get("name"); Image image = resourceDefinitionToImage.create(id, name).apply(definitions.get(0));
disks[1] = datadiskObject.get("name"); logger.debug(">> created %s", image);
return image;
VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
final VMImage ref = VMImage.create(group, storageAccountName, disks[0], disks[1], name, "custom", vm.location());
return imageReferenceToImage.apply(ref);
}
}
}
}
throw new UncheckedTimeoutException("Image was not created within the time limit: "
+ cloneTemplate.getName());
} }
}); });
} else {
final String illegalStateExceptionMessage = format("Node %s was not suspended within %sms.",
id, azureComputeConstants.operationTimeout());
throw new IllegalStateException(illegalStateExceptionMessage);
}
} }
@Override @Override
public boolean deleteImage(String id) { public boolean deleteImage(String id) {
VMImage image = decodeFieldsFromUniqueId(id);
checkArgument(image.custom(), "Only custom images can be deleted");
logger.debug(">> deleting image %s", id);
VMImage image = VMImageToImage.decodeFieldsFromUniqueId(id);
if (image.custom()) {
StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage()); StorageServiceKeys keys = api.getStorageAccountApi(image.group()).getKeys(image.storage());
BlobHelper blobHelper = new BlobHelper(image.storage(), keys.key1());
// This removes now all the images in this storage. At least in theory, there should be just one and if there is try {
// This removes now all the images in this storage. At least in theory,
// there should be just one and if there is
// more, they should be copies of each other. // more, they should be copies of each other.
BlobHelper.deleteContainerIfExists(image.storage(), keys.key1(), "system"); blobHelper.deleteContainerIfExists("system");
return !BlobHelper.customImageExists(image.storage(), keys.key1()); boolean result = !blobHelper.customImageExists();
if (!blobHelper.hasContainers()) {
logger.debug(">> storage account is empty after deleting the custom image. Deleting the storage account...");
api.getStorageAccountApi(image.group()).delete(image.storage());
cleanupResources.deleteResourceGroupIfEmpty(image.group());
} }
return false; return result;
} finally {
closeQuietly(blobHelper);
}
} }
} }

View File

@ -1,244 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import com.google.common.collect.Sets;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.domain.ComputeNode;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.ImageReference;
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.VMDeployment;
import org.jclouds.azurecompute.arm.domain.VMHardware;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Hardware;
public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMetadata> {
public static final String JCLOUDS_DEFAULT_USERNAME = "root";
public static final String AZURE_LOGIN_USERNAME = DeploymentTemplateBuilder.getLoginUserUsername();
public static final String AZURE_LOGIN_PASSWORD = DeploymentTemplateBuilder.getLoginPassword();
private static final Map<ComputeNode.Status, NodeMetadata.Status> INSTANCESTATUS_TO_NODESTATUS =
ImmutableMap.<ComputeNode.Status, NodeMetadata.Status>builder().
put(ComputeNode.Status.GOOD, NodeMetadata.Status.RUNNING).
put(ComputeNode.Status.BAD, NodeMetadata.Status.ERROR).
put(ComputeNode.Status.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).
build();
// When using the Deployment API to deploy an ARM template, the deployment goes through
// stages. Accepted -> Running -> Succeeded. Only when the deployment has SUCCEEDED is
// the resource deployed using the template actually ready.
//
// To get details about the resource(s) deployed via template, one needs to query the
// various resources after the deployment has "SUCCEEDED".
private static final Map<Deployment.ProvisioningState, NodeMetadata.Status> STATUS_TO_NODESTATUS =
ImmutableMap.<Deployment.ProvisioningState, NodeMetadata.Status>builder().
put(Deployment.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING).
put(Deployment.ProvisioningState.READY, NodeMetadata.Status.PENDING).
put(Deployment.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING).
put(Deployment.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED).
put(Deployment.ProvisioningState.FAILED, NodeMetadata.Status.ERROR).
put(Deployment.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED).
put(Deployment.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING).
put(Deployment.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).
build();
public static Deployment.ProvisioningState provisioningStateFromString(final String text) {
return (Deployment.ProvisioningState) GetEnumValue.fromValueOrDefault(text, Deployment.ProvisioningState.UNRECOGNIZED);
}
private final AzureComputeApi api;
private final LocationToLocation locationToLocation;
private final GroupNamingConvention nodeNamingConvention;
private final VMImageToImage vmImageToImage;
private final VMHardwareToHardware vmHardwareToHardware;
private final Map<String, Credentials> credentialStore;
@Inject
DeploymentToNodeMetadata(
AzureComputeApi api,
LocationToLocation locationToLocation,
GroupNamingConvention.Factory namingConvention, VMImageToImage vmImageToImage,
VMHardwareToHardware vmHardwareToHardware, Map<String, Credentials> credentialStore) {
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.locationToLocation = locationToLocation;
this.vmImageToImage = vmImageToImage;
this.vmHardwareToHardware = vmHardwareToHardware;
this.credentialStore = credentialStore;
this.api = api;
}
@Override
public NodeMetadata apply(final VMDeployment from) {
final NodeMetadataBuilder builder = new NodeMetadataBuilder();
final Deployment deployment = from.deployment();
builder.id(deployment.name());
builder.providerId(deployment.name());
builder.name(deployment.name());
String group = this.nodeNamingConvention.extractGroup(deployment.name());
builder.group(group);
if (from.tags() != null)
builder.tags(from.tags());
if (from.userMetaData() != null)
builder.userMetadata(from.userMetaData());
NodeMetadata.Status status = STATUS_TO_NODESTATUS.get(provisioningStateFromString(deployment.properties().provisioningState()));
if (status == NodeMetadata.Status.RUNNING && from.vm() != null && from.vm().statuses() != null) {
List<VirtualMachineInstance.VirtualMachineStatus> statuses = from.vm().statuses();
for (int c = 0; c < statuses.size(); c++) {
if (statuses.get(c).code().substring(0, 10).equals("PowerState")) {
if (statuses.get(c).displayStatus().equals("VM running")) {
status = NodeMetadata.Status.RUNNING;
} else if (statuses.get(c).displayStatus().equals("VM stopped")) {
status = NodeMetadata.Status.SUSPENDED;
}
break;
}
}
}
builder.status(status);
if (from.vm() != null) {
builder.hostname(deployment.name() + "pc");
}
Credentials credentials = credentialStore.get("node#" + from.deployment().name());
if (credentials != null && credentials.identity.equals(JCLOUDS_DEFAULT_USERNAME)) {
credentials = new Credentials(AZURE_LOGIN_USERNAME, credentials.credential);
}
else if (credentials == null) {
String username = AZURE_LOGIN_USERNAME;
String password = AZURE_LOGIN_PASSWORD;
if (username == null) {
username = "jclouds";
}
if (password == null) {
password = "Password1!";
}
credentials = new Credentials(username, password);
}
builder.credentials(LoginCredentials.fromCredentials(credentials));
final Set<String> publicIpAddresses = Sets.newLinkedHashSet();
if (from.ipAddressList() != null) {
for (int c = 0; c < from.ipAddressList().size(); c++) {
PublicIPAddress ip = from.ipAddressList().get(c);
if (ip != null && ip.properties() != null && ip.properties().ipAddress() != null)
{
publicIpAddresses.add(ip.properties().ipAddress());
break;
}
}
if (publicIpAddresses.size() > 0)
builder.publicAddresses(publicIpAddresses);
}
final Set<String> privateIpAddresses = Sets.newLinkedHashSet();
if (from.networkInterfaceCards() != null) {
for (NetworkInterfaceCard nic : from.networkInterfaceCards()) {
if (nic != null && nic.properties() != null && nic.properties().ipConfigurations() != null) {
for (IpConfiguration ip : nic.properties().ipConfigurations()) {
if (ip != null && ip.properties() != null && ip.properties().privateIPAddress() != null) {
privateIpAddresses.add(ip.properties().privateIPAddress());
}
}
}
}
if (!privateIpAddresses.isEmpty()) {
builder.privateAddresses(privateIpAddresses);
}
}
org.jclouds.azurecompute.arm.domain.Location myLocation = null;
if (from.virtualMachine() != null) {
String locationName = from.virtualMachine().location();
List<org.jclouds.azurecompute.arm.domain.Location> locations = api.getLocationApi().list();
for (org.jclouds.azurecompute.arm.domain.Location location : locations) {
if (location.name().equals(locationName)) {
myLocation = location;
break;
}
}
Location jLocation = this.locationToLocation.apply(myLocation);
builder.location(jLocation);
ImageReference imageReference = from.virtualMachine().properties().storageProfile().imageReference();
if (imageReference != null) {
VMImage vmImage = VMImage.create(imageReference.publisher(), imageReference.offer(), imageReference.sku(),
imageReference.version(), locationName);
Image image = vmImageToImage.apply(vmImage);
builder.imageId(image.getId());
}
VMSize myVMSize = null;
String vmSizeName = from.virtualMachine().properties().hardwareProfile().vmSize();
List<VMSize> vmSizes = api.getVMSizeApi(locationName).list();
for (VMSize vmSize : vmSizes) {
if (vmSize.name().equals(vmSizeName)) {
myVMSize = vmSize;
break;
}
}
VMHardware hwProfile = VMHardware.create(
myVMSize.name(),
myVMSize.numberOfCores(),
myVMSize.osDiskSizeInMB(),
myVMSize.resourceDiskSizeInMB(),
myVMSize.memoryInMB(),
myVMSize.maxDataDiskCount(),
locationName,
false);
Hardware hardware = vmHardwareToHardware.apply(hwProfile);
builder.hardware(hardware);
}
return builder.build();
}
}

View File

@ -1,121 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.VMDeployment;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import com.google.common.base.Function;
/**
* Converts an Deployment into a VMDeployment.
*/
@Singleton
public class DeploymentToVMDeployment implements Function<Deployment, VMDeployment> {
private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
private final AzureComputeApi api;
@Inject
DeploymentToVMDeployment(AzureComputeApi api, final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
this.api = api;
this.azureComputeConstants = azureComputeConstants;
}
@Override
public VMDeployment apply(final Deployment deployment) {
String id = deployment.id();
List<PublicIPAddress> ipAddressList = getIPAddresses(deployment);
List<NetworkInterfaceCard> networkInterfaceCards = getNetworkInterfaceCards(deployment);
VirtualMachine vm = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).get(id);
VirtualMachineInstance vmInstanceDetails = api.getVirtualMachineApi(azureComputeConstants.azureResourceGroup()).getInstanceDetails(id);
Map<String, String> userMetaData = null;
Iterable<String> tags = null;
if (vm != null && vm.tags() != null) {
userMetaData = vm.tags();
String tagString = userMetaData.get("tags");
tags = Arrays.asList(tagString.split(","));
}
return VMDeployment.create(deployment, ipAddressList, vmInstanceDetails, vm, networkInterfaceCards, userMetaData, tags);
}
private List<PublicIPAddress> getIPAddresses(Deployment deployment) {
List<PublicIPAddress> list = new ArrayList<PublicIPAddress>();
String resourceGroup = getResourceGroupFromId(deployment.id());
if (deployment.properties() != null && deployment.properties().dependencies() != null) {
List<Deployment.Dependency> dependencies = deployment.properties().dependencies();
for (int d = 0; d < dependencies.size(); d++) {
if (dependencies.get(d).resourceType().equals("Microsoft.Network/networkInterfaces")) {
List<Deployment.Dependency> dependsOn = dependencies.get(d).dependsOn();
for (int e = 0; e < dependsOn.size(); e++) {
if (dependsOn.get(e).resourceType().equals("Microsoft.Network/publicIPAddresses")) {
String resourceName = dependsOn.get(e).resourceName();
PublicIPAddress ip = api.getPublicIPAddressApi(resourceGroup).get(resourceName);
list.add(ip);
break;
}
}
}
}
}
return list;
}
private String getResourceGroupFromId(String id) {
String searchStr = "/resourceGroups/";
int indexStart = id.lastIndexOf(searchStr) + searchStr.length();
searchStr = "/providers/";
int indexEnd = id.lastIndexOf(searchStr);
String resourceGroup = id.substring(indexStart, indexEnd);
return resourceGroup;
}
private List<NetworkInterfaceCard> getNetworkInterfaceCards(Deployment deployment) {
List<NetworkInterfaceCard> result = new ArrayList<NetworkInterfaceCard>();
String resourceGroup = getResourceGroupFromId(deployment.id());
if (deployment.properties() != null && deployment.properties().dependencies() != null) {
for (Deployment.Dependency dependency : deployment.properties().dependencies()) {
if (dependency.resourceType().equals("Microsoft.Network/networkInterfaces")) {
String resourceName = dependency.resourceName();
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(resourceGroup).get(resourceName);
result.add(nic);
}
}
}
return result;
}
}

View File

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
import org.jclouds.compute.domain.Image;
import com.google.common.base.Function;
import com.google.inject.assistedinject.Assisted;
public class ResourceDefinitionToCustomImage implements Function<ResourceDefinition, Image> {
public interface Factory {
ResourceDefinitionToCustomImage create(@Assisted("nodeId") String nodeId, @Assisted("imageName") String imageName);
}
private final String resourceGroup;
private final Function<VMImage, Image> vmImageToImage;
private final String imageName;
private final String storageAccountName;
private final VirtualMachine vm;
@Inject
ResourceDefinitionToCustomImage(AzureComputeApi api, AzureComputeConstants azureComputeConstants,
StorageProfileToStorageAccountName storageProfileToStorageAccountName,
Function<VMImage, Image> vmImageToImage, @Assisted("nodeId") String nodeId,
@Assisted("imageName") String imageName) {
this.vmImageToImage = vmImageToImage;
this.resourceGroup = azureComputeConstants.azureResourceGroup();
this.imageName = imageName;
this.vm = api.getVirtualMachineApi(resourceGroup).get(nodeId);
this.storageAccountName = storageProfileToStorageAccountName.apply(vm.properties().storageProfile());
}
@SuppressWarnings("unchecked")
@Override
public Image apply(ResourceDefinition input) {
VMImage.Builder builder = VMImage.customImage().group(resourceGroup).storage(storageAccountName).name(imageName)
.offer(CUSTOM_IMAGE_OFFER).location(vm.location());
Map<String, String> properties = (Map<String, String>) input.properties();
Object storageObject = properties.get("storageProfile");
Map<String, String> storageProperties = (Map<String, String>) storageObject;
Object osDiskObject = storageProperties.get("osDisk");
Map<String, String> osProperties = (Map<String, String>) osDiskObject;
builder.vhd1(osProperties.get("name"));
return vmImageToImage.apply(builder.build());
}
}

View File

@ -16,58 +16,50 @@
*/ */
package org.jclouds.azurecompute.arm.compute.functions; package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull; import java.util.Set;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
import com.google.common.base.Supplier; import org.jclouds.azurecompute.arm.domain.ImageReference;
import com.google.common.collect.FluentIterable;
import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import com.google.common.base.Function;
import com.google.inject.Inject;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.location.predicates.LocationPredicates; import org.jclouds.location.predicates.LocationPredicates;
import java.util.Set; import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
public class VMImageToImage implements Function<VMImage, Image> { public class VMImageToImage implements Function<VMImage, Image> {
private static final String UNRECOGNIZED = "UNRECOGNIZED";
private static final String UBUNTU = "Ubuntu"; private static final String UBUNTU = "Ubuntu";
private static final String WINDOWS = "Windows"; private static final String WINDOWS = "Windows";
private static final String OPENLOGIC = "openLogic"; private static final String OPENLOGIC = "openLogic";
private static final String CENTOS = "CentOS"; private static final String CENTOS = "CentOS";
private static final String COREOS = "CoreOS"; private static final String COREOS = "CoreOS";
private static final String OPENSUSE = "openSUSE"; private static final String OPENSUSE = "openSUSE";
private static final String SUSE = "SUSE"; private static final String SUSE = "SUSE";
private static final String SLES = "SLES";
private static final String SQL_SERVER = "SQL Server"; private static final String ORACLE_lINUX = "Oracle-Linux";
private static final String RHEL = "RHEL";
private static final String ORACLE_lINUX = "Oracle Linux";
private final Supplier<Set<? extends org.jclouds.domain.Location>> locations; private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
public static String encodeFieldsToUniqueId(boolean globallyAvailable, String locatioName, ImageReference imageReference){
return (globallyAvailable ? "global" : locatioName) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
}
public static String encodeFieldsToUniqueId(VMImage imageReference){ public static String encodeFieldsToUniqueId(VMImage imageReference){
return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku(); return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.publisher() + "/" + imageReference.offer() + "/" + imageReference.sku();
} }
public static String encodeFieldsToUniqueIdCustom(VMImage imageReference){ public static String encodeFieldsToUniqueIdCustom(VMImage imageReference){
return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group() + "/" + imageReference.storage() + "/" + imageReference.vhd1() + "/" + imageReference.offer(); return (imageReference.globallyAvailable() ? "global" : imageReference.location()) + "/" + imageReference.group() + "/" + imageReference.storage() + "/" + imageReference.offer() + "/" + imageReference.name();
} }
public static VMImage decodeFieldsFromUniqueId(final String id) { public static VMImage decodeFieldsFromUniqueId(final String id) {
@ -79,10 +71,10 @@ public class VMImageToImage implements Function<VMImage, Image> {
0: imageReference.location) + "/" + 0: imageReference.location) + "/" +
1: imageReference.group + "/" + 1: imageReference.group + "/" +
2: imageReference.storage + "/" + 2: imageReference.storage + "/" +
3: imageReference.vhd1 + "/" + 3: imageReference.offer + "/" +
4: imageReference.offer 4: imageReference.name
*/ */
vmImage = VMImage.create(fields[1], fields[2], fields[3], null, null, fields[4], fields[0]); vmImage = VMImage.customImage().location(fields[0]).group(fields[1]).storage(fields[2]).vhd1(fields[3]).offer(fields[4]).build();
} else { } else {
/* id fields indexes /* id fields indexes
0: imageReference.location) + "/" + 0: imageReference.location) + "/" +
@ -90,7 +82,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
2: imageReference.offer + "/" + 2: imageReference.offer + "/" +
3: imageReference.sku + "/" + 3: imageReference.sku + "/" +
*/ */
vmImage = VMImage.create(fields[1], fields[2], fields[3], null, fields[0]); vmImage = VMImage.azureImage().location(fields[0]).publisher(fields[1]).offer(fields[2]).sku(fields[3]).build();
} }
return vmImage; return vmImage;
} }
@ -102,26 +94,21 @@ public class VMImageToImage implements Function<VMImage, Image> {
@Override @Override
public Image apply(final VMImage image) { public Image apply(final VMImage image) {
Credentials credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD);
if (image.custom()) { if (image.custom()) {
final ImageBuilder builder = new ImageBuilder() final ImageBuilder builder = new ImageBuilder()
.location(FluentIterable.from(locations.get()) .location(FluentIterable.from(locations.get())
.firstMatch(LocationPredicates.idEquals(image.location())) .firstMatch(LocationPredicates.idEquals(image.location()))
.get()) .get())
.name(image.name()) .name(image.name())
.description("#" + image.group()) .description(image.group())
.status(Image.Status.AVAILABLE) .status(Image.Status.AVAILABLE)
.version(image.storage()) .version("latest")
.providerId(image.vhd1()) .providerId(image.vhd1())
.id(encodeFieldsToUniqueIdCustom(image)) .id(encodeFieldsToUniqueIdCustom(image));
.defaultCredentials(LoginCredentials.fromCredentials(credentials));
final OperatingSystem.Builder osBuilder = osFamily().apply(image); final OperatingSystem.Builder osBuilder = osFamily().apply(image);
Image retimage = builder.operatingSystem(osBuilder.build()).build(); Image retimage = builder.operatingSystem(osBuilder.build()).build();
return retimage; return retimage;
} }
else { else {
final ImageBuilder builder = new ImageBuilder() final ImageBuilder builder = new ImageBuilder()
@ -130,7 +117,6 @@ public class VMImageToImage implements Function<VMImage, Image> {
.status(Image.Status.AVAILABLE) .status(Image.Status.AVAILABLE)
.version(image.sku()) .version(image.sku())
.id(encodeFieldsToUniqueId(image)) .id(encodeFieldsToUniqueId(image))
.defaultCredentials(LoginCredentials.fromCredentials(credentials))
.providerId(image.publisher()) .providerId(image.publisher())
.location(image.globallyAvailable() ? null : FluentIterable.from(locations.get()) .location(image.globallyAvailable() ? null : FluentIterable.from(locations.get())
.firstMatch(LocationPredicates.idEquals(image.location())) .firstMatch(LocationPredicates.idEquals(image.location()))
@ -149,11 +135,11 @@ public class VMImageToImage implements Function<VMImage, Image> {
final String label = image.offer(); final String label = image.offer();
OsFamily family = OsFamily.UNRECOGNIZED; OsFamily family = OsFamily.UNRECOGNIZED;
if (label.contains(CENTOS)) { if (label.contains(CENTOS) || label.contains(OPENLOGIC)) {
family = OsFamily.CENTOS; family = OsFamily.CENTOS;
} else if (label.contains(OPENLOGIC)) { } else if (label.contains(COREOS)) {
family = OsFamily.CENTOS; family = OsFamily.COREOS;
} else if (label.contains(SUSE)) { } else if (label.contains(SUSE) || label.contains(SLES) || label.contains(OPENSUSE)) {
family = OsFamily.SUSE; family = OsFamily.SUSE;
} else if (label.contains(UBUNTU)) { } else if (label.contains(UBUNTU)) {
family = OsFamily.UBUNTU; family = OsFamily.UBUNTU;
@ -161,18 +147,16 @@ public class VMImageToImage implements Function<VMImage, Image> {
family = OsFamily.WINDOWS; family = OsFamily.WINDOWS;
} else if (label.contains(ORACLE_lINUX)) { } else if (label.contains(ORACLE_lINUX)) {
family = OsFamily.OEL; family = OsFamily.OEL;
} else if (label.contains(RHEL)) {
family = OsFamily.RHEL;
} }
String sku = image.sku();
if (image.custom())
sku = image.vhd1();
// only 64bit OS images are supported by Azure ARM // only 64bit OS images are supported by Azure ARM
return OperatingSystem.builder(). return OperatingSystem.builder().
family(family). family(family).
is64Bit(true). is64Bit(true).
description(sku). description(image.custom() ? image.vhd1() : image.sku()).
version(sku); version(image.custom() ? "latest" : image.sku());
} }
}; };
} }

View File

@ -0,0 +1,279 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Iterables.tryFind;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CONTAINER_NAME;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_OFFER;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.encodeFieldsToUniqueId;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties.ProvisioningState;
import org.jclouds.azurecompute.arm.functions.StorageProfileToStorageAccountName;
import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
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.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, NodeMetadata> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
// When using the Deployment API to deploy an ARM template, the deployment
// goes through
// stages. Accepted -> Running -> Succeeded. Only when the deployment has
// SUCCEEDED is
// the resource deployed using the template actually ready.
//
// To get details about the resource(s) deployed via template, one needs to
// query the
// various resources after the deployment has "SUCCEEDED".
private static final Function<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> PROVISIONINGSTATE_TO_NODESTATUS = Functions
.forMap(
ImmutableMap.<VirtualMachineProperties.ProvisioningState, NodeMetadata.Status> builder()
.put(VirtualMachineProperties.ProvisioningState.ACCEPTED, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.READY, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.CREATING, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.RUNNING, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.UPDATING, NodeMetadata.Status.PENDING)
.put(VirtualMachineProperties.ProvisioningState.SUCCEEDED, NodeMetadata.Status.RUNNING)
.put(VirtualMachineProperties.ProvisioningState.DELETED, NodeMetadata.Status.TERMINATED)
.put(VirtualMachineProperties.ProvisioningState.CANCELED, NodeMetadata.Status.TERMINATED)
.put(VirtualMachineProperties.ProvisioningState.FAILED, NodeMetadata.Status.ERROR)
.put(VirtualMachineProperties.ProvisioningState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED)
.build(), NodeMetadata.Status.UNRECOGNIZED);
private static final Function<VirtualMachineStatus.PowerState, NodeMetadata.Status> POWERSTATE_TO_NODESTATUS = Functions
.forMap(
ImmutableMap.<PowerState, NodeMetadata.Status> builder()
.put(PowerState.RUNNING, NodeMetadata.Status.RUNNING)
.put(PowerState.STOPPED, NodeMetadata.Status.SUSPENDED)
.put(PowerState.UNRECOGNIZED, NodeMetadata.Status.UNRECOGNIZED).build(),
NodeMetadata.Status.UNRECOGNIZED);
private final String azureGroup;
private final AzureComputeApi api;
private final GroupNamingConvention nodeNamingConvention;
private final Supplier<Map<String, ? extends Image>> images;
private final Supplier<Set<? extends Location>> locations;
private final Supplier<Map<String, ? extends Hardware>> hardwares;
private final Map<String, Credentials> credentialStore;
private final Function<VMImage, Image> vmImageToImge;
private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
@Inject
VirtualMachineToNodeMetadata(AzureComputeApi api, GroupNamingConvention.Factory namingConvention,
Supplier<Map<String, ? extends Image>> images, Supplier<Map<String, ? extends Hardware>> hardwares,
@Memoized Supplier<Set<? extends Location>> locations, Map<String, Credentials> credentialStore,
final AzureComputeConstants azureComputeConstants, Function<VMImage, Image> vmImageToImge,
StorageProfileToStorageAccountName storageProfileToStorageAccountName) {
this.api = api;
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.images = checkNotNull(images, "images cannot be null");
this.locations = checkNotNull(locations, "locations cannot be null");
this.hardwares = checkNotNull(hardwares, "hardwares cannot be null");
this.credentialStore = credentialStore;
this.azureGroup = azureComputeConstants.azureResourceGroup();
this.vmImageToImge = vmImageToImge;
this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
}
@Override
public NodeMetadata apply(VirtualMachine virtualMachine) {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.id(virtualMachine.name());
builder.providerId(virtualMachine.id());
builder.name(virtualMachine.name());
builder.hostname(virtualMachine.name());
String group = this.nodeNamingConvention.extractGroup(virtualMachine.name());
builder.group(group);
ProvisioningState provisioningState = virtualMachine.properties().provisioningState();
if (ProvisioningState.SUCCEEDED.equals(provisioningState)) {
// If the provisioning succeeded, we need to query the *real* status of
// the VM
VirtualMachineInstance instanceDetails = api.getVirtualMachineApi(azureGroup).getInstanceDetails(
virtualMachine.name());
builder.status(POWERSTATE_TO_NODESTATUS.apply(instanceDetails.powerState()));
builder.backendStatus(Joiner.on(',').join(
transform(instanceDetails.statuses(), new Function<VirtualMachineStatus, String>() {
@Override
public String apply(VirtualMachineStatus input) {
return input.code();
}
})));
} else {
builder.status(PROVISIONINGSTATE_TO_NODESTATUS.apply(provisioningState));
builder.backendStatus(provisioningState.name());
}
Credentials credentials = credentialStore.get("node#" + virtualMachine.name());
builder.credentials(LoginCredentials.fromCredentials(credentials));
builder.publicAddresses(getPublicIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces()));
builder.privateAddresses(getPrivateIpAddresses(virtualMachine.properties().networkProfile().networkInterfaces()));
if (virtualMachine.tags() != null) {
Map<String, String> userMetaData = virtualMachine.tags();
builder.userMetadata(userMetaData);
builder.tags(Splitter.on(",").split(userMetaData.get("tags")));
}
String locationName = virtualMachine.location();
builder.location(getLocation(locationName));
Optional<? extends Image> image = findImage(virtualMachine.properties().storageProfile(), locationName);
if (image.isPresent()) {
builder.imageId(image.get().getId());
builder.operatingSystem(image.get().getOperatingSystem());
} else {
logger.info(">> image with id %s for virtualmachine %s was not found. "
+ "This might be because the image that was used to create the virtualmachine has a new id.",
virtualMachine.id(), virtualMachine.id());
}
builder.hardware(getHardware(virtualMachine.properties().hardwareProfile().vmSize()));
return builder.build();
}
private Iterable<String> getPrivateIpAddresses(List<IdReference> idReferences) {
List<String> privateIpAddresses = Lists.newArrayList();
for (IdReference networkInterfaceCardIdReference : idReferences) {
NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
privateIpAddresses.add(ipConfiguration.properties().privateIPAddress());
}
}
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 Iterable<String> getPublicIpAddresses(List<IdReference> idReferences) {
List<String> publicIpAddresses = Lists.newArrayList();
for (IdReference networkInterfaceCardIdReference : idReferences) {
NetworkInterfaceCard networkInterfaceCard = getNetworkInterfaceCard(networkInterfaceCardIdReference);
String resourceGroup = Iterables.get(Splitter.on("/").split(networkInterfaceCardIdReference.id()), 4);
for (IpConfiguration ipConfiguration : networkInterfaceCard.properties().ipConfigurations()) {
if (ipConfiguration.properties().publicIPAddress() != null) {
String publicIpId = ipConfiguration.properties().publicIPAddress().id();
publicIpAddresses.add(api.getPublicIPAddressApi(resourceGroup)
.get(Iterables.getLast(Splitter.on("/").split(publicIpId))).properties().ipAddress());
}
}
}
return publicIpAddresses;
}
protected Location getLocation(final String locationName) {
return find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location location) {
return locationName != null && locationName.equals(location.getId());
}
}, null);
}
protected Optional<? extends Image> findImage(final StorageProfile storageProfile, String locatioName) {
if (storageProfile.imageReference() != null) {
return Optional.fromNullable(images.get().get(
encodeFieldsToUniqueId(false, locatioName, storageProfile.imageReference())));
} else {
String storageAccountName = storageProfileToStorageAccountName.apply(storageProfile);
StorageServiceKeys keys = api.getStorageAccountApi(azureGroup).getKeys(storageAccountName);
BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
try {
// Custom image. Let's find it by uri
List<VMImage> customImagesInStorage = blobHelper.getImages(CONTAINER_NAME, azureGroup, CUSTOM_IMAGE_OFFER,
locatioName);
Optional<VMImage> customImage = tryFind(customImagesInStorage, new Predicate<VMImage>() {
@Override
public boolean apply(VMImage input) {
return input.vhd1().equals(storageProfile.osDisk().image().uri());
}
});
return customImage.isPresent() ? Optional.of(vmImageToImge.apply(customImage.get())) : Optional
.<Image> absent();
} finally {
closeQuietly(blobHelper);
}
}
}
protected Hardware getHardware(final String vmSize) {
return Iterables.find(hardwares.get().values(), new Predicate<Hardware>() {
@Override
public boolean apply(Hardware input) {
return input.getId().equals(vmSize);
}
});
}
}

View File

@ -16,10 +16,12 @@
*/ */
package org.jclouds.azurecompute.arm.compute.options; package org.jclouds.azurecompute.arm.compute.options;
import static com.google.common.base.Objects.equal;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import static com.google.common.base.Objects.equal;
/** /**
* Azure ARM custom options * Azure ARM custom options
*/ */
@ -31,7 +33,9 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
private String subnetAddressPrefix; private String subnetAddressPrefix;
private String DNSLabelPrefix; private String DNSLabelPrefix;
private String keyVaultIdAndSecret; private String keyVaultIdAndSecret;
private String virtualNetworkName;
private String subnetId;
private String blob;
/** /**
* Custom options for the Azure ARM API * Custom options for the Azure ARM API
@ -40,8 +44,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
this.customData = customData; this.customData = customData;
return this; return this;
} }
private String virtualNetworkName;
private String subnetId;
/** /**
* Sets the CIDR block for virtual network * Sets the CIDR block for virtual network
@ -75,15 +77,6 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
return this; return this;
} }
public String getCustomData() { return customData; }
public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; }
public String getSubnetAddressPrefix() { return subnetAddressPrefix; }
public String getDNSLabelPrefix() { return DNSLabelPrefix; }
public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; }
public String getVirtualNetworkName() { return virtualNetworkName; }
public String getSubnetId() { return subnetId; }
/** /**
* Sets the virtual network name * Sets the virtual network name
*/ */
@ -100,6 +93,24 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
return this; return this;
} }
/**
* Sets the blob name
*/
public AzureTemplateOptions blob(String blob) {
this.blob = blob;
return this;
}
public String getCustomData() { return customData; }
public String getVirtualNetworkAddressPrefix() { return virtualNetworkAddressPrefix; }
public String getSubnetAddressPrefix() { return subnetAddressPrefix; }
public String getDNSLabelPrefix() { return DNSLabelPrefix; }
public String getKeyVaultIdAndSecret() { return keyVaultIdAndSecret; }
public String getVirtualNetworkName() { return virtualNetworkName; }
public String getSubnetId() { return subnetId; }
public String getBlob() { return blob; }
@Override @Override
public AzureTemplateOptions clone() { public AzureTemplateOptions clone() {
AzureTemplateOptions options = new AzureTemplateOptions(); AzureTemplateOptions options = new AzureTemplateOptions();
@ -119,12 +130,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
eTo.keyVaultIdAndSecret(keyVaultIdAndSecret); eTo.keyVaultIdAndSecret(keyVaultIdAndSecret);
eTo.virtualNetworkName(virtualNetworkName); eTo.virtualNetworkName(virtualNetworkName);
eTo.subnetId(subnetId); eTo.subnetId(subnetId);
eTo.blob(blob);
} }
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId); return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId, blob);
} }
@Override @Override
@ -146,7 +158,8 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
&& equal(this.DNSLabelPrefix, other.DNSLabelPrefix) && equal(this.DNSLabelPrefix, other.DNSLabelPrefix)
&& equal(this.keyVaultIdAndSecret, other.keyVaultIdAndSecret) && equal(this.keyVaultIdAndSecret, other.keyVaultIdAndSecret)
&& equal(this.virtualNetworkName, other.virtualNetworkName) && equal(this.virtualNetworkName, other.virtualNetworkName)
&& equal(this.subnetId, other.subnetId); && equal(this.subnetId, other.subnetId)
&& equal(this.blob, other.blob);
} }
@Override @Override
@ -159,6 +172,7 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
toString.add("keyVaultIdAndSecret", keyVaultIdAndSecret); toString.add("keyVaultIdAndSecret", keyVaultIdAndSecret);
toString.add("virtualNetworkName", virtualNetworkName); toString.add("virtualNetworkName", virtualNetworkName);
toString.add("subnetId", subnetId); toString.add("subnetId", subnetId);
toString.add("blob", blob);
return toString; return toString;
} }
@ -219,5 +233,13 @@ public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
AzureTemplateOptions options = new AzureTemplateOptions(); AzureTemplateOptions options = new AzureTemplateOptions();
return options.subnetId(subnetId); return options.subnetId(subnetId);
} }
/**
* @see AzureTemplateOptions#blob
*/
public static AzureTemplateOptions blob(String blob) {
AzureTemplateOptions options = new AzureTemplateOptions();
return options.blob(blob);
}
} }
} }

View File

@ -40,6 +40,7 @@ public class IsDeploymentInRegions implements Predicate<Deployment> {
@Override @Override
public boolean apply(Deployment deployment) { public boolean apply(Deployment deployment) {
if (deployment.properties() == null || deployment.properties().parameters() == null || deployment.properties().parameters().get("location") == null) return false;
Value locationValue = deployment.properties().parameters().get("location"); Value locationValue = deployment.properties().parameters().get("location");
return regionIds.get().contains(locationValue.value()); return regionIds.get().contains(locationValue.value());
} }

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.compute.strategy;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_PASSWORD;
import static org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata.AZURE_LOGIN_USERNAME;
public class AzurePopulateDefaultLoginCredentialsForImageStrategy implements PopulateDefaultLoginCredentialsForImageStrategy {
@Override
public LoginCredentials apply(Object o) {
ImageImpl node = (ImageImpl)o;
String username = AZURE_LOGIN_USERNAME;
String password = AZURE_LOGIN_PASSWORD;
if (username == null) {
username = "jclouds";
}
if (password == null) {
password = "Password1!";
}
Credentials creds = new Credentials(username, password);
LoginCredentials credentials = LoginCredentials.fromCredentials(creds);
return credentials;
}
}

View File

@ -17,26 +17,36 @@
package org.jclouds.azurecompute.arm.compute.strategy; package org.jclouds.azurecompute.arm.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.azurecompute.arm.compute.functions.VMImageToImage.decodeFieldsFromUniqueId;
import static org.jclouds.util.Predicates2.retry;
import java.net.URI;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import com.google.common.collect.ImmutableMap;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.Subnet; import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi; import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.SubnetApi; import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi; import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.functions.GroupNamingConvention;
@ -45,9 +55,11 @@ import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap; import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet; import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
@ -81,7 +93,13 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template, public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes, Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) { Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
// If there is a script to be run on the node and public key
// authentication has been configured, warn users if the private key
// is not present
if (hasRunScriptWithKeyAuthAndNoPrivateKey(template)) {
logger.warn(">> a runScript was configured but no SSH key has been provided. " +
"Authentication will delegate to the ssh-agent");
}
String azureGroupName = this.azureComputeConstants.azureResourceGroup(); String azureGroupName = this.azureComputeConstants.azureResourceGroup();
AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class); AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
@ -91,7 +109,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
final String location = template.getLocation().getId(); final String location = template.getLocation().getId();
if (resourceGroup == null){ if (resourceGroup == null){
final Map<String, String> tags = ImmutableMap.of("description", "jClouds managed VMs"); final Map<String, String> tags = ImmutableMap.of("description", "jclouds managed VMs");
resourceGroupApi.create(azureGroupName, location, tags).name(); resourceGroupApi.create(azureGroupName, location, tags).name();
} }
@ -104,6 +122,9 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
this.getOrCreateVirtualNetworkWithSubnet(vnetName, subnetName, location, options, azureGroupName); this.getOrCreateVirtualNetworkWithSubnet(vnetName, subnetName, location, options, azureGroupName);
StorageService storageService = getOrCreateStorageService(group, azureGroupName, location, template.getImage());
String blob = storageService.storageServiceProperties().primaryEndpoints().get("blob");
options.blob(blob);
Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes, Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes,
customizationResponses); customizationResponses);
@ -135,6 +156,70 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
options.virtualNetworkName(virtualNetworkName); options.virtualNetworkName(virtualNetworkName);
options.subnetId(subnet.id()); options.subnetId(subnet.id());
}
private static boolean hasRunScriptWithKeyAuthAndNoPrivateKey(Template template) {
return template.getOptions().getRunScript() != null && template.getOptions().getPublicKey() != null
&& !template.getOptions().hasLoginPrivateKeyOption();
}
public StorageService getOrCreateStorageService(String name, String resourceGroupName, String locationName, Image image) {
String storageAccountName = null;
VMImage imageRef = decodeFieldsFromUniqueId(image.getId());
if (imageRef.custom()) {
storageAccountName = imageRef.storage();
}
if (Strings.isNullOrEmpty(storageAccountName)) {
storageAccountName = generateStorageAccountName(name);
}
StorageService storageService = api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
if (storageService != null) return storageService;
URI uri = api.getStorageAccountApi(resourceGroupName).create(storageAccountName, locationName, ImmutableMap.of("jclouds",
name), ImmutableMap.of("accountType", StorageService.AccountType.Standard_LRS.toString()));
boolean starageAccountCreated = retry(new Predicate<URI>() {
@Override
public boolean apply(URI uri) {
return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
}
}, 60 * 2 * 1000 /* 2 minutes timeout */).apply(uri);
// TODO check provisioning state of the primary
checkState(starageAccountCreated, "Storage account %s was not created in the configured timeout",
storageAccountName);
return api.getStorageAccountApi(resourceGroupName).get(storageAccountName);
}
/**
* Generates a valid storage account
*
* Storage account names must be between 3 and 24 characters in length and may contain numbers and lowercase letters only.
*
* @param name the node name
* @return the storage account name starting from a sanitized name (with only numbers and lowercase letters only ).
* If sanitized name is between 3 and 24 characters, storage account name is equals to sanitized name.
* If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars.
* If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name.
*/
public static String generateStorageAccountName(String name) {
String random = UUID.randomUUID().toString().substring(0, 4);
String storageAccountName = new StringBuilder().append(name).append(random).toString();
String sanitizedStorageAccountName = storageAccountName.replaceAll("[^a-z0-9]", "");
int nameLength = sanitizedStorageAccountName.length();
if (nameLength >= 3 && nameLength <= 24) {
return sanitizedStorageAccountName;
}
if (nameLength > 24) {
sanitizedStorageAccountName = shorten(storageAccountName, random);
}
return sanitizedStorageAccountName;
}
private static String shorten(String storageAccountName, String random) {
String prefix = storageAccountName.substring(0, 10);
String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
return String.format("%s%s%s", prefix, random, suffix);
} }
} }

View File

@ -18,7 +18,6 @@ package org.jclouds.azurecompute.arm.config;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler; import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
@ -30,7 +29,6 @@ import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule; import org.jclouds.rest.config.HttpApiModule;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.assistedinject.FactoryModuleBuilder;
@ConfiguresHttpApi @ConfiguresHttpApi
public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> { public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
@ -51,7 +49,6 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
@Override @Override
protected void configure() { protected void configure() {
install(new FactoryModuleBuilder().build(DeploymentTemplateBuilder.Factory.class));
super.configure(); super.configure();
bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create()); bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create());
} }

View File

@ -17,10 +17,13 @@
package org.jclouds.azurecompute.arm.config; package org.jclouds.azurecompute.arm.config;
/** /**
* Configuration properties and constants used in Azure Resource Manager connections. * Configuration properties and constants used in Azure Resource Manager
* connections.
*/ */
public class AzureComputeProperties { public class AzureComputeProperties {
public static final String STORAGE_API_VERSION = "2015-06-15";
public static final String OPERATION_TIMEOUT = "jclouds.azurecompute.arm.operation.timeout"; public static final String OPERATION_TIMEOUT = "jclouds.azurecompute.arm.operation.timeout";
public static final String OPERATION_POLL_INITIAL_PERIOD = "jclouds.azurecompute.arm.operation.poll.initial.period"; public static final String OPERATION_POLL_INITIAL_PERIOD = "jclouds.azurecompute.arm.operation.poll.initial.period";
@ -31,8 +34,6 @@ public class AzureComputeProperties {
public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.arm.tcp.rule.regexp"; public static final String TCP_RULE_REGEXP = "jclouds.azurecompute.arm.tcp.rule.regexp";
public static final String STORAGE_API_VERSION = "2015-06-15";
public static final String RESOURCE_GROUP_NAME = "jclouds.azurecompute.arm.operation.resourcegroup"; public static final String RESOURCE_GROUP_NAME = "jclouds.azurecompute.arm.operation.resourcegroup";
public static final String IMAGE_PUBLISHERS = "jclouds.azurecompute.arm.publishers"; public static final String IMAGE_PUBLISHERS = "jclouds.azurecompute.arm.publishers";
@ -47,4 +48,6 @@ public class AzureComputeProperties {
public static final String DEFAULT_DATADISKSIZE = "jclouds.azurecompute.arm.datadisksize"; public static final String DEFAULT_DATADISKSIZE = "jclouds.azurecompute.arm.datadisksize";
public static final String API_VERSION_PREFIX = "jclouds.azurecompute.arm.apiversion.";
} }

View File

@ -16,43 +16,29 @@
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue; import java.util.List;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import java.util.List; import com.google.auto.value.AutoValue;
import java.util.Map;
@AutoValue @AutoValue
public abstract class VMDeployment { public abstract class VMDeployment {
public abstract Deployment deployment(); public abstract String deploymentId();
@Nullable
public abstract List<PublicIPAddress> ipAddressList();
@Nullable
public abstract VirtualMachineInstance vm();
@Nullable @Nullable
public abstract VirtualMachine virtualMachine(); public abstract VirtualMachine virtualMachine();
@Nullable
public abstract List<PublicIPAddress> ipAddressList();
@Nullable @Nullable
public abstract List<NetworkInterfaceCard> networkInterfaceCards(); public abstract List<NetworkInterfaceCard> networkInterfaceCards();
@Nullable public static VMDeployment create(String deploymentId, VirtualMachine virtualMachine,
public abstract Map<String, String> userMetaData(); List<PublicIPAddress> ipAddressList,
List<NetworkInterfaceCard> networkInterfaceCards) {
@Nullable return new AutoValue_VMDeployment(deploymentId, virtualMachine, ipAddressList, networkInterfaceCards);
public abstract Iterable<String> tags();
public static VMDeployment create(Deployment deployment) {
return create(deployment, null, null, null, null, null, null);
}
public static VMDeployment create(Deployment deployment, List<PublicIPAddress> ipAddressList,
VirtualMachineInstance vm, VirtualMachine virtualMachine,
List<NetworkInterfaceCard> networkInterfaceCards, Map<String, String> userMetaData,
Iterable<String> tags) {
return new AutoValue_VMDeployment(deployment, ipAddressList, vm, virtualMachine, networkInterfaceCards, userMetaData, tags);
} }
} }

View File

@ -16,9 +16,9 @@
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
@AutoValue @AutoValue
public abstract class VMImage { public abstract class VMImage {
@ -92,15 +92,34 @@ public abstract class VMImage {
*/ */
public abstract boolean custom(); public abstract boolean custom();
@SerializedNames({ "publisher", "offer", "sku", "version", "location"}) public static Builder builder() {
public static VMImage create(String publisher, String offer, String sku, String version, String location) { return new AutoValue_VMImage.Builder();
return new AutoValue_VMImage(publisher, offer, sku, version, location, false, null, null, null, null, null, false);
} }
@SerializedNames({ "group", "storage", "vhd1", "vhd2", "name", "offer", "location"}) public static Builder azureImage() {
public static VMImage create(String group, String storage, String vhd1, String vhd2, String name, String offer, String location) { return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(false);
}
return new AutoValue_VMImage(null, offer, null, null, location, false, group, storage, vhd1, vhd2, name, true); public static Builder customImage() {
return new AutoValue_VMImage.Builder().globallyAvailable(false).custom(true);
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder publisher(String published);
public abstract Builder offer(String offer);
public abstract Builder sku(String sku);
public abstract Builder version(String version);
public abstract Builder location(String location);
public abstract Builder globallyAvailable(boolean globallyAvailable);
public abstract Builder group(String group);
public abstract Builder storage(String storage);
public abstract Builder vhd1(String vhd1);
public abstract Builder vhd2(String vhd2);
public abstract Builder name(String name);
public abstract Builder custom(boolean custom);
public abstract VMImage build();
} }
} }

View File

@ -16,12 +16,13 @@
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue; import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames; import org.jclouds.json.SerializedNames;
import java.util.Map; import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
/** /**
* A virtual machine that is valid for your subscription. * A virtual machine that is valid for your subscription.

View File

@ -16,13 +16,23 @@
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue; import static com.google.common.collect.Iterables.filter;
import com.google.common.collect.ImmutableList; import static com.google.common.collect.Iterables.getFirst;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.util.Predicates2.startsWith;
import java.util.Date;
import java.util.List; import java.util.List;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties.ProvisioningState;
import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames; import org.jclouds.json.SerializedNames;
import java.util.Date; import com.google.auto.value.AutoValue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
/** /**
* A virtual machine instance view that is valid for your subscription. * A virtual machine instance view that is valid for your subscription.
@ -30,9 +40,22 @@ import java.util.Date;
@AutoValue @AutoValue
public abstract class VirtualMachineInstance { public abstract class VirtualMachineInstance {
@AutoValue @com.google.auto.value.AutoValue
public abstract static class VirtualMachineStatus { public abstract static class VirtualMachineStatus {
public static final String PROVISIONING_STATE_PREFIX = "ProvisioningState/";
public static final String POWER_STATE_PREFIX = "PowerState/";
public enum PowerState {
RUNNING,
STOPPED,
UNRECOGNIZED;
public static PowerState fromValue(final String text) {
return (PowerState) GetEnumValue.fromValueOrDefault(text, PowerState.UNRECOGNIZED);
}
}
@Nullable @Nullable
public abstract String code(); public abstract String code();
@ -62,6 +85,26 @@ public abstract class VirtualMachineInstance {
@Nullable @Nullable
public abstract List<VirtualMachineStatus> statuses(); public abstract List<VirtualMachineStatus> statuses();
public ProvisioningState provisioningState() {
return ProvisioningState.fromValue(firstStatus(VirtualMachineStatus.PROVISIONING_STATE_PREFIX));
}
public PowerState powerState() {
return PowerState.fromValue(firstStatus(VirtualMachineStatus.POWER_STATE_PREFIX));
}
private String firstStatus(final String type) {
return getFirst(transform(filter(transform(statuses(), new Function<VirtualMachineStatus, String>() {
@Override public String apply(VirtualMachineStatus input) {
return input.code();
}
}), startsWith(type)), new Function<String, String>() {
@Override public String apply(String input) {
return input.substring(type.length());
}
}), null);
}
@SerializedNames({"platformUpdateDomain", "platformFaultDomain", "statuses"}) @SerializedNames({"platformUpdateDomain", "platformFaultDomain", "statuses"})
public static VirtualMachineInstance create(final String platformUpdateDomain, final String platformFaultDomain, public static VirtualMachineInstance create(final String platformUpdateDomain, final String platformFaultDomain,

View File

@ -16,16 +16,35 @@
*/ */
package org.jclouds.azurecompute.arm.domain; package org.jclouds.azurecompute.arm.domain;
import com.google.auto.value.AutoValue; import org.jclouds.azurecompute.arm.util.GetEnumValue;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames; import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
/** /**
* A virtual machine properties for the virtual machine. * A virtual machine properties for the virtual machine.
*/ */
@AutoValue @AutoValue
public abstract class VirtualMachineProperties { public abstract class VirtualMachineProperties {
public enum ProvisioningState {
ACCEPTED,
CREATING,
READY,
CANCELED,
FAILED,
DELETED,
SUCCEEDED,
RUNNING,
UPDATING,
UNRECOGNIZED;
public static ProvisioningState fromValue(final String text) {
return (ProvisioningState) GetEnumValue.fromValueOrDefault(text, ProvisioningState.UNRECOGNIZED);
}
}
/** /**
* The id of the virtual machine. * The id of the virtual machine.
*/ */
@ -78,7 +97,7 @@ public abstract class VirtualMachineProperties {
* The provisioning state of the VM * The provisioning state of the VM
*/ */
@Nullable @Nullable
public abstract String provisioningState(); public abstract ProvisioningState provisioningState();
@SerializedNames({"vmId", "licenseType", "availabilitySet", "hardwareProfile", "storageProfile", "osProfile", @SerializedNames({"vmId", "licenseType", "availabilitySet", "hardwareProfile", "storageProfile", "osProfile",
"networkProfile", "diagnosticsProfile", "provisioningState"}) "networkProfile", "diagnosticsProfile", "provisioningState"})
@ -90,7 +109,7 @@ public abstract class VirtualMachineProperties {
final OSProfile osProfile, final OSProfile osProfile,
final NetworkProfile networkProfile, final NetworkProfile networkProfile,
final DiagnosticsProfile diagnosticsProfile, final DiagnosticsProfile diagnosticsProfile,
final String provisioningState) { final ProvisioningState provisioningState) {
return builder() return builder()
.vmId(vmId) .vmId(vmId)
.licenseType(licenseType) .licenseType(licenseType)
@ -126,7 +145,7 @@ public abstract class VirtualMachineProperties {
public abstract Builder diagnosticsProfile(DiagnosticsProfile diagnosticsProfile); public abstract Builder diagnosticsProfile(DiagnosticsProfile diagnosticsProfile);
public abstract Builder provisioningState(String provisioningState); public abstract Builder provisioningState(ProvisioningState provisioningState);
public abstract VirtualMachineProperties build(); public abstract VirtualMachineProperties build();
} }

View File

@ -34,12 +34,12 @@ import org.jclouds.Fallbacks;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Deployment; import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser; import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
@ -50,8 +50,7 @@ import org.jclouds.rest.annotations.SelectJson;
* - get information about deployment * - get information about deployment
*/ */
@Path("/resourcegroups/{resourcegroup}/providers/microsoft.resources/deployments") @Path("/resourcegroups/{resourcegroup}/providers/microsoft.resources/deployments")
@QueryParams(keys = "api-version", values = "2016-02-01") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface DeploymentApi { public interface DeploymentApi {

View File

@ -18,19 +18,20 @@ package org.jclouds.azurecompute.arm.features;
import java.io.Closeable; import java.io.Closeable;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks; import org.jclouds.Fallbacks;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition; import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
/** /**

View File

@ -27,11 +27,11 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Location; import org.jclouds.azurecompute.arm.domain.Location;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback;
/** /**
* This Azure Resource Manager API provides all of the locations that are available for resource providers * This Azure Resource Manager API provides all of the locations that are available for resource providers
@ -40,8 +40,7 @@ import org.jclouds.rest.annotations.Fallback;
* @see <a href="https://msdn.microsoft.com/en-US/library/azure/dn790540.aspx">docs</a> * @see <a href="https://msdn.microsoft.com/en-US/library/azure/dn790540.aspx">docs</a>
*/ */
@Path("/locations") @Path("/locations")
@RequestFilters(OAuthFilter.class) @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@QueryParams(keys = "api-version", values = "2015-11-01")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface LocationApi { public interface LocationApi {

View File

@ -16,20 +16,9 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import java.net.URI;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import java.util.List;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; import java.util.Map;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -39,15 +28,25 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import java.net.URI; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkInterfaces") @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkInterfaces")
@QueryParams(keys = "api-version", values = "2015-06-15") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface NetworkInterfaceCardApi { public interface NetworkInterfaceCardApi {
@Named("networkinterfacecard:list") @Named("networkinterfacecard:list")

View File

@ -16,40 +16,38 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.DELETE;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups") import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@QueryParams(keys = "api-version", values = "2016-03-30") import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
@RequestFilters(OAuthFilter.class) import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface NetworkSecurityGroupApi { public interface NetworkSecurityGroupApi {
@ -72,9 +70,8 @@ public interface NetworkSecurityGroupApi {
@MapBinder(BindToJsonPayload.class) @MapBinder(BindToJsonPayload.class)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
NetworkSecurityGroup createOrUpdate(@PathParam("networksecuritygroupname") String nsgName, NetworkSecurityGroup createOrUpdate(@PathParam("networksecuritygroupname") String nsgName,
@PayloadParam("location") String location, @PayloadParam("location") String location, @Nullable @PayloadParam("tags") Map<String, String> tags,
@Nullable @PayloadParam("tags") Map<String, String> tags, @PayloadParam("properties") NetworkSecurityGroupProperties properties);
@PayloadParam("properties")NetworkSecurityGroupProperties properties);
@Named("networksecuritygroup:get") @Named("networksecuritygroup:get")
@Path("/{networksecuritygroupname}") @Path("/{networksecuritygroupname}")
@ -82,4 +79,3 @@ public interface NetworkSecurityGroupApi {
@Fallback(NullOnNotFoundOr404.class) @Fallback(NullOnNotFoundOr404.class)
NetworkSecurityGroup get(@PathParam("networksecuritygroupname") String nsgName); NetworkSecurityGroup get(@PathParam("networksecuritygroupname") String nsgName);
} }

View File

@ -16,38 +16,36 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties; import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser; import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.DELETE;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.net.URI;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups/{networksecuritygroup}") @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/networkSecurityGroups/{networksecuritygroup}")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@QueryParams(keys = "api-version", values = "2016-03-30")
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface NetworkSecurityRuleApi { public interface NetworkSecurityRuleApi {
@Named("networksecurityrule:createOrUpdate") @Named("networksecurityrule:createOrUpdate")

View File

@ -31,17 +31,16 @@ import org.jclouds.azurecompute.arm.domain.Offer;
import org.jclouds.azurecompute.arm.domain.Publisher; import org.jclouds.azurecompute.arm.domain.Publisher;
import org.jclouds.azurecompute.arm.domain.SKU; import org.jclouds.azurecompute.arm.domain.SKU;
import org.jclouds.azurecompute.arm.domain.Version; import org.jclouds.azurecompute.arm.domain.Version;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
/** /**
* The Azure Resource Management API includes operations for managing the OS images in your subscription. * The Azure Resource Management API includes operations for managing the OS images in your subscription.
*/ */
@Path("/providers/Microsoft.Compute/locations/{location}") @Path("/providers/Microsoft.Compute/locations/{location}")
@RequestFilters(OAuthFilter.class) @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@QueryParams(keys = "api-version", values = "2015-06-15")
@Consumes(APPLICATION_JSON) @Consumes(APPLICATION_JSON)
public interface OSImageApi { public interface OSImageApi {

View File

@ -16,20 +16,8 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import java.util.List;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import java.util.Map;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -39,14 +27,25 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/publicIPAddresses") @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/publicIPAddresses")
@QueryParams(keys = "api-version", values = "2015-06-15") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface PublicIPAddressApi { public interface PublicIPAddressApi {
@Named("publicipaddress:list") @Named("publicipaddress:list")

View File

@ -19,32 +19,31 @@ import java.io.Closeable;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.ResourceGroup; import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.PATCH; import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.azurecompute.arm.functions.URIParser; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToJsonPayload;
/** /**
@ -53,9 +52,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
* @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790546.aspx">docs</a> * @see <a href="https://msdn.microsoft.com/en-us/library/azure/dn790546.aspx">docs</a>
*/ */
@Path("/resourcegroups") @Path("/resourcegroups")
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@QueryParams(keys = "api-version", values = "2015-01-01")
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface ResourceGroupApi extends Closeable{ public interface ResourceGroupApi extends Closeable{

View File

@ -17,14 +17,8 @@
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.NullOnNotFoundOr404; import java.io.Closeable;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData; import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -32,8 +26,15 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.io.Closeable;
import java.util.List; import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
/** /**
* The Azure Resource Provider API provides information about a resource provider and its supported resource types. * The Azure Resource Provider API provides information about a resource provider and its supported resource types.
@ -42,8 +43,7 @@ import java.util.List;
*/ */
@Path("/providers") @Path("/providers")
@QueryParams(keys = "api-version", values = "2015-01-01") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface ResourceProviderApi extends Closeable { public interface ResourceProviderApi extends Closeable {

View File

@ -16,15 +16,19 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.POST;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks; import org.jclouds.Fallbacks;
@ -32,35 +36,28 @@ import org.jclouds.azurecompute.arm.domain.Availability;
import org.jclouds.azurecompute.arm.domain.StorageService; import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.StorageServiceKeys; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams; import org.jclouds.azurecompute.arm.domain.StorageServiceUpdateParams;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204; import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.azurecompute.arm.functions.URIParser; import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToJsonPayload;
import java.util.List;
import java.util.Map;
import java.net.URI;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
/** /**
* The Azure Resource Management API includes operations for managing the storage accounts in your subscription. * The Azure Resource Management API includes operations for managing the storage accounts in your subscription.
* *
* @see <a href="https://msdn.microsoft.com/en-us/library/mt163683.aspx">docs</a> * @see <a href="https://msdn.microsoft.com/en-us/library/mt163683.aspx">docs</a>
*/ */
@Path("/") @Path("/")
@RequestFilters(OAuthFilter.class) @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@QueryParams(keys = "api-version", values = STORAGE_API_VERSION)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface StorageAccountApi { public interface StorageAccountApi {

View File

@ -16,20 +16,7 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import java.util.List;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.MapBinder;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -39,12 +26,24 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.List;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks/{virtualnetwork}/subnets") @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks/{virtualnetwork}/subnets")
@QueryParams(keys = "api-version", values = "2015-06-15") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface SubnetApi { public interface SubnetApi {

View File

@ -16,24 +16,24 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import java.util.List;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.List;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VMSize;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
@Path("/providers/Microsoft.Compute/locations/{location}/vmSizes") @Path("/providers/Microsoft.Compute/locations/{location}/vmSizes")
@QueryParams(keys = "api-version", values = "2015-06-15") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface VMSizeApi { public interface VMSizeApi {

View File

@ -16,10 +16,25 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks; import org.jclouds.Fallbacks;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.URIParser; import org.jclouds.azurecompute.arm.functions.URIParser;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Fallback;
@ -32,27 +47,13 @@ import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import java.util.List;
/** /**
* The Virtual Machine API includes operations for managing the virtual machines in your subscription. * The Virtual Machine API includes operations for managing the virtual machines in your subscription.
* *
* @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt163630.aspx">docs</a> * @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt163630.aspx">docs</a>
*/ */
@Path("/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines") @Path("/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines")
@RequestFilters(OAuthFilter.class) @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@QueryParams(keys = "api-version", values = "2015-06-15")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface VirtualMachineApi { public interface VirtualMachineApi {
@ -66,7 +67,7 @@ public interface VirtualMachineApi {
VirtualMachine get(@PathParam("name") String name); VirtualMachine get(@PathParam("name") String name);
/** /**
* The Get Virtual Machine details * Get information about the model view and instance view of a virtual machine:
*/ */
@Named("GetVirtualMachineInstance") @Named("GetVirtualMachineInstance")
@GET @GET

View File

@ -15,22 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; import java.util.List;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Named; import javax.inject.Named;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -40,11 +25,23 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.List;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.functions.FalseOn204;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
@Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks") @Path("/resourcegroups/{resourcegroup}/providers/Microsoft.Network/virtualNetworks")
@QueryParams(keys = "api-version", values = "2015-06-15") @RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@RequestFilters(OAuthFilter.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public interface VirtualNetworkApi { public interface VirtualNetworkApi {

View File

@ -0,0 +1,90 @@
/*
* 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.filters;
import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
import static org.jclouds.util.Maps2.transformKeys;
import static org.jclouds.util.Predicates2.startsWith;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.rest.config.InvocationConfig;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.reflect.Invokable;
/**
* Allow users to customize the api versions for each method call.
* <p>
* In Azure ARM, each method may have its own api version. This filter allows to
* configure the versions of each method, so there is no need to change the code
* when Azure deprecates old versions.
*/
public class ApiVersionFilter implements HttpRequestFilter {
private final InvocationConfig config;
private final Map<String, String> versions;
@Inject
ApiVersionFilter(InvocationConfig config, Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
this.config = config;
this.versions = versions(filterStringsBoundByName);
}
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
checkArgument(request instanceof GeneratedHttpRequest,
"This filter can only be applied to GeneratedHttpRequest objects");
GeneratedHttpRequest generatedRequest = (GeneratedHttpRequest) request;
// Look if there is a custom api version for the current method
String commandName = config.getCommandName(generatedRequest.getInvocation());
String customApiVersion = versions.get(commandName);
if (customApiVersion == null) {
// No custom config for the specific method. Let's look for custom
// config for the class
Invokable<?, ?> invoked = generatedRequest.getInvocation().getInvokable();
String className = invoked.getOwnerType().getRawType().getSimpleName();
customApiVersion = versions.get(className);
}
if (customApiVersion != null) {
return request.toBuilder().replaceQueryParam("api-version", customApiVersion).build();
}
return request;
}
private static Map<String, String> versions(Function<Predicate<String>, Map<String, String>> filterStringsBoundByName) {
Map<String, String> stringBoundWithApiVersionPrefix = filterStringsBoundByName
.apply(startsWith(API_VERSION_PREFIX));
return transformKeys(stringBoundWithApiVersionPrefix, new Function<String, String>() {
public String apply(String input) {
return input.replaceFirst(API_VERSION_PREFIX, "");
}
});
}
}

View File

@ -16,125 +16,161 @@
*/ */
package org.jclouds.azurecompute.arm.functions; package org.jclouds.azurecompute.arm.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import static org.jclouds.util.Closeables2.closeQuietly;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import com.google.common.base.Predicate;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.Deployment; import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard; import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCard;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.arm.domain.ResourceGroup;
import org.jclouds.azurecompute.arm.domain.PublicIPAddress; import org.jclouds.azurecompute.arm.domain.StorageServiceKeys;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.util.BlobHelper;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import java.net.URI; import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@Singleton @Singleton
public class CleanupResources implements Function<String, Boolean> { public class CleanupResources implements Function<String, Boolean> {
private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
protected final AzureComputeApi api; protected final AzureComputeApi api;
private Predicate<URI> nodeTerminated; private final Predicate<URI> resourceDeleted;
private Predicate<URI> resourceDeleted; private final StorageProfileToStorageAccountName storageProfileToStorageAccountName;
@Inject @Inject
public CleanupResources(AzureComputeApi azureComputeApi, CleanupResources(AzureComputeApi azureComputeApi, @Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted,
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants, StorageProfileToStorageAccountName storageProfileToStorageAccountName) {
@Named(TIMEOUT_NODE_TERMINATED) Predicate<URI> nodeTerminated,
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted) {
this.azureComputeConstants = azureComputeConstants;
this.api = azureComputeApi; this.api = azureComputeApi;
this.nodeTerminated = nodeTerminated;
this.resourceDeleted = resourceDeleted; this.resourceDeleted = resourceDeleted;
this.storageProfileToStorageAccountName = storageProfileToStorageAccountName;
} }
@Override @Override
public Boolean apply(String id) { public Boolean apply(final String id) {
logger.debug(">> destroying %s ...", id);
logger.debug("Destroying %s ...", id); Map<String, VirtualMachine> resourceGroupNamesAndVirtualMachines = getResourceGroupNamesAndVirtualMachines(id);
String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor"; if (resourceGroupNamesAndVirtualMachines.isEmpty())
String group = azureComputeConstants.azureResourceGroup(); return true;
VirtualMachine vm = api.getVirtualMachineApi(group).get(id); String group = checkNotNull(resourceGroupNamesAndVirtualMachines.entrySet().iterator().next().getKey(),
if (vm != null) { "resourceGroup name must not be null");
URI uri = api.getVirtualMachineApi(group).delete(id); VirtualMachine virtualMachine = checkNotNull(resourceGroupNamesAndVirtualMachines.get(group),
if (uri != null) { "virtualMachine must not be null");
boolean jobDone = nodeTerminated.apply(uri);
boolean storageAcctDeleteStatus = false;
boolean deploymentDeleteStatus = false;
if (jobDone) { boolean vmDeleted = deleteVirtualMachine(group, virtualMachine);
Deployment deployment = api.getDeploymentApi(group).get(id);
if (deployment != null) { // We don't delete the network here, as it is global to the resource
uri = api.getDeploymentApi(group).delete(id); // group. It will be deleted when the resource group is deleted
jobDone = resourceDeleted.apply(uri);
if (jobDone) { for (String nicName : getNetworkCardInterfaceNames(virtualMachine)) {
deploymentDeleteStatus = true; NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(nicName);
Iterable<String> publicIps = getPublicIps(group, nic);
logger.debug(">> destroying nic %s...", nicName);
URI nicDeletionURI = api.getNetworkInterfaceCardApi(group).delete(nicName);
resourceDeleted.apply(nicDeletionURI);
for (String publicIp : publicIps) {
logger.debug(">> deleting public ip nic %s...", publicIp);
api.getPublicIPAddressApi(group).delete(publicIp);
} }
} else {
deploymentDeleteStatus = true;
}
NetworkInterfaceCard nic = api.getNetworkInterfaceCardApi(group).get(id + "nic");
if (nic != null) {
uri = api.getNetworkInterfaceCardApi(group).delete(id + "nic");
if (uri != null) {
jobDone = resourceDeleted.apply(uri);
if (jobDone) {
boolean ipDeleteStatus = false;
PublicIPAddress ip = api.getPublicIPAddressApi(group).get(id + "publicip");
if (ip != null) {
ipDeleteStatus = api.getPublicIPAddressApi(group).delete(id + "publicip");
} else {
ipDeleteStatus = true;
} }
// Get NSG String storageAccountName = storageProfileToStorageAccountName.apply(virtualMachine.properties().storageProfile());
boolean nsgDeleteStatus = false; StorageServiceKeys keys = api.getStorageAccountApi(group).getKeys(storageAccountName);
NetworkSecurityGroup nsg = api.getNetworkSecurityGroupApi(group).get(id + "nsg");
if (nsg != null) {
uri = api.getNetworkSecurityGroupApi(group).delete(id + "nsg");
jobDone = resourceDeleted.apply(uri);
if (jobDone) {
nsgDeleteStatus = true;
// Remove the virtual machine files
logger.debug(">> deleting virtual machine disk storage...");
BlobHelper blobHelper = new BlobHelper(storageAccountName, keys.key1());
try {
blobHelper.deleteContainerIfExists("vhds");
if (!blobHelper.customImageExists()) {
logger.debug(">> deleting storage account %s...", storageAccountName);
api.getStorageAccountApi(group).delete(storageAccountName);
} else {
logger.debug(">> the storage account contains custom images. Will not delete it!");
} }
} } finally {
else { closeQuietly(blobHelper);
nsgDeleteStatus = true;
} }
return deploymentDeleteStatus && storageAcctDeleteStatus && ipDeleteStatus && nsgDeleteStatus; deleteResourceGroupIfEmpty(group);
} else {
return false; return vmDeleted;
} }
} else {
return false; public void deleteResourceGroupIfEmpty(String group) {
if (api.getVirtualMachineApi(group).list().isEmpty()
&& api.getStorageAccountApi(group).list().isEmpty()
&& api.getNetworkInterfaceCardApi(group).list().isEmpty()
&& api.getPublicIPAddressApi(group).list().isEmpty()) {
logger.debug(">> the resource group %s is empty. Deleting...", group);
resourceDeleted.apply(api.getResourceGroupApi().delete(group));
} }
} else {
return false;
} }
} else {
return false; 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();
} }
} else { }), notNull()), new Function<IdReference, String>() {
return false; @Override
public String apply(IdReference input) {
return Iterables.getLast(Splitter.on("/").split(input.id()));
} }
} else { });
return false;
} }
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()));
}
private Map<String, VirtualMachine> getResourceGroupNamesAndVirtualMachines(String id) {
for (ResourceGroup resourceGroup : api.getResourceGroupApi().list()) {
String group = resourceGroup.name();
VirtualMachine virtualMachine = api.getVirtualMachineApi(group).get(id);
if (virtualMachine != null) {
return ImmutableMap.of(group, virtualMachine);
}
}
return Maps.newHashMap();
} }
} }

View File

@ -0,0 +1,38 @@
/*
* 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.functions;
import java.net.URI;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
/**
* Returns the storage account name for a given storage profile.
*/
public class StorageProfileToStorageAccountName implements Function<StorageProfile, String> {
@Override
public String apply(StorageProfile input) {
String storageAccountNameURI = input.osDisk().vhd().uri();
return Iterables.get(Splitter.on(".").split(URI.create(storageAccountNameURI).getHost()), 0);
}
}

View File

@ -16,76 +16,68 @@
*/ */
package org.jclouds.azurecompute.arm.util; package org.jclouds.azurecompute.arm.util;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jclouds.ContextBuilder; import org.jclouds.ContextBuilder;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azureblob.AzureBlobClient; import org.jclouds.azureblob.AzureBlobClient;
import org.jclouds.azureblob.domain.BlobProperties; import org.jclouds.azureblob.domain.BlobProperties;
import org.jclouds.azureblob.domain.ContainerProperties; import org.jclouds.azureblob.domain.ContainerProperties;
import org.jclouds.azureblob.domain.ListBlobsResponse; import org.jclouds.azureblob.domain.ListBlobsResponse;
import org.jclouds.azurecompute.arm.domain.VMImage; import org.jclouds.azurecompute.arm.domain.VMImage;
import org.jclouds.util.Closeables2;
public class BlobHelper { public class BlobHelper implements Closeable {
public static void deleteContainerIfExists(String storage, String key, String containerName) { private final String storageAccount;
final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob") private final AzureBlobClient azureBlob;
.credentials(storage, key)
public BlobHelper(String storageAccount, String key) {
this.storageAccount = storageAccount;
this.azureBlob = ContextBuilder.newBuilder("azureblob").credentials(storageAccount, key)
.buildApi(AzureBlobClient.class); .buildApi(AzureBlobClient.class);
}
try { @Override
public void close() throws IOException {
closeQuietly(azureBlob);
}
public void deleteContainerIfExists(String containerName) {
azureBlob.deleteContainer(containerName); azureBlob.deleteContainer(containerName);
} }
finally {
Closeables2.closeQuietly(azureBlob); public boolean hasContainers() {
} return !azureBlob.listContainers().isEmpty();
} }
public static boolean customImageExists(String storage, String key) { public boolean customImageExists() {
final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
.credentials(storage, key)
.buildApi(AzureBlobClient.class);
try {
return azureBlob.containerExists("system"); return azureBlob.containerExists("system");
} }
finally {
Closeables2.closeQuietly(azureBlob);
}
}
public static List<VMImage> getImages(String containerName, String group,
String storageAccountName, String key, String offer, String location) {
final AzureBlobClient azureBlob = ContextBuilder.newBuilder("azureblob")
.credentials(storageAccountName, key)
.buildApi(AzureBlobClient.class);
public List<VMImage> getImages(String containerName, String group, String offer, String location) {
List<VMImage> list = new ArrayList<VMImage>(); List<VMImage> list = new ArrayList<VMImage>();
try {
BoundedSet<ContainerProperties> containerList = azureBlob.listContainers();
for (ContainerProperties props : containerList) {
if (props.getName().equals("system")) {
ListBlobsResponse blobList = azureBlob.listBlobs("system");
String osDisk = "";
String dataDisk = "";
ContainerProperties systemContainer = azureBlob.getContainerProperties("system");
if (systemContainer != null) {
ListBlobsResponse blobList = azureBlob.listBlobs(systemContainer.getName());
for (BlobProperties blob : blobList) { for (BlobProperties blob : blobList) {
String name = blob.getName(); String name = blob.getName();
if (dataDisk.length() == 0) dataDisk = name.substring(1 + name.lastIndexOf('/')); if (name.contains("-osDisk")) {
else if (osDisk.length() == 0) osDisk = name.substring(1 + name.lastIndexOf('/')); String imageName = name.substring(name.lastIndexOf('/') + 1, name.indexOf("-osDisk"));
} String imageUrl = blob.getUrl().toString();
final VMImage ref = VMImage.create(group, storageAccountName, osDisk, dataDisk, "test-create-image", "custom", location);
list.add(ref); list.add(VMImage.customImage().group(group).storage(storageAccount).vhd1(imageUrl).name(imageName)
.offer(offer).location(location).build());
} }
} }
} }
finally {
Closeables2.closeQuietly(azureBlob);
}
return list; return list;
} }
} }

View File

@ -1,573 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.domain.DeploymentTemplate;
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
import org.jclouds.azurecompute.arm.domain.DnsSettings;
import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.KeyVaultReference;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
import org.jclouds.azurecompute.arm.domain.TemplateParameterType;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.compute.domain.Template;
import org.jclouds.json.Json;
import org.jclouds.predicates.Validator;
import org.jclouds.predicates.validators.DnsNameValidator;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import static com.google.common.io.BaseEncoding.base64;
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.STORAGE_API_VERSION;
public class DeploymentTemplateBuilder {
public interface Factory {
DeploymentTemplateBuilder create(@Assisted("group") String group, @Assisted("name") String name, Template template);
}
private final String name;
private final String azureGroup;
private final String group;
private final Template template;
private final Json json;
private AzureTemplateOptions options;
private Iterable<String> tags;
private Map<String, String> userMetaData;
private List<ResourceDefinition> resources;
private Map<String, String> variables;
private static String loginUser;
private static String loginPassword;
private String location;
private AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
private static final String DEPLOYMENT_MODE = "Incremental";
@Inject
DeploymentTemplateBuilder(Json json, @Assisted("group") String group, @Assisted("name") String name, @Assisted Template template,
final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
this.name = name;
this.group = group;
this.template = template;
this.options = template.getOptions().as(AzureTemplateOptions.class);
this.tags = template.getOptions().getTags();
this.userMetaData = template.getOptions().getUserMetadata();
this.variables = new HashMap<String, String>();
this.resources = new ArrayList<ResourceDefinition>();
this.location = template.getLocation().getId();
this.json = json;
this.azureComputeConstants = azureComputeConstants;
this.azureGroup = this.azureComputeConstants.azureResourceGroup();
String[] defaultLogin = this.azureComputeConstants.azureDefaultImageLogin().split(":");
String defaultUser = null;
String defaultPassword = null;
if (defaultLogin.length == 2) {
defaultUser = defaultLogin[0].trim();
defaultPassword = defaultLogin[1].trim();
}
loginUser = options.getLoginUser() == null ? defaultUser : options.getLoginUser();
loginPassword = options.getLoginPassword() == null ? defaultPassword : options.getLoginPassword();
}
public static String getLoginUserUsername() {
return loginUser;
}
public static String getLoginPassword() {
return loginPassword;
}
public Template getTemplate() {
return template;
}
public DeploymentBody getDeploymentTemplate() {
addStorageResource();
addPublicIpAddress();
addNetworkSecurityGroup();
addNetworkInterfaceCard();
addVirtualMachine();
DeploymentTemplate.TemplateParameters templateParameters = null;
DeploymentTemplate.Parameters parameters = null;
if (keyVaultInUse()){
String[] keyVaultInfo = options.getKeyVaultIdAndSecret().split(":");
Preconditions.checkArgument(keyVaultInfo.length == 2);
String vaultId = keyVaultInfo[0].trim();
String secretName = keyVaultInfo[1].trim();
templateParameters = DeploymentTemplate.TemplateParameters.create(TemplateParameterType.create("securestring"));
parameters = DeploymentTemplate.Parameters.create(KeyVaultReference.create(KeyVaultReference.Reference.create(IdReference.create(vaultId), secretName)));
} else {
templateParameters = DeploymentTemplate.TemplateParameters.create(null);
parameters = DeploymentTemplate.Parameters.create(null);
}
DeploymentTemplate template = DeploymentTemplate.builder()
.schema("https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#")
.contentVersion("1.0.0.0")
.resources(resources)
.variables(variables)
.parameters(templateParameters)
.build();
DeploymentBody body = DeploymentBody.create(template, DEPLOYMENT_MODE, parameters);
return body;
}
public String getDeploymentTemplateJson(DeploymentProperties properties) {
return json.toJson(properties);
}
private void addStorageResource() {
String storageAccountName = null;
String imageName = template.getImage().getName();
if (imageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
storageAccountName = template.getImage().getVersion();
}
if (Strings.isNullOrEmpty(storageAccountName)) {
storageAccountName = generateStorageAccountName(name);
}
Validator<String> validator = new DnsNameValidator(3, 24);
validator.validate(storageAccountName);
variables.put("storageAccountName", storageAccountName);
ResourceDefinition storageAccount = ResourceDefinition.builder()
.name("[variables('storageAccountName')]")
.type("Microsoft.Storage/storageAccounts")
.location(location)
.apiVersion(STORAGE_API_VERSION)
.properties(
StorageServiceProperties.builder()
.accountType(StorageService.AccountType.Standard_LRS)
.build()
)
.build();
resources.add(storageAccount);
}
private void addPublicIpAddress() {
String publicIPAddressName = name + "publicip";
String dnsLabelPrefix = options.getDNSLabelPrefix();
PublicIPAddressProperties.Builder properties = PublicIPAddressProperties.builder();
if (!Strings.isNullOrEmpty(dnsLabelPrefix)) {
properties.dnsSettings(DnsSettings.builder().domainNameLabel(dnsLabelPrefix).build());
variables.put("dnsLabelPrefix", dnsLabelPrefix);
}
properties.publicIPAllocationMethod("Dynamic");
variables.put("publicIPAddressName", publicIPAddressName);
variables.put("publicIPAddressReference", "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]");
ResourceDefinition publicIpAddress = ResourceDefinition.builder()
.name("[variables('publicIPAddressName')]")
.type("Microsoft.Network/publicIPAddresses")
.location(location)
.apiVersion(STORAGE_API_VERSION)
.properties(properties.build())
.build();
resources.add(publicIpAddress);
}
private void addNetworkInterfaceCard() {
List<IpConfiguration> ipConfigurations = new ArrayList<IpConfiguration>();
String ipConfigurationName = name + "ipconfig";
String subnetId = options.getSubnetId();
String vnetName = options.getVirtualNetworkName();
variables.put("ipConfigurationName", ipConfigurationName);
variables.put("subnetReference", subnetId);
IpConfiguration ipConfig = IpConfiguration.create(ipConfigurationName, null, null, null,
IpConfigurationProperties.builder()
.privateIPAllocationMethod("Dynamic")
.publicIPAddress(IdReference.create("[variables('publicIPAddressReference')]"))
.subnet(IdReference.create("[variables('subnetReference')]"))
.build());
ipConfigurations.add(ipConfig);
// Check to see if we have defined a network security group
IdReference networkSecurityGroup = null;
int ports[] = options.getInboundPorts();
if ((ports != null) && (ports.length > 0)) {
networkSecurityGroup = IdReference.create("[variables('networkSecurityGroupNameReference')]");
}
ArrayList<String> depends = new ArrayList<String>(Arrays.asList("[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"));
NetworkInterfaceCardProperties.Builder networkInterfaceCardPropertiesBuilder = NetworkInterfaceCardProperties.builder();
networkInterfaceCardPropertiesBuilder.ipConfigurations(ipConfigurations);
if (networkSecurityGroup != null) {
networkInterfaceCardPropertiesBuilder.networkSecurityGroup(networkSecurityGroup);
depends.add("[concat('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]");
}
NetworkInterfaceCardProperties networkInterfaceCardProperties = networkInterfaceCardPropertiesBuilder.build();
String networkInterfaceCardName = name + "nic";
variables.put("networkInterfaceCardName", networkInterfaceCardName);
variables.put("networkInterfaceCardReference", "[resourceId('Microsoft.Network/networkInterfaces',variables('networkInterfaceCardName'))]");
ResourceDefinition networkInterfaceCard = ResourceDefinition.builder()
.name("[variables('networkInterfaceCardName')]")
.type("Microsoft.Network/networkInterfaces")
.location(location)
.apiVersion(STORAGE_API_VERSION)
.dependsOn(depends)
.properties(networkInterfaceCardProperties)
.build();
resources.add(networkInterfaceCard);
}
private void addNetworkSecurityGroup() {
int inboundPorts[] = options.getInboundPorts();
if ((inboundPorts != null) && (inboundPorts.length > 0)) {
variables.put("networkSecurityGroupName", name + "nsg");
variables.put("networkSecurityGroupNameReference", "[resourceId('Microsoft.Network/networkSecurityGroups',variables('networkSecurityGroupName'))]");
List<String> portRanges = simplifyPorts(inboundPorts);
List<NetworkSecurityRule> rules = new ArrayList<NetworkSecurityRule>();
int priority = 1234;
for (String portRange : portRanges) {
NetworkSecurityRuleProperties ruleProperties = NetworkSecurityRuleProperties.builder()
.description("default-allow-port-" + portRange)
.protocol(NetworkSecurityRuleProperties.Protocol.All)
.access(NetworkSecurityRuleProperties.Access.Allow)
.sourcePortRange("*")
.destinationPortRange(portRange)
.sourceAddressPrefix("*")
.destinationAddressPrefix("*")
.priority(priority)
.direction(NetworkSecurityRuleProperties.Direction.Inbound)
.build();
NetworkSecurityRule networkSecurityRule = NetworkSecurityRule.create(
"default-allow-port-" + portRange,
null,
null,
ruleProperties);
rules.add(networkSecurityRule);
priority++;
}
NetworkSecurityGroupProperties networkSecurityGroupProperties = NetworkSecurityGroupProperties.builder()
.securityRules(rules)
.build();
ResourceDefinition networkSecurityGroup = ResourceDefinition.builder()
.name("[variables('networkSecurityGroupName')]")
.type("Microsoft.Network/networkSecurityGroups").location(location)
.apiVersion(STORAGE_API_VERSION)
.properties(networkSecurityGroupProperties)
.build();
resources.add(networkSecurityGroup);
}
}
/**
* Helper function for simplifying an array of ports to a list of ranges as list of strings
* @param ports array of int
* @return list of strings representing ranges
*/
public static List<String> simplifyPorts(int[] ports) {
Preconditions.checkArgument(ports != null && ports.length != 0);
ArrayList<String> output = new ArrayList<String>();
Arrays.sort(ports);
int range_start = ports[0];
int range_end = ports[0];
for (int i = 1; i < ports.length; i++) {
if ((ports[i - 1] == ports[i] - 1) || (ports[i - 1] == ports[i])){
// Range continues.
range_end = ports[i];
}
else {
// Range ends.
output.add(formatRange(range_start, range_end));
range_start = ports[i];
range_end = ports[i];
}
}
// Make sure we get the last range.
output.add(formatRange(range_start, range_end));
return output;
}
private static String formatRange(int start, int finish) {
if (start == finish){
return Integer.toString(start);
}
else {
return String.format("%s-%s", Integer.toString(start), Integer.toString(finish));
}
}
private void addVirtualMachine() {
//Build OS Profile
final String computerName = name + "pc";
variables.put("loginUser", loginUser);
OSProfile.Builder profileBuilder = OSProfile.builder()
.adminUsername(loginUser)
.computerName(computerName);
profileBuilder.adminPassword(loginPassword);
//boolean usePublicKey = options.getPublicKey() != null;
if (keyVaultInUse()) {
OSProfile.LinuxConfiguration configuration = OSProfile.LinuxConfiguration.create("false",
OSProfile.LinuxConfiguration.SSH.create(Arrays.asList(
OSProfile.LinuxConfiguration.SSH.SSHPublicKey.create(
"[concat('/home/',variables('loginUser'),'/.ssh/authorized_keys')]",
"[parameters('publicKeyFromAzureKeyVault')]"
))
));
profileBuilder.linuxConfiguration(configuration);
}
if (!Strings.isNullOrEmpty(options.getCustomData())){
String encodedCustomData = base64().encode(options.getCustomData().getBytes());
profileBuilder.customData(encodedCustomData);
}
OSProfile osProfile = profileBuilder.build();
//Build OsDisk
final String storageAccountContainerName = name + "vhds";
variables.put("storageAccountContainerName", storageAccountContainerName);
final String osDiskName = name + "osdisk";
variables.put("osDiskName", osDiskName);
boolean usingMarketplaceImage = true;
String cusotomImageUri = "";
// Handle custom image case if description starts with CUSTOM_IMAGE_PREFIX
String vhd1 = template.getImage().getProviderId();
String description = template.getImage().getDescription();
if (description.substring(0, CUSTOM_IMAGE_PREFIX.length()).equals(CUSTOM_IMAGE_PREFIX)) {
String storageName = template.getImage().getVersion();
cusotomImageUri = vhd1;
cusotomImageUri = "https://" + storageName + ".blob.core.windows.net/system/Microsoft.Compute/Images/" + AzureComputeImageExtension.CONTAINER_NAME + "/" + cusotomImageUri;
}
if (!cusotomImageUri.isEmpty()) {
usingMarketplaceImage = false;
}
OSDisk osDisk = getOsDisk("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('osDiskName'),'.vhd')]", cusotomImageUri);
//Create Data Disk(s) and add to list
final String dataDiskName = name + "datadisk";
variables.put("dataDiskName", dataDiskName);
List<DataDisk> dataDisks = new ArrayList<DataDisk>();
DataDisk dataDisk = DataDisk.builder()
.name("[variables('dataDiskName')]")
.diskSizeGB(azureComputeConstants.azureDefaultDataDiskSizeProperty())
.lun(0)
.vhd(
VHD.create("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('dataDiskName'),'.vhd')]")
)
.createOption("Empty")
.build();
dataDisks.add(dataDisk);
//Create Storage Profile
StorageProfile.Builder storageProfileBuilder = StorageProfile.builder()
.osDisk(osDisk)
.dataDisks(dataDisks);
if (usingMarketplaceImage) {
//Build Image Reference if marketplace image is used
ImageReference imageReference = getImageReference(template.getImage().getProviderId(),
template.getImage().getName(),
template.getImage().getVersion());
storageProfileBuilder.imageReference(imageReference);
}
StorageProfile storageProfile = storageProfileBuilder.build();
//Create Network Profile for this VM (links to network interface cards)
NetworkProfile networkProfile = NetworkProfile.create(
Arrays.asList(
IdReference.create("[variables('networkInterfaceCardReference')]")
));
//Boot Diagnostics
DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(
DiagnosticsProfile.BootDiagnostics.builder()
.enabled(true)
.storageUri("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net')]")
.build());
//Build VirtualMachine properties based on above properties.
final String vmSize = template.getHardware().getId();
HardwareProfile hw = HardwareProfile.create(vmSize);
VirtualMachineProperties properties = VirtualMachineProperties.builder()
.hardwareProfile(hw)
.osProfile(osProfile)
.storageProfile(storageProfile)
.networkProfile(networkProfile)
.diagnosticsProfile(diagnosticsProfile)
.build();
String tagString = Joiner.on(",").join(Lists.newArrayList(tags));
if (tagString.isEmpty())
tagString = "jclouds";
userMetaData.put("tags", tagString);
variables.put("virtualMachineName", name);
ResourceDefinition virtualMachine = ResourceDefinition.builder()
.name("[variables('virtualMachineName')]")
.type("Microsoft.Compute/virtualMachines")
.location(location)
.apiVersion("2015-06-15")
.dependsOn(Arrays.asList("[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceCardName'))]"))
.tags(userMetaData)
.properties(properties)
.build();
resources.add(virtualMachine);
}
private ImageReference getImageReference(String publisher, String offer, String sku) {
return ImageReference.builder()
.publisher(publisher)
.offer(offer)
.sku(sku)
.version("latest")
.build();
}
private OSDisk getOsDisk(String vhdUri, String imageUri) {
OSDisk.Builder builder = OSDisk.builder();
builder.name("[variables('osDiskName')]");
builder.caching("ReadWrite");
builder.createOption("FromImage");
builder.vhd(VHD.create(vhdUri));
if (!imageUri.isEmpty()) {
builder.osType("Linux");
builder.image(VHD.create(imageUri));
}
return builder.build();
}
private boolean keyVaultInUse(){
return !Strings.isNullOrEmpty(options.getKeyVaultIdAndSecret());
}
/**
* Generates a valid storage account
*
* Storage account names must be between 3 and 24 characters in length and may contain numbers and lowercase letters only.
*
* @param name the node name
* @return the storage account name starting from a sanitized name (with only numbers and lowercase letters only ).
* If sanitized name is between 3 and 24 characters, storage account name is equals to sanitized name.
* If sanitized name is less than 3 characters, storage account is sanitized name plus 4 random chars.
* If sanitized name is more than 24 characters, storage account is first 10 chars of sanitized name plus 4 random chars plus last 10 chars of sanitized name.
*/
private static String generateStorageAccountName(String name) {
String storageAccountName = name.replaceAll("[^a-z0-9]", "");
int nameLength = storageAccountName.length();
if (nameLength >= 3 && nameLength <= 24) {
return storageAccountName;
}
String random = UUID.randomUUID().toString().replaceAll("[^a-z0-9]", "").substring(0, 4);
if (nameLength < 3) {
storageAccountName = new StringBuilder().append(storageAccountName).append(random).toString();
}
if (nameLength > 24) {
storageAccountName = shorten(storageAccountName, random);
}
return storageAccountName;
}
private static String shorten(String storageAccountName, String random) {
String prefix = storageAccountName.substring(0, 10);
String suffix = storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length());
return String.format("%s%s%s", prefix, random, suffix);
}
}

View File

@ -20,7 +20,6 @@ import java.util.EnumSet;
public class GetEnumValue { public class GetEnumValue {
@SuppressWarnings("unchecked")
public static <T extends Enum<T>> Enum<T> fromValueOrDefault(String text, Enum<T> defaultValue) { public static <T extends Enum<T>> Enum<T> fromValueOrDefault(String text, Enum<T> defaultValue) {
if (text != null) { if (text != null) {
EnumSet<T> elements = EnumSet.allOf(defaultValue.getDeclaringClass()); EnumSet<T> elements = EnumSet.allOf(defaultValue.getDeclaringClass());

View File

@ -16,21 +16,26 @@
*/ */
package org.jclouds.azurecompute.arm.compute; package org.jclouds.azurecompute.arm.compute;
import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeServiceLiveTest; import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.config.LoggingModule; import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
@ -41,29 +46,18 @@ import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module; import com.google.inject.Module;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
/** /**
* Live tests for the {@link org.jclouds.compute.ComputeService} integration. * Live tests for the {@link org.jclouds.compute.ComputeService} integration.
*/ */
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest") @Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest")
public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest { public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
protected int nonBlockDurationSeconds = 30;
public AzureComputeServiceLiveTest() { public AzureComputeServiceLiveTest() {
provider = "azurecompute-arm"; provider = "azurecompute-arm";
nonBlockDurationSeconds = 300;
group = "az-u";
} }
@Override @Override
@ -78,21 +72,20 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override @Override
protected ProviderMetadata createProviderMetadata() { protected ProviderMetadata createProviderMetadata() {
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build(); return AzureComputeProviderMetadata.builder().build();
return pm;
} }
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES); String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + ""); properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + ""); properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + ""); properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + ""); properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + ""); properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
properties.put(RESOURCE_GROUP_NAME, "a4"); properties.put(RESOURCE_GROUP_NAME, "jc");
properties.put(TEMPLATE, "locationId=westeurope"); properties.put(PROPERTY_REGIONS, "eastus");
properties.put(IMAGE_PUBLISHERS, "Canonical"); properties.put(IMAGE_PUBLISHERS, "Canonical");
AzureLiveTestUtils.defaultProperties(properties); AzureLiveTestUtils.defaultProperties(properties);
@ -102,24 +95,27 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
} }
@Override @Override
protected Template refreshTemplate() { protected TemplateBuilder templateBuilder() {
return this.template = addRunScriptToTemplate(this.buildTemplate(this.client.templateBuilder())); return super.templateBuilder().options(
authorizePublicKey(keyPair.get("public")).overrideLoginPrivateKey(keyPair.get("private")));
} }
@Override @Override
protected Template addRunScriptToTemplate(Template template) { protected Template addRunScriptToTemplate(Template template) {
template.getOptions().runScript(Statements.newStatementList(new Statement[]{AdminAccess.standard(), Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()})); template.getOptions().runScript(
Statements.newStatementList(new Statement[] { AdminAccess.standard(), Statements.exec("sleep 50"),
InstallJDK.fromOpenJDK() }));
return template; return template;
} }
@Override @Override
@Test( enabled = false) protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
protected void weCanCancelTasks(NodeMetadata node) throws InterruptedException, ExecutionException { // User metadata not yet supported
return;
} }
@Override @Override
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(String group, OperatingSystem os, LoginCredentials creds) throws RunScriptOnNodesException { protected void checkTagsInNodeEquals(NodeMetadata node, ImmutableSet<String> tags) {
return this.client.runScriptOnNodesMatching(NodePredicates.runningInGroup(group), Statements.newStatementList(Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()), org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials(creds).nameTask("runScriptWithCreds")); // Tags not yet supported
} }
} }

View File

@ -16,33 +16,30 @@
*/ */
package org.jclouds.azurecompute.arm.compute; package org.jclouds.azurecompute.arm.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.domain.Region;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils; import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest; import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module; import com.google.inject.Module;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
@Test(groups = "live", testName = "AzureTemplateBuilderLiveTest") @Test(groups = "live", testName = "AzureTemplateBuilderLiveTest")
public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest { public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
public String azureGroup;
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.of("US-IA", "US-VA", "US-IL", "US-TX", "US-CA", "IE", "NL", "HK", "SG", "JP-11", "JP-27", "BR", "AU-NSW", "AU-VIC", "IN-GA", "IN-TN", "IN-MH", "CN-SH", "CN-BJ", "CA-ON", "CA-QC");
}
public AzureTemplateBuilderLiveTest() { public AzureTemplateBuilderLiveTest() {
provider = "azurecompute-arm"; provider = "azurecompute-arm";
@ -55,23 +52,33 @@ public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
@Override @Override
protected ProviderMetadata createProviderMetadata() { protected ProviderMetadata createProviderMetadata() {
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build(); return AzureComputeProviderMetadata.builder().build();
return pm;
} }
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
azureGroup = "jc" + System.getProperty("user.name").substring(0, 3);
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
long scriptTimeout = TimeUnit.MILLISECONDS.convert(20, TimeUnit.MINUTES); properties.put(RESOURCE_GROUP_NAME, "jc");
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
properties.put(RESOURCE_GROUP_NAME, azureGroup);
AzureLiveTestUtils.defaultProperties(properties); AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties; return properties;
}
@Override
@Test
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = view.getComputeService().templateBuilder().build();
assertTrue(defaultTemplate.getImage().getOperatingSystem().getVersion().matches("1[45]\\.[01][04]\\.[0-9]-LTS"),
"Version mismatch, expected dd.dd.d-LTS, found: " + defaultTemplate.getImage().getOperatingSystem().getVersion());
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
@Override
protected Set<String> getIso3166Codes() {
return Region.iso3166Codes();
} }
} }

View File

@ -16,29 +16,35 @@
*/ */
package org.jclouds.azurecompute.arm.compute.extensions; package org.jclouds.azurecompute.arm.compute.extensions;
import com.google.inject.Module;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.config.AzureComputeProperties;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME; import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.RESOURCE_GROUP_NAME;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.inject.Module;
/** /**
* Live tests for the {@link org.jclouds.compute.extensions.ImageExtension} integration. * Live tests for the {@link org.jclouds.compute.extensions.ImageExtension}
* integration.
*/ */
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest") @Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest { public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
@ -57,34 +63,33 @@ public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTe
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties properties = super.setupProperties(); Properties properties = super.setupProperties();
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES); String defaultTimeout = String.valueOf(TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES));
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + ""); properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + ""); properties.setProperty(TIMEOUT_NODE_RUNNING, defaultTimeout);
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + ""); properties.setProperty(TIMEOUT_PORT_OPEN, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + ""); properties.setProperty(TIMEOUT_NODE_TERMINATED, defaultTimeout);
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + ""); properties.setProperty(TIMEOUT_NODE_SUSPENDED, defaultTimeout);
properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup"); properties.put(RESOURCE_GROUP_NAME, "jc");
properties.put(PROPERTY_REGIONS, "eastus");
properties.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000); properties.put(IMAGE_PUBLISHERS, "Canonical");
properties.put(ComputeServiceProperties.POLL_MAX_PERIOD, 10000);
properties.setProperty(AzureComputeProperties.OPERATION_TIMEOUT, "46000000");
properties.setProperty(AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD, "5");
properties.setProperty(AzureComputeProperties.OPERATION_POLL_MAX_PERIOD, "15");
properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
AzureLiveTestUtils.defaultProperties(properties); AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint"); checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
return properties; return properties;
} }
@Override @Override
protected ProviderMetadata createProviderMetadata() { protected ProviderMetadata createProviderMetadata() {
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build(); return AzureComputeProviderMetadata.builder().build();
return pm;
} }
@Override
public TemplateBuilder getNodeTemplate() {
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
return super.getNodeTemplate().options(
authorizePublicKey(keyPair.get("public"))
.overrideLoginPrivateKey(keyPair.get("private")));
}
} }

View File

@ -16,30 +16,19 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions; import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.Deployment; import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState; import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.domain.Subnet; import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork; import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest; import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.util.Predicates2; import org.jclouds.util.Predicates2;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
@ -49,10 +38,6 @@ import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.net.UrlEscapers; import com.google.common.net.UrlEscapers;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
@Test(testName = "DeploymentApiLiveTest", singleThreaded = true) @Test(testName = "DeploymentApiLiveTest", singleThreaded = true)
public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest { public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
@ -112,37 +97,6 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
return body; return body;
} }
private Template getTemplate(TemplateOptions options) {
Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description("West Europe").parent(provider).build();
OperatingSystem os = OperatingSystem.builder()
.family(OsFamily.UBUNTU)
.description("14.04.3-LTS")
.is64Bit(true)
.build();
Image image = (new ImageBuilder())
.id("UbuntuServer14.04.3-LTS")
.providerId("Canonical")
.name("UbuntuServer")
.description("14.04.3-LTS")
.version("14.04.3-LTS")
.operatingSystem(os)
.status(Image.Status.AVAILABLE)
.location(region)
.build();
Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
return new TemplateImpl(image, hardware, region, options);
}
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
Template template = getTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
return templateBuilder;
}
@Test @Test
public void testValidate(){ public void testValidate(){
Deployment deploymentInvalid = null; Deployment deploymentInvalid = null;
@ -168,12 +122,40 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
AzureTemplateOptions options = new AzureTemplateOptions(); AzureTemplateOptions options = new AzureTemplateOptions();
options.authorizePublicKey(rsakey); options.authorizePublicKey(rsakey);
options.subnetId(subnetId); options.subnetId(subnetId);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody); String deploymentTemplate = "{\n" +
" \"id\": \"/subscriptions/04f7ec88-8e28-41ed-8537-5e17766001f5/resourceGroups/jims216group/providers/Microsoft.Resources/deployments/jcdep1458344383064\",\n" +
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties); " \"name\": \"jcdep1458344383064\",\n" +
" \"properties\": {\n" +
" \"parameters\": {\n" +
" \"newStorageAccountName\": {\n" +
" \"type\": \"String\",\n" +
" \"value\": \"jcres1458344383064\"\n" +
" },\n" +
" \"storageAccountType\": {\n" +
" \"type\": \"String\",\n" +
" \"value\": \"Standard_LRS\"\n" +
" },\n" +
" \"location\": {\n" +
" \"type\": \"String\",\n" +
" \"value\": \"West US\"\n" +
" }\n" +
" },\n" +
" \"mode\": \"Incremental\",\n" +
" \"provisioningState\": \"Accepted\",\n" +
" \"timestamp\": \"2016-03-18T23:39:47.3048037Z\",\n" +
" \"duration\": \"PT2.4433028S\",\n" +
" \"correlationId\": \"8dee9711-8632-4948-9fe6-368bb75e6438\",\n" +
" \"providers\": [{\n" +
" \"namespace\": \"Microsoft.Storage\",\n" +
" \"resourceTypes\": [{\n" +
" \"resourceType\": \"storageAccounts\",\n" +
" \"locations\": [\"westus\"]\n" +
" }]\n" +
" }],\n" +
" \"dependencies\": []\n" +
" }\n" +
"}";
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate); deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
Deployment deploymentValid = api().validate(deploymentName, deploymentTemplate); Deployment deploymentValid = api().validate(deploymentName, deploymentTemplate);

View File

@ -1,287 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import java.util.List;
import java.util.Map;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.IpConfiguration;
import org.jclouds.azurecompute.arm.domain.IpConfigurationProperties;
import org.jclouds.azurecompute.arm.domain.NetworkInterfaceCardProperties;
import org.jclouds.azurecompute.arm.domain.PublicIPAddressProperties;
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
import org.jclouds.azurecompute.arm.domain.StorageService;
import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "unit", testName = "DeploymentTemplateBuilderTest", singleThreaded = true)
public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
final String group = "jcgroup";
final String vnetName = group + "virtualnetwork";
final String subnetId = "";
@Test
public void testResourceGroup() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Storage/storageAccounts");
StorageServiceProperties properties = (StorageServiceProperties) resource.properties();
assertEquals(properties.accountType(), StorageService.AccountType.Standard_LRS);
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testPublicIpAddress() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
PublicIPAddressProperties properties = (PublicIPAddressProperties) resource.properties();
assertEquals(properties.publicIPAllocationMethod(), "Dynamic");
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testNetworkInterfaceCard() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Network/networkInterfaces");
NetworkInterfaceCardProperties properties = (NetworkInterfaceCardProperties) resource.properties();
List<IpConfiguration> ipConfigs = properties.ipConfigurations();
assertTrue(ipConfigs.size() > 0);
IpConfigurationProperties ipProperties = ipConfigs.get(0).properties();
assertEquals(ipProperties.privateIPAllocationMethod(), "Dynamic");
assertNotNull(ipProperties.publicIPAddress());
assertNotNull(ipProperties.subnet());
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testVirtualMachine() {
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
Template template = builder.getTemplate();
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
Map<String, String> variables = deploymentBody.template().variables();
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
assertNotNull(resource);
VirtualMachineProperties properties = (VirtualMachineProperties) resource.properties();
assertEquals(properties.hardwareProfile().vmSize(), template.getHardware().getId());
ImageReference image = properties.storageProfile().imageReference();
assertEquals(image.publisher(), template.getImage().getProviderId());
assertEquals(image.offer(), template.getImage().getName());
assertEquals(image.sku(), template.getImage().getVersion());
assertEquals(image.version(), "latest");
assertTrue(variables.containsKey(parseVariableName(resource.name())));
}
@Test
void testAddStorageResourceWhenNameIsLongerThan24Chars() {
String name = "thishasmorethan24characters";
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
String storageAccountName = deploymentBody.template().variables().get("storageAccountName");
assertEquals(storageAccountName.length(), 24);
assertEquals(storageAccountName.substring(0, 10), "thishasmor");
assertEquals(storageAccountName.substring(storageAccountName.length() - 10, storageAccountName.length()), "characters");
}
@Test
void testAddStorageResourceWhenNameIsExactly24Chars() {
String name = "ithasexactly24characters";
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
assertEquals(deploymentBody.template().variables().get("storageAccountName").length(), 24);
assertEquals(deploymentBody.template().variables().get("storageAccountName"), name);
}
@Test
void testAddStorageResourceWhenNameIsLessThan3Chars() {
String name = "3c";
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions(name);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
assertTrue(Iterables.contains(deploymentBody.template().variables().keySet(), "storageAccountName"));
assertEquals(deploymentBody.template().variables().get("storageAccountName").length(), 6);
assertEquals(deploymentBody.template().variables().get("storageAccountName").substring(0, 2), name);
}
@Test
void testCustomOptions(){
final String dnsLabelPrefix = "mydnslabel";
final String customData = "echo customData";
final String customData64 = "ZWNobyBjdXN0b21EYXRh";
final String keyvaultString = "/url/to/vault/:publickeysecret";
AzureTemplateOptions options = new AzureTemplateOptions()
.customData(customData)
.DNSLabelPrefix(dnsLabelPrefix)
.keyVaultIdAndSecret(keyvaultString);
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
assertEquals(options.as(AzureTemplateOptions.class).getCustomData(), customData);
assertEquals(options.getDNSLabelPrefix(), dnsLabelPrefix);
assertEquals(options.as(AzureTemplateOptions.class).getKeyVaultIdAndSecret(), keyvaultString);
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
List<ResourceDefinition> resources = deploymentBody.template().resources();
ResourceDefinition publicIpResource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
assertNotNull(publicIpResource);
PublicIPAddressProperties ipProperties = (PublicIPAddressProperties) publicIpResource.properties();
assertEquals(ipProperties.dnsSettings().domainNameLabel(), dnsLabelPrefix);
ResourceDefinition vmResource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
assertNotNull(vmResource);
VirtualMachineProperties virtualMachineProperties = (VirtualMachineProperties) vmResource.properties();
assertEquals(virtualMachineProperties.osProfile().customData(), customData64);
//populated when keyvault is used to get public key.
assertNotNull(virtualMachineProperties.osProfile().linuxConfiguration().ssh().publicKeys());
}
@Test(expectedExceptions = IllegalArgumentException.class)
void testSimplifyPortsWithPortsNull() {
int[] ports = null;
DeploymentTemplateBuilder.simplifyPorts(ports);
}
@Test(expectedExceptions = IllegalArgumentException.class)
void testSimplifyPortsWithPortsEmpty() {
int[] ports = new int[0];
DeploymentTemplateBuilder.simplifyPorts(ports);
}
@Test
void testSimplifyPorts() {
int[] ports = {8084, 22, 8081, 8080, 8082};
List<String> ranges = DeploymentTemplateBuilder.simplifyPorts(ports);
assertEquals(ranges.size(), 3);
assertEquals(ranges.get(0), "22");
assertEquals(ranges.get(1), "8080-8082");
assertEquals(ranges.get(2), "8084");
}
private Template getMockTemplate(TemplateOptions options) {
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
((AzureTemplateOptions)options).subnetId(subnetId);
Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id("northeurope").description("North Europe").parent(provider).build();
OperatingSystem os = OperatingSystem.builder().name("osName").version("osVersion").description("osDescription").arch("X86_32").build();
//Note that version is set to "latest"
Image image = (new ImageBuilder()).id("imageId").providerId("imageId").name("imageName").description("imageDescription").version("sku").operatingSystem(os).status(Image.Status.AVAILABLE).location(region).build();
Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
return new TemplateImpl(image, hardware, region, options);
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions() {
return getMockDeploymentTemplateBuilderWithEmptyOptions("mydeployment");
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions(String name) {
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
Template template = getMockTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, name, template);
return templateBuilder;
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
return getMockDeploymentTemplateBuilderWithOptions("mydeployment", options);
}
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(String name, TemplateOptions options) {
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
((AzureTemplateOptions)options).subnetId(subnetId);
Template template = getMockTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, name, template);
return templateBuilder;
}
private ResourceDefinition getResourceByType(List<ResourceDefinition> resources, String type) {
for (ResourceDefinition r : resources) {
if (r.type().equals(type)) {
return r;
}
}
Assert.fail("Resource with type: " + type + " not found");
return null;
}
private String parseVariableName(String variable) {
String[] parts = variable.split("\'");
assertTrue(parts.length == 3);
return parts[1];
}
}

View File

@ -83,8 +83,6 @@ public class NetworkSecurityGroupApiMockTest extends BaseAzureComputeApiMockTest
} }
public void getNetworkSecurityGroup() throws InterruptedException { public void getNetworkSecurityGroup() throws InterruptedException {
NetworkSecurityGroup nsg = createGroup();
server.enqueue(jsonResponse("/networksecuritygroupget.json").setResponseCode(200)); server.enqueue(jsonResponse("/networksecuritygroupget.json").setResponseCode(200));
final NetworkSecurityGroupApi nsgApi = api.getNetworkSecurityGroupApi(resourcegroup); final NetworkSecurityGroupApi nsgApi = api.getNetworkSecurityGroupApi(resourcegroup);

View File

@ -147,8 +147,7 @@ public class PublicIPAddressApiMockTest extends BaseAzureComputeApiMockTest {
PublicIPAddressProperties properties = PublicIPAddressProperties.create(null, null, "Static", 4, null, PublicIPAddressProperties properties = PublicIPAddressProperties.create(null, null, "Static", 4, null,
DnsSettings.create("foobar", "foobar.northeurope.cloudapp.azure.com", null)); DnsSettings.create("foobar", "foobar.northeurope.cloudapp.azure.com", null));
PublicIPAddress ip = ipApi.createOrUpdate(publicIpName, location, tags, properties); ipApi.createOrUpdate(publicIpName, location, tags, properties);
} }
public void deletePublicIPAddress() throws InterruptedException { public void deletePublicIPAddress() throws InterruptedException {

View File

@ -31,7 +31,6 @@ public class ResourceProviderAPIMockTest extends BaseAzureComputeApiMockTest {
final String apiVersion = "2015-01-01"; final String apiVersion = "2015-01-01";
final String resource = "Microsoft.Compute"; final String resource = "Microsoft.Compute";
private final String vm_resource = "virtualMachines";
public void getPublicIPAddressInfo() throws InterruptedException { public void getPublicIPAddressInfo() throws InterruptedException {
server.enqueue(jsonResponse("/getresourceprovidermetadata.json")); server.enqueue(jsonResponse("/getresourceprovidermetadata.json"));

View File

@ -235,41 +235,6 @@ public class StorageAccountApiMockTest extends BaseAzureComputeApiMockTest {
"/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15"); "/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE?api-version=2015-06-15");
} }
private StorageService getStrorageAccount() {
DateService DATE_SERVICE = new SimpleDateFormatDateService();
Map<String, String> endpoints = new HashMap<String, String>();
endpoints.put("blob", "https://TESTSTORAGE.blob.core.windows.net/");
endpoints.put("file", "https://TESTSTORAGE.file.core.windows.net/");
endpoints.put("queue", "https://TESTSTORAGE.queue.core.windows.net/");
endpoints.put("table", "https://TESTSTORAGE.table.core.windows.net/");
Map<String, String> secondaryEndpoints = new HashMap<String, String>();
secondaryEndpoints.put("blob", "https://TESTSTORAGE-secondary.blob.core.windows.net/");
secondaryEndpoints.put("queue", "https://TESTSTORAGE-secondary.queue.core.windows.net/");
secondaryEndpoints.put("table", "https://TESTSTORAGE-secondary.table.core.windows.net/");
String location = "westus";
String secondaryLocation = "eastus";
final StorageService.StorageServiceProperties props = StorageService.StorageServiceProperties.create(
StorageService.AccountType.Standard_RAGRS,
DATE_SERVICE.iso8601DateOrSecondsDateParse("2016-02-24T13:04:45.0890883Z"),
endpoints,
location,
StorageService.Status.Succeeded,
secondaryEndpoints, secondaryLocation,
StorageService.RegionStatus.Available,
StorageService.RegionStatus.Available);
final Map<String, String> tags = ImmutableMap.of(
"key1", "value1",
"key2", "value2");
return StorageService.create(
"/subscriptions/SUBSCRIPTIONID/resourceGroups/resourceGroup" +
"/providers/Microsoft.Storage/storageAccounts/TESTSTORAGE",
"TESTSTORAGE", location, tags, null, props);
}
private List<StorageService> expected() throws MalformedURLException { private List<StorageService> expected() throws MalformedURLException {
DateService DATE_SERVICE = new SimpleDateFormatDateService(); DateService DATE_SERVICE = new SimpleDateFormatDateService();
Map<String, String> endpoints = new HashMap<String, String>(); Map<String, String> endpoints = new HashMap<String, String>();

View File

@ -16,18 +16,17 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.testng.annotations.Test;
import java.util.List;
import static com.google.common.collect.Iterables.isEmpty; import static com.google.common.collect.Iterables.isEmpty;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertNull; import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.util.List;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "SubnetApiMockTest", singleThreaded = true) @Test(groups = "unit", testName = "SubnetApiMockTest", singleThreaded = true)
@ -135,6 +134,6 @@ public class SubnetApiMockTest extends BaseAzureComputeApiMockTest {
assertFalse(status); assertFalse(status);
String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s/subnets/%s?%s", subscriptionid, resourcegroup, virtualNetwork, subnetName, apiVersion); String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s/subnets/%s?%s", subscriptionid, resourcegroup, virtualNetwork, subnetName, apiVersion);
RecordedRequest rr = assertSent(server, "DELETE", path); assertSent(server, "DELETE", path);
} }
} }

View File

@ -1,281 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
import org.jclouds.azurecompute.arm.domain.Deployment;
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VirtualNetwork;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.internal.TemplateImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.net.UrlEscapers;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "live", testName = "TemplateToDeploymentTemplateLiveTest", singleThreaded = true)
public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiveTest {
private int maxTestDuration = 400;
private int pollingInterval = 3; // how frequently to poll for create status
private String resourceGroupName;
private String deploymentName;
private String vnetName;
private String subnetId;
private String virtualNetworkName;
@BeforeClass
@Override
public void setup() {
super.setup();
resourceGroupName = String.format("rg-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
assertNotNull(createResourceGroup(resourceGroupName));
virtualNetworkName = String.format("vn-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
//Subnets belong to a virtual network so that needs to be created first
VirtualNetwork vn = createDefaultVirtualNetwork(resourceGroupName, virtualNetworkName, "10.2.0.0/16", LOCATION);
assertNotNull(vn);
vnetName = vn.name();
//Subnet needs to be up & running before NIC can be created
String subnetName = String.format("s-%s-%s", this.getClass().getSimpleName().toLowerCase(), System.getProperty("user.name"));
Subnet subnet = createDefaultSubnet(resourceGroupName, subnetName, virtualNetworkName, "10.2.0.0/23");
assertNotNull(subnet);
assertNotNull(subnet.id());
subnetId = subnet.id();
}
@AfterClass
@Override
protected void tearDown() {
super.tearDown();
URI uri = deleteResourceGroup(resourceGroupName);
assertResourceDeleted(uri);
}
@Test
public void testValidateDeploymentTemplateLinuxNodeWithOptions() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
options.inboundPorts(22, 8080);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
//Validates that template is syntactically correct
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testValidateDeploymentTemplateLinuxNode() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithEmptyOptions();
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
//Validates that template is syntactically correct
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testValidateDeploymentTemplateWithCustomOptions() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
TemplateOptions options = new AzureTemplateOptions()
.DNSLabelPrefix("mydnslabel")
.virtualNetworkAddressPrefix("10.0.0.0/20")
.subnetAddressPrefix("10.0.0.0/25")
.authorizePublicKey(rsakey);
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
((AzureTemplateOptions)options).subnetId(subnetId);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testValidateDeploymentTemplateLinuxNodeWithSSH() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
options.authorizePublicKey(rsakey);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
Deployment deployment = api().validate(deploymentName, deploymentTemplate);
assertNotNull(deployment);
}
@Test
public void testCreateDeploymentTemplateLinuxNode() {
Long now = System.currentTimeMillis();
deploymentName = "jc" + now;
String rsakey = new String("ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmfk/QSF0pvnrpdz+Ah2KulGruKU+8FFBdlw938MpOysRdmp7uwpH6Z7+5VNGNdxFIAyc/W3UaZXF9hTsU8+78TlwkZpsr2mzU+ycu37XLAQ8Uv7hjsAN0DkKKPrZ9lgUUfZVKV/8E/JIAs03gIbL6zO3y7eYJQ5fNeZb+nji7tQT+YLpGq/FDegvraPKVMQbCSCZhsHyWhdPLyFlu9/30npZ0ahYOPI/KyZxFDtM/pHp88+ZAk9Icq5owaLRWcJQqrBGWqjbZnHtjdDqvHZ+C0wPhdJZPyfkHOrSYTwSQBXfX4JLRRCz3J1jf62MbQWT1o6Y4JEs1ZP1Skxu6zR96Q== mocktest");
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
options.authorizePublicKey(rsakey);
options.inboundPorts(22, 8080);
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
DeploymentProperties properties = DeploymentProperties.create(deploymentTemplateBody);
String deploymentTemplate = templateBuilder.getDeploymentTemplateJson(properties);
deploymentTemplate = UrlEscapers.urlFormParameterEscaper().escape(deploymentTemplate);
//creates an actual VM using deployment template
Deployment deployment = api().create(deploymentName, deploymentTemplate);
Deployment.ProvisioningState state = Deployment.ProvisioningState.fromValue(deployment.properties().provisioningState());
int testTime = 0;
while (testTime < maxTestDuration) {
if ((state == Deployment.ProvisioningState.SUCCEEDED) ||
(state == Deployment.ProvisioningState.CANCELED) ||
(state == Deployment.ProvisioningState.DELETED) ||
(state == Deployment.ProvisioningState.FAILED)) {
break;
}
// sleep a little bit before polling, timeout after a fixed time
try {
Thread.sleep(pollingInterval * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
testTime += pollingInterval;
deployment = api().get(deploymentName);
assertNotNull(deployment);
state = Deployment.ProvisioningState.fromValue(deployment.properties().provisioningState());
}
assertTrue(state == Deployment.ProvisioningState.SUCCEEDED);
assertNotNull(deployment);
}
private Template getTemplate(TemplateOptions options) {
Location provider = (new LocationBuilder()).scope(LocationScope.PROVIDER).id("azurecompute-arm").description("azurecompute-arm").build();
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description(LOCATIONDESCRIPTION).parent(provider).build();
OperatingSystem os = OperatingSystem.builder()
.family(OsFamily.UBUNTU)
.description("14.04.3-LTS")
.is64Bit(true)
.build();
Image image = (new ImageBuilder())
.id("UbuntuServer14.04.3-LTS")
.providerId("Canonical")
.name("UbuntuServer")
.description("14.04.3-LTS")
.version("14.04.3-LTS")
.operatingSystem(os)
.status(Image.Status.AVAILABLE)
.location(region)
.build();
Hardware hardware = (new HardwareBuilder()).id("Standard_A0").build();
return new TemplateImpl(image, hardware, region, options);
}
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithEmptyOptions() {
AzureTemplateOptions options = new AzureTemplateOptions();
options.virtualNetworkName(vnetName);
options.subnetId(subnetId);
Template template = getTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
return templateBuilder;
}
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
Template template = getTemplate(options);
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroupName, deploymentName, template);
return templateBuilder;
}
private DeploymentApi api() {
return api.getDeploymentApi(resourceGroupName);
}
}

View File

@ -16,6 +16,10 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -41,6 +45,7 @@ import org.jclouds.azurecompute.arm.domain.Subnet;
import org.jclouds.azurecompute.arm.domain.VHD; import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance.VirtualMachineStatus.PowerState;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest; import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.testng.Assert; import org.testng.Assert;
@ -48,16 +53,9 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.gson.internal.LinkedTreeMap;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Test(groups = "live", testName = "VirtualMachineApiLiveTest") @Test(groups = "live", testName = "VirtualMachineApiLiveTest")
public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest { public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@ -125,7 +123,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
}, 60 * 20 * 1000).apply(vmName); }, 60 * 20 * 1000).apply(vmName);
assertTrue(jobDone, "create operation did not complete in the configured timeout"); assertTrue(jobDone, "create operation did not complete in the configured timeout");
String status = api().get(vmName).properties().provisioningState(); VirtualMachineProperties.ProvisioningState status = api().get(vmName).properties().provisioningState();
// Cannot be creating anymore. Should be succeeded or running but not failed. // Cannot be creating anymore. Should be succeeded or running but not failed.
assertTrue(!status.equals("Creating")); assertTrue(!status.equals("Creating"));
assertTrue(!status.equals("Failed")); assertTrue(!status.equals("Failed"));
@ -146,21 +144,21 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@Test(dependsOnMethods = "testStart") @Test(dependsOnMethods = "testStart")
public void testStop() { public void testStop() {
api().stop(vmName); api().stop(vmName);
assertTrue(stateReached("PowerState", "VM stopped"), "stop operation did not complete in the configured timeout"); assertTrue(stateReached(PowerState.STOPPED), "stop operation did not complete in the configured timeout");
} }
@Test(dependsOnMethods = "testGet") @Test(dependsOnMethods = "testGet")
public void testStart() { public void testStart() {
api().start(vmName); api().start(vmName);
assertTrue(stateReached("PowerState", "VM running"), "start operation did not complete in the configured timeout"); assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
} }
@Test(dependsOnMethods = "testStop") @Test(dependsOnMethods = "testStop")
public void testRestart() { public void testRestart() {
api().start(vmName); api().start(vmName);
assertTrue(stateReached("PowerState", "VM running"), "start operation did not complete in the configured timeout"); assertTrue(stateReached(PowerState.RUNNING), "start operation did not complete in the configured timeout");
api().restart(vmName); api().restart(vmName);
assertTrue(stateReached("PowerState", "VM running"), "restart operation did not complete in the configured timeout"); assertTrue(stateReached(PowerState.RUNNING), "restart operation did not complete in the configured timeout");
} }
@Test(dependsOnMethods = "testCreate") @Test(dependsOnMethods = "testCreate")
@ -180,10 +178,11 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
@Test(dependsOnMethods = "testRestart") @Test(dependsOnMethods = "testRestart")
public void testGeneralize() throws IllegalStateException { public void testGeneralize() throws IllegalStateException {
api().stop(vmName); api().stop(vmName);
assertTrue(stateReached("PowerState", "VM stopped"), "restart operation did not complete in the configured timeout"); assertTrue(stateReached(PowerState.STOPPED), "restart operation did not complete in the configured timeout");
api().generalize(vmName); api().generalize(vmName);
} }
@SuppressWarnings("unchecked")
@Test(dependsOnMethods = "testGeneralize") @Test(dependsOnMethods = "testGeneralize")
public void testCapture() throws IllegalStateException { public void testCapture() throws IllegalStateException {
URI uri = api().capture(vmName, vmName, vmName); URI uri = api().capture(vmName, vmName, vmName);
@ -192,17 +191,17 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri); List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
if (definitions != null) { if (definitions != null) {
for (ResourceDefinition definition : definitions) { for (ResourceDefinition definition : definitions) {
LinkedTreeMap<String, String> properties = (LinkedTreeMap<String, String>) definition.properties(); Map<String, String> properties = (Map<String, String>) definition.properties();
Object storageObject = properties.get("storageProfile"); Object storageObject = properties.get("storageProfile");
LinkedTreeMap<String, String> properties2 = (LinkedTreeMap<String, String>) storageObject; Map<String, String> properties2 = (Map<String, String>) storageObject;
Object osDiskObject = properties2.get("osDisk"); Object osDiskObject = properties2.get("osDisk");
LinkedTreeMap<String, String> osProperties = (LinkedTreeMap<String, String>) osDiskObject; Map<String, String> osProperties = (Map<String, String>) osDiskObject;
Object dataDisksObject = properties2.get("dataDisks"); Object dataDisksObject = properties2.get("dataDisks");
ArrayList<Object> dataProperties = (ArrayList<Object>) dataDisksObject; List<Object> dataProperties = (List<Object>) dataDisksObject;
LinkedTreeMap<String, String> datadiskObject = (LinkedTreeMap<String, String>) dataProperties.get(0); Map<String, String> datadiskObject = (Map<String, String>) dataProperties.get(0);
Assert.assertNotNull(osProperties.get("name")); assertNotNull(osProperties.get("name"));
Assert.assertNotNull(datadiskObject.get("name")); assertNotNull(datadiskObject.get("name"));
} }
} }
} }
@ -245,7 +244,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
DiagnosticsProfile.BootDiagnostics.create(true, blob); DiagnosticsProfile.BootDiagnostics.create(true, blob);
DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics); DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
VirtualMachineProperties properties = VirtualMachineProperties.create(null, VirtualMachineProperties properties = VirtualMachineProperties.create(null,
null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating"); null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
return properties; return properties;
} }
@ -261,37 +260,15 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags); return api.getNetworkInterfaceCardApi(resourceGroupName).createOrUpdate(networkInterfaceCardName, locationName, networkInterfaceCardProperties, tags);
} }
private boolean deleteStorageService(String resourceGroupName, String storageServiceName) { private boolean waitForState(String name, final PowerState state) {
return api.getStorageAccountApi(resourceGroupName).delete(storageServiceName); return api().getInstanceDetails(name).powerState().equals(state);
} }
private boolean waitForState(String name, final String state, final String displayStatus) { private boolean stateReached(final PowerState state) {
return FluentIterable.from(api().getInstanceDetails(name).statuses())
.filter(new Predicate<VirtualMachineInstance.VirtualMachineStatus>() {
@Override
public boolean apply(VirtualMachineInstance.VirtualMachineStatus input) {
return input.code().substring(0, 10).equals(state);
}
})
.transform(new Function<VirtualMachineInstance.VirtualMachineStatus, String>() {
@Override
public String apply(VirtualMachineInstance.VirtualMachineStatus input) {
return input.displayStatus();
}
})
.anyMatch(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.equals(displayStatus);
}
});
}
private boolean stateReached(final String state, final String displayStatus) {
return retry(new Predicate<String>() { return retry(new Predicate<String>() {
@Override @Override
public boolean apply(String name) { public boolean apply(String name) {
return waitForState(name, state, displayStatus); return waitForState(name, state);
} }
}, 60 * 4 * 1000).apply(vmName); }, 60 * 4 * 1000).apply(vmName);
} }

View File

@ -16,35 +16,36 @@
*/ */
package org.jclouds.azurecompute.arm.features; package org.jclouds.azurecompute.arm.features;
import com.google.common.collect.ImmutableList; import java.net.URI;
import com.squareup.okhttp.mockwebserver.MockResponse; import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.jclouds.azurecompute.arm.domain.DataDisk;
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
import org.jclouds.azurecompute.arm.domain.HardwareProfile; import org.jclouds.azurecompute.arm.domain.HardwareProfile;
import org.jclouds.azurecompute.arm.domain.IdReference; import org.jclouds.azurecompute.arm.domain.IdReference;
import org.jclouds.azurecompute.arm.domain.ImageReference; import org.jclouds.azurecompute.arm.domain.ImageReference;
import org.jclouds.azurecompute.arm.domain.VirtualMachine; import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.OSDisk; import org.jclouds.azurecompute.arm.domain.OSDisk;
import org.jclouds.azurecompute.arm.domain.OSProfile; import org.jclouds.azurecompute.arm.domain.OSProfile;
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
import org.jclouds.azurecompute.arm.domain.NetworkProfile;
import org.jclouds.azurecompute.arm.domain.StorageProfile; import org.jclouds.azurecompute.arm.domain.StorageProfile;
import org.jclouds.azurecompute.arm.domain.DataDisk; import org.jclouds.azurecompute.arm.domain.VHD;
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance; import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties; import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest; import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.net.URI; import com.google.common.collect.ImmutableList;
import java.util.ArrayList; import com.squareup.okhttp.mockwebserver.MockResponse;
import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import static com.google.common.collect.Iterables.isEmpty; import static com.google.common.collect.Iterables.isEmpty;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true) @Test(groups = "unit", testName = "VirtualMachineApiMockTest", singleThreaded = true)
@ -55,14 +56,14 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname"); final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
assertEquals(vmAPI.get("windowsmachine"), getVM()); assertEquals(vmAPI.get("windowsmachine"), getVM());
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15"); "/virtualMachines/windowsmachine?api-version=2016-03-30");
} }
public void testGetEmpty() throws Exception { public void testGetEmpty() throws Exception {
server.enqueue(new MockResponse().setResponseCode(404)); server.enqueue(new MockResponse().setResponseCode(404));
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname"); final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
assertNull(vmAPI.get("windowsmachine")); assertNull(vmAPI.get("windowsmachine"));
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15"); "/virtualMachines/windowsmachine?api-version=2016-03-30");
} }
public void testGetInstanceDetails() throws Exception { public void testGetInstanceDetails() throws Exception {
@ -76,7 +77,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
assertEquals(actual.statuses().get(0).level(), expected.statuses().get(0).level()); assertEquals(actual.statuses().get(0).level(), expected.statuses().get(0).level());
//assertEquals(actual.statuses().get(0).time().toString(), expected.statuses().get(0).time().toString()); //assertEquals(actual.statuses().get(0).time().toString(), expected.statuses().get(0).time().toString());
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15"); "/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
} }
public void testGetInstanceDetailsEmpty() throws Exception { public void testGetInstanceDetailsEmpty() throws Exception {
@ -84,7 +85,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname"); final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
assertNull(vmAPI.getInstanceDetails("windowsmachine")); assertNull(vmAPI.getInstanceDetails("windowsmachine"));
assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "GET", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15"); "/virtualMachines/windowsmachine/instanceView?api-version=2016-03-30");
} }
public void testList() throws Exception { public void testList() throws Exception {
@ -109,7 +110,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
VirtualMachine vm = vmAPI.create("windowsmachine", "westus", getProperties()); VirtualMachine vm = vmAPI.create("windowsmachine", "westus", getProperties());
assertEquals(vm, getVM()); assertEquals(vm, getVM());
assertSent(server, "PUT", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "PUT", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15&validating=false", "/virtualMachines/windowsmachine?validating=false&api-version=2016-03-30",
"{\"location\":\"westus\",\"properties\":" + "{\"location\":\"westus\",\"properties\":" +
"{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\"," + "{\"vmId\":\"27ee085b-d707-xxxx-yyyy-2370e2eb1cc1\"," +
"\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"}," + "\"hardwareProfile\":{\"vmSize\":\"Standard_D1\"}," +
@ -118,7 +119,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
"\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\"},\"dataDisks\":[]}," + "\"vhd\":{\"uri\":\"https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd\"},\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\"},\"dataDisks\":[]}," +
"\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"windowsConfiguration\":{\"provisionVMAgent\":false,\"enableAutomaticUpdates\":true}}," + "\"osProfile\":{\"computerName\":\"windowsmachine\",\"adminUsername\":\"azureuser\",\"windowsConfiguration\":{\"provisionVMAgent\":false,\"enableAutomaticUpdates\":true}}," +
"\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]}," + "\"networkProfile\":{\"networkInterfaces\":[{\"id\":\"/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Network/networkInterfaces/windowsmachine167\"}]}," +
"\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"Creating\"}}"); "\"diagnosticsProfile\":{\"bootDiagnostics\":{\"enabled\":true,\"storageUri\":\"https://groupname2760.blob.core.windows.net/\"}},\"provisioningState\":\"CREATING\"}}");
} }
@ -133,7 +134,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
assertNull(uri); assertNull(uri);
assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15"); "/virtualMachines/windowsmachine?api-version=2016-03-30");
} }
public void testDelete() throws Exception { public void testDelete() throws Exception {
server.enqueue(response202WithHeader()); server.enqueue(response202WithHeader());
@ -146,7 +147,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
assertNotNull(uri); assertNotNull(uri);
assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" + assertSent(server, "DELETE", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
"/virtualMachines/windowsmachine?api-version=2015-06-15"); "/virtualMachines/windowsmachine?api-version=2016-03-30");
} }
public void testStart() throws Exception { public void testStart() throws Exception {
@ -231,7 +232,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
"https://groupname2760.blob.core.windows.net/"); "https://groupname2760.blob.core.windows.net/");
DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics); DiagnosticsProfile diagnosticsProfile = DiagnosticsProfile.create(bootDiagnostics);
VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1", VirtualMachineProperties properties = VirtualMachineProperties.create("27ee085b-d707-xxxx-yyyy-2370e2eb1cc1",
null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, "Creating"); null, null, hwProf, storageProfile, osProfile, networkProfile, diagnosticsProfile, VirtualMachineProperties.ProvisioningState.CREATING);
return properties; return properties;
} }

View File

@ -101,7 +101,7 @@ public class VirtualNetworkApiMockTest extends BaseAzureComputeApiMockTest {
VirtualNetwork.AddressSpace.create(Arrays.asList("10.2.0.0/16")), null); VirtualNetwork.AddressSpace.create(Arrays.asList("10.2.0.0/16")), null);
VirtualNetwork vn = vnApi.createOrUpdate(virtualNetwork, location, virtualNetworkProperties); vnApi.createOrUpdate(virtualNetwork, location, virtualNetworkProperties);
String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s?%s", subscriptionid, resourcegroup, virtualNetwork, apiVersion); String path = String.format("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.Network/virtualNetworks/%s?%s", subscriptionid, resourcegroup, virtualNetwork, apiVersion);
String json = String.format("{\"location\":\"%s\",\"properties\":{\"addressSpace\":{\"addressPrefixes\":[\"%s\"]}}}", location, "10.2.0.0/16"); String json = String.format("{\"location\":\"%s\",\"properties\":{\"addressSpace\":{\"addressPrefixes\":[\"%s\"]}}}", location, "10.2.0.0/16");

View File

@ -0,0 +1,129 @@
/*
* 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.filters;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.API_VERSION_PREFIX;
import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.config.InvocationConfig;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
@Test(groups = "unit", testName = "ApiVersionFilterTest", singleThreaded = true)
public class ApiVersionFilterTest {
public interface VersionedApi {
HttpResponse noName();
@Named("named:get")
HttpResponse named();
}
private Invocation noName;
private Invocation named;
private InvocationConfig config;
@BeforeMethod
public void setup() {
noName = Invocation.create(method(VersionedApi.class, "noName"), ImmutableList.of());
named = Invocation.create(method(VersionedApi.class, "named"), ImmutableList.of());
config = createMock(InvocationConfig.class);
expect(config.getCommandName(noName)).andReturn("VersionedApi.noName");
expect(config.getCommandName(named)).andReturn("named:get");
replay(config);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testFailIfNoGeneratedHttpRequest() {
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(new Properties()));
filter.filter(HttpRequest.builder().method("GET").endpoint("http://localhost").build());
}
@Test
public void testOverrideMethodVersion() {
Properties props = new Properties();
props.setProperty(API_VERSION_PREFIX + "named:get", "namedversion");
props.setProperty(API_VERSION_PREFIX + "VersionedApi.noName", "noNameversion");
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(props));
HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost")
.invocation(noName).addQueryParam("api-version", "original", "original2").build();
HttpRequest filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=noNameversion");
request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
.addQueryParam("api-version", "original", "original2").build();
filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=namedversion");
}
@Test
public void testFallbackToClassName() {
Properties props = new Properties();
props.setProperty(API_VERSION_PREFIX + "VersionedApi", "classversion");
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(props));
HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost")
.invocation(noName).addQueryParam("api-version", "original", "original2").build();
HttpRequest filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=classversion");
request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
.addQueryParam("api-version", "original", "original2").build();
filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=classversion");
}
@Test
public void testNothingChangesIfNoCustomVersion() {
ApiVersionFilter filter = new ApiVersionFilter(config, filterStringsBoundToInjectorByName(new Properties()));
HttpRequest request = GeneratedHttpRequest.builder().method("GET").endpoint("http://localhost").invocation(named)
.addQueryParam("api-version", "foo").build();
HttpRequest filtered = filter.filter(request);
assertEquals(filtered.getEndpoint().getQuery(), "api-version=foo");
}
private FilterStringsBoundToInjectorByName filterStringsBoundToInjectorByName(final Properties props) {
Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
Names.bindProperties(binder(), props);
}
});
return new FilterStringsBoundToInjectorByName(injector);
}
}

View File

@ -28,6 +28,7 @@ import org.jclouds.ContextBuilder;
import org.jclouds.azurecompute.arm.AzureComputeApi; import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata; import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.rest.ApiContext;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
@ -50,6 +51,7 @@ public class BaseAzureComputeApiMockTest {
protected MockWebServer server; protected MockWebServer server;
protected AzureComputeApi api; protected AzureComputeApi api;
protected ApiContext<AzureComputeApi> context;
// So that we can ignore formatting. // So that we can ignore formatting.
private final JsonParser parser = new JsonParser(); private final JsonParser parser = new JsonParser();
@ -58,16 +60,21 @@ public class BaseAzureComputeApiMockTest {
public void start() throws IOException { public void start() throws IOException {
server = new MockWebServer(); server = new MockWebServer();
server.play(); server.play();
Properties properties = new Properties();
properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build(); AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
api = ContextBuilder.newBuilder(pm) context = ContextBuilder.newBuilder(pm)
.credentials("", MOCK_BEARER_TOKEN) .credentials("", MOCK_BEARER_TOKEN)
.endpoint(server.getUrl("/").toString() + "subscriptions/SUBSCRIPTIONID") .endpoint(server.getUrl("/").toString() + "subscriptions/SUBSCRIPTIONID")
.modules(modules) .modules(modules)
.overrides(properties) .overrides(setupProperties())
.buildApi(AzureComputeApi.class); .build();
api = context.getApi();
}
protected Properties setupProperties() {
Properties properties = new Properties();
properties.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
properties.put("oauth.endpoint", "https://login.microsoftonline.com/tenant-id/oauth2/token");
return properties;
} }
@AfterMethod(alwaysRun = true) @AfterMethod(alwaysRun = true)