mirror of https://github.com/apache/jclouds.git
JCLOUDS-664 Azurecompute-arm image capture userdata keyvault
This commit is contained in:
parent
cadd60dc22
commit
10d9b38976
|
@ -156,6 +156,7 @@
|
|||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<threadCount>1</threadCount>
|
||||
<systemPropertyVariables>
|
||||
<test.azurecompute-arm.endpoint>${test.azurecompute-arm.endpoint}</test.azurecompute-arm.endpoint>
|
||||
<test.azurecompute-arm.api-version>${test.azurecompute-arm.api-version}</test.azurecompute-arm.api-version>
|
||||
|
|
|
@ -24,6 +24,9 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATI
|
|||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
|
||||
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.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
|
||||
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
|
||||
|
||||
|
@ -70,7 +73,10 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
|
|||
properties.put(RESOURCE, "https://management.azure.com/");
|
||||
properties.put(CREDENTIAL_TYPE, CLIENT_CREDENTIALS_SECRET.toString());
|
||||
properties.put(RESOURCE_GROUP_NAME, "jcloudsgroup");
|
||||
properties.put(IMAGE_PUBLISHERS, "Microsoft.WindowsAzure.Compute, MicrosoftWindowsServer, Canonical");
|
||||
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_DATADISKSIZE, "100");
|
||||
properties.put(IMAGE_PUBLISHERS, "Canonical,RedHat");
|
||||
properties.put(DEFAULT_IMAGE_LOGIN, "jclouds:Password1!");
|
||||
properties.put(TIMEOUT_NODE_TERMINATED, 60 * 10 * 1000);
|
||||
return properties;
|
||||
|
|
|
@ -18,9 +18,11 @@ package org.jclouds.azurecompute.arm.compute;
|
|||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension.CUSTOM_IMAGE_PREFIX;
|
||||
import static org.jclouds.util.Predicates2.retry;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -40,15 +42,14 @@ import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
|
|||
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.ResourceProviderMetaData;
|
||||
import org.jclouds.azurecompute.arm.domain.VMImage;
|
||||
import org.jclouds.azurecompute.arm.domain.VMHardware;
|
||||
import org.jclouds.azurecompute.arm.domain.Location;
|
||||
import org.jclouds.azurecompute.arm.domain.Offer;
|
||||
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceProviderMetaData;
|
||||
import org.jclouds.azurecompute.arm.domain.SKU;
|
||||
import org.jclouds.azurecompute.arm.domain.VMDeployment;
|
||||
import org.jclouds.azurecompute.arm.domain.VMSize;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
|
||||
import org.jclouds.azurecompute.arm.features.DeploymentApi;
|
||||
import org.jclouds.azurecompute.arm.features.OSImageApi;
|
||||
|
@ -60,6 +61,8 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
|||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.azurecompute.arm.functions.CleanupResources;
|
||||
import org.jclouds.azurecompute.arm.domain.VMSize;
|
||||
import org.jclouds.azurecompute.arm.domain.Version;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
@ -118,15 +121,13 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
logger.debug("Deployment created with name: %s group: %s", name, group);
|
||||
|
||||
|
||||
|
||||
final Set<VMDeployment> deployments = Sets.newHashSet();
|
||||
|
||||
final DeploymentApi deploymentApi = api.getDeploymentApi(group);
|
||||
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) {
|
||||
|
@ -149,8 +150,18 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
final VMDeployment deployment = deployments.iterator().next();
|
||||
|
||||
|
||||
return new NodeAndInitialCredentials<VMDeployment>(deployment, name,
|
||||
LoginCredentials.builder().user(loginUser).identity(loginUser).password(loginPassword).authenticateSudo(true).build());
|
||||
NodeAndInitialCredentials<VMDeployment> credential = null;
|
||||
|
||||
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
|
||||
|
@ -166,17 +177,17 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
Iterable<VMSize> vmSizes = api.getVMSizeApi(location.name()).list();
|
||||
|
||||
for (VMSize vmSize : vmSizes){
|
||||
VMHardware hwProfile = new VMHardware();
|
||||
hwProfile.name = vmSize.name();
|
||||
hwProfile.numberOfCores = vmSize.numberOfCores();
|
||||
hwProfile.osDiskSizeInMB = vmSize.osDiskSizeInMB();
|
||||
hwProfile.resourceDiskSizeInMB = vmSize.resourceDiskSizeInMB();
|
||||
hwProfile.memoryInMB = vmSize.memoryInMB();
|
||||
hwProfile.maxDataDiskCount = vmSize.maxDataDiskCount();
|
||||
hwProfile.location = location.name();
|
||||
VMHardware hwProfile = VMHardware.create(
|
||||
vmSize.name(),
|
||||
vmSize.numberOfCores(),
|
||||
vmSize.osDiskSizeInMB(),
|
||||
vmSize.resourceDiskSizeInMB(),
|
||||
vmSize.memoryInMB(),
|
||||
vmSize.maxDataDiskCount(),
|
||||
location.name(),
|
||||
false);
|
||||
hwProfiles.add(hwProfile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
checkAndSetHwAvailability(hwProfiles, Sets.newHashSet(locationIds));
|
||||
|
@ -186,34 +197,35 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
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);
|
||||
hwMap.put(hw.name(), hw.location());
|
||||
}
|
||||
|
||||
for (VMHardware hw : hwProfiles) {
|
||||
hw.globallyAvailable = hwMap.get(hw.name).containsAll(locations);
|
||||
}
|
||||
/// TODO
|
||||
// for (VMHardware hw : hwProfiles) {
|
||||
// hw.globallyAvailable() = hwMap.get(hw.name()).containsAll(locations);
|
||||
// }
|
||||
}
|
||||
|
||||
private void getImagesFromPublisher(String publisherName, List<VMImage> osImagesRef, String location) {
|
||||
|
||||
OSImageApi osImageApi = api.getOSImageApi(location);
|
||||
|
||||
OSImageApi osImageApi = api.getOSImageApi(location);
|
||||
Iterable<Offer> offerList = osImageApi.listOffers(publisherName);
|
||||
|
||||
for (Offer offer : offerList) {
|
||||
Iterable<SKU> skuList = osImageApi.listSKUs(publisherName, offer.name());
|
||||
|
||||
for (SKU sku : skuList) {
|
||||
VMImage vmImage = new VMImage();
|
||||
vmImage.publisher = publisherName;
|
||||
vmImage.offer = offer.name();
|
||||
vmImage.sku = sku.name();
|
||||
vmImage.location = location;
|
||||
Iterable<Version> versionList = osImageApi.listVersions(publisherName, offer.name(), sku.name());
|
||||
for (Version version : versionList) {
|
||||
VMImage vmImage = VMImage.create(publisherName, offer.name(), sku.name(), version.name(), location, false);
|
||||
osImagesRef.add(vmImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<VMImage> listImagesByLocation(String location) {
|
||||
final List<VMImage> osImages = Lists.newArrayList();
|
||||
Iterable<String> publishers = Splitter.on(',').trimResults().omitEmptyStrings().split(this.azureComputeConstants.azureImagePublishers());
|
||||
|
@ -241,17 +253,23 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
Multimap<String, String> map = ArrayListMultimap.create();
|
||||
|
||||
for (VMImage image : images) {
|
||||
map.put( image.offer + "/" + image.sku, image.location);
|
||||
}
|
||||
|
||||
for (VMImage image : images) {
|
||||
image.globallyAvailable = map.get(image.offer + "/" + image.sku).containsAll(locations);
|
||||
map.put( image.offer() + "/" + image.sku(), image.location());
|
||||
}
|
||||
///TODO
|
||||
// for (VMImage image : images) {
|
||||
// image.globallyAvailable() = map.get(image.offer() + "/" + image.sku()).containsAll(locations);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMImage getImage(final String id) {
|
||||
String[] fields = VMImageToImage.decodeFieldsFromUniqueId(id);
|
||||
if (fields[2].startsWith(CUSTOM_IMAGE_PREFIX)) {
|
||||
String storage = fields[2].substring(CUSTOM_IMAGE_PREFIX.length());
|
||||
String vhd = fields[3];
|
||||
VMImage ref = VMImage.create(CUSTOM_IMAGE_PREFIX + azureGroup, CUSTOM_IMAGE_PREFIX + storage, vhd, null, fields[0], false);
|
||||
return ref;
|
||||
}
|
||||
|
||||
Iterable<VMImage> images = listImages();
|
||||
|
||||
|
@ -266,6 +284,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
|
||||
@Override
|
||||
public Iterable<Location> listLocations() {
|
||||
|
||||
List<Location> locations = api.getLocationApi().list();
|
||||
|
||||
List<ResourceProviderMetaData> resources = api.getResourceProviderApi().get("Microsoft.Compute");
|
||||
|
@ -309,9 +328,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
vmDeployment.deployment = deployment;
|
||||
List<PublicIPAddress> list = getIPAddresses(deployment);
|
||||
vmDeployment.ipAddressList = list;
|
||||
|
||||
VirtualMachine vm = api.getVirtualMachineApi(azureGroup).get(id);
|
||||
vmDeployment.virtualMachine = vm;
|
||||
vmDeployment.vm = api.getVirtualMachineApi(azureGroup).getInstanceDetails(id);
|
||||
if (vm != null && vm.tags() != null) {
|
||||
vmDeployment.userMetaData = vm.tags();
|
||||
String tagString = vmDeployment.userMetaData.get("tags");
|
||||
List<String> tags = Arrays.asList(tagString.split(","));
|
||||
vmDeployment.tags = tags;
|
||||
}
|
||||
return vmDeployment;
|
||||
}
|
||||
|
||||
|
@ -372,9 +397,15 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<VMDeplo
|
|||
List<PublicIPAddress> list = getIPAddresses(d);
|
||||
vmDeployment.ipAddressList = list;
|
||||
|
||||
VirtualMachine virtualMachine = vmApi.get(d.name());
|
||||
vmDeployment.virtualMachine = virtualMachine;
|
||||
VirtualMachine vm = vmApi.get(d.name());
|
||||
vmDeployment.virtualMachine = vm;
|
||||
|
||||
if (vm != null && vm.tags() != null) {
|
||||
vmDeployment.userMetaData = vm.tags();
|
||||
String tagString = vmDeployment.userMetaData.get("tags");
|
||||
List<String> tags = Arrays.asList(tagString.split(","));
|
||||
vmDeployment.tags = tags;
|
||||
}
|
||||
vmDeployments.add(vmDeployment);
|
||||
}
|
||||
return vmDeployments;
|
||||
|
|
|
@ -16,34 +16,56 @@
|
|||
*/
|
||||
package org.jclouds.azurecompute.arm.compute.config;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.jclouds.azurecompute.arm.compute.AzureComputeServiceAdapter;
|
||||
import org.jclouds.azurecompute.arm.compute.extensions.AzureComputeImageExtension;
|
||||
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
|
||||
import org.jclouds.azurecompute.arm.compute.functions.DeploymentToNodeMetadata;
|
||||
import org.jclouds.azurecompute.arm.compute.functions.VMHardwareToHardware;
|
||||
import org.jclouds.azurecompute.arm.compute.functions.LocationToLocation;
|
||||
import org.jclouds.azurecompute.arm.compute.strategy.AzurePopulateDefaultLoginCredentialsForImageStrategy;
|
||||
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
|
||||
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.Location;
|
||||
import org.jclouds.azurecompute.arm.compute.strategy.CreateResourceGroupThenCreateNodes;
|
||||
import org.jclouds.azurecompute.arm.AzureComputeApi;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
|
||||
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
|
||||
import org.jclouds.azurecompute.arm.compute.AzureComputeService;
|
||||
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
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.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
|
||||
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_MAX_PERIOD;
|
||||
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.RESOURCE_GROUP_NAME;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.IMAGE_PUBLISHERS;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_IMAGE_LOGIN;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_VNET_ADDRESS_SPACE_PREFIX;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_SUBNET_ADDRESS_PREFIX;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.DEFAULT_DATADISKSIZE;
|
||||
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
import static org.jclouds.util.Predicates2.retry;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.inject.Inject;
|
||||
|
@ -52,21 +74,22 @@ import com.google.common.base.Predicate;
|
|||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
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_MAX_PERIOD;
|
||||
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.DEFAULT_IMAGE_LOGIN;
|
||||
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
|
||||
import org.jclouds.compute.extensions.ImageExtension;
|
||||
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
|
||||
import org.jclouds.azurecompute.arm.compute.AzureComputeService;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
public class AzureComputeServiceContextModule
|
||||
extends ComputeServiceAdapterContextModule<VMDeployment, VMHardware, VMImage, Location> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
|
@ -84,7 +107,12 @@ public class AzureComputeServiceContextModule
|
|||
install(new LocationsFromComputeServiceAdapterModule<VMDeployment, VMHardware, VMImage, Location>() {
|
||||
});
|
||||
|
||||
bind(TemplateOptions.class).to(AzureTemplateOptions.class);
|
||||
bind(PopulateDefaultLoginCredentialsForImageStrategy.class).to(AzurePopulateDefaultLoginCredentialsForImageStrategy.class);
|
||||
//bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class);
|
||||
bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourceGroupThenCreateNodes.class);
|
||||
bind(new TypeLiteral<ImageExtension>() {
|
||||
}).to(AzureComputeImageExtension.class);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
@ -122,6 +150,18 @@ public class AzureComputeServiceContextModule
|
|||
@Inject
|
||||
private String azureDefaultImageLoginProperty;
|
||||
|
||||
@Named(DEFAULT_VNET_ADDRESS_SPACE_PREFIX)
|
||||
@Inject
|
||||
private String azureDefaultVnetAddressPrefixProperty;
|
||||
|
||||
@Named(DEFAULT_SUBNET_ADDRESS_PREFIX)
|
||||
@Inject
|
||||
private String azureDefaultSubnetAddressPrefixProperty;
|
||||
|
||||
@Named(DEFAULT_DATADISKSIZE)
|
||||
@Inject
|
||||
private String azureDefaultDataDiskSizeProperty;
|
||||
|
||||
public Long operationTimeout() {
|
||||
return Long.parseLong(operationTimeoutProperty);
|
||||
}
|
||||
|
@ -138,6 +178,18 @@ public class AzureComputeServiceContextModule
|
|||
return azureDefaultImageLoginProperty;
|
||||
}
|
||||
|
||||
public String azureDefaultVnetAddressPrefixProperty() {
|
||||
return azureDefaultVnetAddressPrefixProperty;
|
||||
}
|
||||
|
||||
public String azureDefaultSubnetAddressPrefixProperty() {
|
||||
return azureDefaultSubnetAddressPrefixProperty;
|
||||
}
|
||||
|
||||
public String azureDefaultDataDiskSizeProperty() {
|
||||
return azureDefaultDataDiskSizeProperty;
|
||||
}
|
||||
|
||||
public Integer operationPollInitialPeriod() {
|
||||
return Integer.parseInt(operationPollInitialPeriodProperty);
|
||||
}
|
||||
|
@ -163,6 +215,14 @@ public class AzureComputeServiceContextModule
|
|||
pollPeriod.pollMaxPeriod);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named(TIMEOUT_IMAGE_AVAILABLE)
|
||||
protected Predicate<URI> provideImageAvailablePredicate(final AzureComputeApi api, Timeouts timeouts,
|
||||
PollPeriod pollPeriod) {
|
||||
return retry(new ImageDonePredicate(api), timeouts.imageAvailable, pollPeriod.pollInitialPeriod,
|
||||
pollPeriod.pollMaxPeriod);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named(TIMEOUT_RESOURCE_DELETED)
|
||||
protected Predicate<URI> provideResourceDeletedPredicate(final AzureComputeApi api, Timeouts timeouts,
|
||||
|
@ -171,6 +231,18 @@ public class AzureComputeServiceContextModule
|
|||
pollPeriod.pollMaxPeriod);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named(TIMEOUT_NODE_SUSPENDED)
|
||||
protected Predicate<String> provideNodeSuspendedPredicate(final AzureComputeApi api,
|
||||
final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
|
||||
Timeouts timeouts,
|
||||
PollPeriod pollPeriod) {
|
||||
|
||||
String azureGroup = azureComputeConstants.azureResourceGroup();
|
||||
return retry(new NodeSuspendedPredicate(api, azureGroup), timeouts.nodeSuspended, pollPeriod.pollInitialPeriod,
|
||||
pollPeriod.pollMaxPeriod);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class ActionDonePredicate implements Predicate<URI> {
|
||||
|
||||
|
@ -183,9 +255,51 @@ public class AzureComputeServiceContextModule
|
|||
@Override
|
||||
public boolean apply(URI uri) {
|
||||
checkNotNull(uri, "uri cannot be null");
|
||||
return ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri);
|
||||
return (ParseJobStatus.JobStatus.DONE == api.getJobApi().jobStatus(uri)) || (ParseJobStatus.JobStatus.NO_CONTENT == api.getJobApi().jobStatus(uri));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class ImageDonePredicate implements Predicate<URI> {
|
||||
|
||||
private final AzureComputeApi api;
|
||||
|
||||
public ImageDonePredicate(AzureComputeApi api) {
|
||||
this.api = checkNotNull(api, "api must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(URI uri) {
|
||||
checkNotNull(uri, "uri cannot be null");
|
||||
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
|
||||
return definitions != null;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class NodeSuspendedPredicate implements Predicate<String> {
|
||||
|
||||
private final AzureComputeApi api;
|
||||
private final String azureGroup;
|
||||
|
||||
public NodeSuspendedPredicate(AzureComputeApi api, String azureGroup) {
|
||||
this.api = checkNotNull(api, "api must not be null");
|
||||
this.azureGroup = checkNotNull(azureGroup, "azuregroup must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(String name) {
|
||||
checkNotNull(name, "name cannot be null");
|
||||
String status = "";
|
||||
List<VirtualMachineInstance.VirtualMachineStatus> statuses = api.getVirtualMachineApi(this.azureGroup).getInstanceDetails(name).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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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.extensions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.google.gson.internal.LinkedTreeMap;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.azurecompute.arm.AzureComputeApi;
|
||||
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
|
||||
import org.jclouds.azurecompute.arm.compute.functions.VMImageToImage;
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
|
||||
import org.jclouds.azurecompute.arm.domain.VMImage;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
|
||||
import org.jclouds.compute.domain.CloneImageTemplate;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.ImageTemplate;
|
||||
import org.jclouds.compute.domain.ImageTemplateBuilder;
|
||||
import org.jclouds.compute.extensions.ImageExtension;
|
||||
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule.AzureComputeConstants;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
|
||||
import com.google.common.util.concurrent.UncheckedTimeoutException;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
|
||||
public class AzureComputeImageExtension implements ImageExtension {
|
||||
private final AzureComputeApi api;
|
||||
private final Predicate<URI> imageAvailablePredicate;
|
||||
private final Predicate<String> nodeSuspendedPredicate;
|
||||
private final AzureComputeConstants azureComputeConstants;
|
||||
private final ListeningExecutorService userExecutor;
|
||||
private final String group;
|
||||
private final VMImageToImage imageReferenceToImage;
|
||||
public static final String CONTAINER_NAME = "vhdsnew";
|
||||
public static final String CUSTOM_IMAGE_PREFIX = "#";
|
||||
|
||||
@Inject
|
||||
AzureComputeImageExtension(AzureComputeApi api,
|
||||
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<URI> imageAvailablePredicate,
|
||||
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> nodeSuspendedPredicate,
|
||||
final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
|
||||
VMImageToImage imageReferenceToImage) {
|
||||
this.userExecutor = userExecutor;
|
||||
this.group = azureComputeConstants.azureResourceGroup();
|
||||
this.imageReferenceToImage = imageReferenceToImage;
|
||||
this.api = api;
|
||||
this.imageAvailablePredicate = imageAvailablePredicate;
|
||||
this.nodeSuspendedPredicate = nodeSuspendedPredicate;
|
||||
this.azureComputeConstants = azureComputeConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageTemplate buildImageTemplateFromNode(String name, String id) {
|
||||
String imageName = name.toLowerCase();
|
||||
return new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(imageName).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Image> createImage(ImageTemplate template) {
|
||||
final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
|
||||
final String id = cloneTemplate.getSourceNodeId();
|
||||
final String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
|
||||
|
||||
// VM needs to be stopped before it can be generalized
|
||||
String status = "";
|
||||
api.getVirtualMachineApi(group).stop(id);
|
||||
//Poll until resource is ready to be used
|
||||
if (nodeSuspendedPredicate.apply(id)) {
|
||||
return userExecutor.submit(new Callable<Image>() {
|
||||
@Override
|
||||
public Image call() throws Exception {
|
||||
api.getVirtualMachineApi(group).generalize(id);
|
||||
|
||||
final String[] disks = new String[2];
|
||||
URI uri = api.getVirtualMachineApi(group).capture(id, cloneTemplate.getName(), CONTAINER_NAME);
|
||||
if (uri != null) {
|
||||
if (imageAvailablePredicate.apply(uri)) {
|
||||
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
|
||||
if (definitions != null) {
|
||||
for (ResourceDefinition definition : definitions) {
|
||||
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");
|
||||
disks[1] = datadiskObject.get("name");
|
||||
|
||||
VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
|
||||
String location = vm.location();
|
||||
final VMImage ref = VMImage.create(CUSTOM_IMAGE_PREFIX + group, CUSTOM_IMAGE_PREFIX + storageAccountName, disks[0], disks[1], location, false);
|
||||
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
|
||||
public boolean deleteImage(String id) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ 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();
|
||||
|
||||
|
@ -116,6 +117,10 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta
|
|||
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) {
|
||||
|
@ -134,9 +139,25 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta
|
|||
|
||||
builder.status(status);
|
||||
|
||||
if (from.vm != null) {
|
||||
builder.hostname(deployment.name() + "pc");
|
||||
}
|
||||
|
||||
Credentials credentials = credentialStore.get("node#" + from.deployment.name());
|
||||
if (credentials == null) {
|
||||
credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD);
|
||||
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));
|
||||
|
||||
|
@ -149,7 +170,6 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta
|
|||
publicIpAddresses.add(ip.properties().ipAddress());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (publicIpAddresses.size() > 0)
|
||||
builder.publicAddresses(publicIpAddresses);
|
||||
|
@ -171,13 +191,12 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta
|
|||
|
||||
ImageReference imageReference = from.virtualMachine.properties().storageProfile().imageReference();
|
||||
|
||||
VMImage vmImage = new VMImage();
|
||||
vmImage.publisher = imageReference.publisher();
|
||||
vmImage.offer = imageReference.offer();
|
||||
vmImage.sku = imageReference.sku();
|
||||
vmImage.location = locationName;
|
||||
if (imageReference != null) {
|
||||
VMImage vmImage = VMImage.create(imageReference.publisher(), imageReference.offer(), imageReference.sku(),
|
||||
imageReference.version(), locationName, false);
|
||||
Image image = vmImageToImage.apply(vmImage);
|
||||
builder.imageId(image.getId());
|
||||
}
|
||||
|
||||
VMSize myVMSize = null;
|
||||
String vmSizeName = from.virtualMachine.properties().hardwareProfile().vmSize();
|
||||
|
@ -189,14 +208,15 @@ public class DeploymentToNodeMetadata implements Function<VMDeployment, NodeMeta
|
|||
}
|
||||
}
|
||||
|
||||
VMHardware hwProfile = new VMHardware();
|
||||
hwProfile.name = myVMSize.name();
|
||||
hwProfile.numberOfCores = myVMSize.numberOfCores();
|
||||
hwProfile.osDiskSizeInMB = myVMSize.osDiskSizeInMB();
|
||||
hwProfile.resourceDiskSizeInMB = myVMSize.resourceDiskSizeInMB();
|
||||
hwProfile.memoryInMB = myVMSize.memoryInMB();
|
||||
hwProfile.maxDataDiskCount = myVMSize.maxDataDiskCount();
|
||||
hwProfile.location = locationName;
|
||||
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);
|
||||
|
|
|
@ -47,30 +47,31 @@ public class VMHardwareToHardware implements Function<VMHardware, Hardware> {
|
|||
@Override
|
||||
public Hardware apply(VMHardware from) {
|
||||
final HardwareBuilder builder = new HardwareBuilder()
|
||||
.name(from.name)
|
||||
.id(from.name)
|
||||
.processors(ImmutableList.of(new Processor(from.numberOfCores, 2)))
|
||||
.ram(from.memoryInMB)
|
||||
.location(from.globallyAvailable ? null : FluentIterable.from(locations.get())
|
||||
.firstMatch(LocationPredicates.idEquals(from.location))
|
||||
.name(from.name())
|
||||
.providerId(from.name())
|
||||
.id(from.name())
|
||||
.processors(ImmutableList.of(new Processor(from.numberOfCores(), 2)))
|
||||
.ram(from.memoryInMB())
|
||||
.location(from.globallyAvailable() ? null : FluentIterable.from(locations.get())
|
||||
.firstMatch(LocationPredicates.idEquals(from.location()))
|
||||
.get());
|
||||
|
||||
// No id or providerId from Azure
|
||||
if (from.resourceDiskSizeInMB != null) {
|
||||
if (from.resourceDiskSizeInMB() != null) {
|
||||
builder.volume(new VolumeBuilder()
|
||||
.size(Float.valueOf(from.resourceDiskSizeInMB))
|
||||
.size(Float.valueOf(from.resourceDiskSizeInMB()))
|
||||
.type(Volume.Type.LOCAL)
|
||||
.build());
|
||||
}
|
||||
if (from.osDiskSizeInMB != null) {
|
||||
if (from.osDiskSizeInMB() != null) {
|
||||
builder.volume(new VolumeBuilder()
|
||||
.size(Float.valueOf(from.osDiskSizeInMB))
|
||||
.size(Float.valueOf(from.osDiskSizeInMB()))
|
||||
.type(Volume.Type.LOCAL)
|
||||
.build());
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<String, String> metadata = ImmutableMap.builder();
|
||||
metadata.put("maxDataDiskCount", String.valueOf(from.maxDataDiskCount));
|
||||
metadata.put("maxDataDiskCount", String.valueOf(from.maxDataDiskCount()));
|
||||
builder.userMetadata(metadata.build());
|
||||
|
||||
return builder.build();
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package org.jclouds.azurecompute.arm.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
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 com.google.common.collect.FluentIterable;
|
||||
|
@ -29,7 +31,9 @@ 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.LoginCredentials;
|
||||
import org.jclouds.location.predicates.LocationPredicates;
|
||||
|
||||
import java.util.Set;
|
||||
|
@ -59,7 +63,7 @@ public class VMImageToImage implements Function<VMImage, Image> {
|
|||
private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
|
||||
|
||||
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[] decodeFieldsFromUniqueId(final String id) {
|
||||
|
@ -74,18 +78,19 @@ public class VMImageToImage implements Function<VMImage, Image> {
|
|||
@Override
|
||||
public Image apply(final VMImage image) {
|
||||
|
||||
Credentials credentials = new Credentials(AZURE_LOGIN_USERNAME, AZURE_LOGIN_PASSWORD);
|
||||
final ImageBuilder builder = new ImageBuilder()
|
||||
.name(image.offer)
|
||||
.description(image.sku)
|
||||
.name(image.offer())
|
||||
.description(image.sku())
|
||||
.status(Image.Status.AVAILABLE)
|
||||
.version(image.sku)
|
||||
.version(image.sku())
|
||||
.id(encodeFieldsToUniqueId(image))
|
||||
.providerId(image.publisher)
|
||||
.location(image.globallyAvailable ? null : FluentIterable.from(locations.get())
|
||||
.firstMatch(LocationPredicates.idEquals(image.location))
|
||||
.defaultCredentials(LoginCredentials.fromCredentials(credentials))
|
||||
.providerId(image.publisher())
|
||||
.location(image.globallyAvailable() ? null : FluentIterable.from(locations.get())
|
||||
.firstMatch(LocationPredicates.idEquals(image.location()))
|
||||
.get());
|
||||
|
||||
|
||||
final OperatingSystem.Builder osBuilder = osFamily().apply(image);
|
||||
return builder.operatingSystem(osBuilder.build()).build();
|
||||
}
|
||||
|
@ -94,8 +99,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
|
|||
return new Function<VMImage, OperatingSystem.Builder>() {
|
||||
@Override
|
||||
public OperatingSystem.Builder apply(final VMImage image) {
|
||||
checkNotNull(image.offer, "offer");
|
||||
final String label = image.offer;
|
||||
checkNotNull(image.offer(), "offer");
|
||||
final String label = image.offer();
|
||||
|
||||
OsFamily family = OsFamily.UNRECOGNIZED;
|
||||
if (label.contains(CENTOS)) {
|
||||
|
@ -116,8 +121,8 @@ public class VMImageToImage implements Function<VMImage, Image> {
|
|||
return OperatingSystem.builder().
|
||||
family(family).
|
||||
is64Bit(true).
|
||||
description(image.sku).
|
||||
version(image.sku);
|
||||
description(image.sku()).
|
||||
version(image.sku());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* 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.options;
|
||||
|
||||
import static com.google.common.base.Objects.equal;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Azure ARM custom options
|
||||
*/
|
||||
public class AzureTemplateOptions extends TemplateOptions implements Cloneable {
|
||||
|
||||
|
||||
private String customData;
|
||||
private String virtualNetworkAddressPrefix;
|
||||
private String subnetAddressPrefix;
|
||||
private String DNSLabelPrefix;
|
||||
private String keyVaultIdAndSecret;
|
||||
|
||||
|
||||
/**
|
||||
* Custom options for the Azure ARM API
|
||||
*/
|
||||
public AzureTemplateOptions customData(String customData) {
|
||||
this.customData = customData;
|
||||
return this;
|
||||
}
|
||||
private String virtualNetworkName;
|
||||
private String subnetId;
|
||||
|
||||
/**
|
||||
* Sets the CIDR block for virtual network
|
||||
*/
|
||||
public AzureTemplateOptions virtualNetworkAddressPrefix(String virtualNetworkAddressPrefix) {
|
||||
this.virtualNetworkAddressPrefix = virtualNetworkAddressPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CIDR block for subnet within virtual network
|
||||
*/
|
||||
public AzureTemplateOptions subnetAddressPrefix(String subnetAddressPrefix) {
|
||||
this.subnetAddressPrefix = subnetAddressPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the DNS label prefix for public IP address. label.location.cloudapp.azure.com
|
||||
*/
|
||||
public AzureTemplateOptions DNSLabelPrefix(String DNSLabelPrefix) {
|
||||
this.DNSLabelPrefix = DNSLabelPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the KeyVault id and secret separated with ":"
|
||||
*/
|
||||
public AzureTemplateOptions keyVaultIdAndSecret(String keyVaultIdAndSecret) {
|
||||
this.keyVaultIdAndSecret = keyVaultIdAndSecret;
|
||||
return this;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
public AzureTemplateOptions virtualNetworkName(String virtualNetworkName) {
|
||||
this.virtualNetworkName = virtualNetworkName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the subnet name
|
||||
*/
|
||||
public AzureTemplateOptions subnetId(String subnetId) {
|
||||
this.subnetId = subnetId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AzureTemplateOptions clone() {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
copyTo(options);
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(TemplateOptions to) {
|
||||
super.copyTo(to);
|
||||
if (to instanceof AzureTemplateOptions) {
|
||||
AzureTemplateOptions eTo = AzureTemplateOptions.class.cast(to);
|
||||
eTo.customData(customData);
|
||||
eTo.virtualNetworkAddressPrefix(virtualNetworkAddressPrefix);
|
||||
eTo.subnetAddressPrefix(subnetAddressPrefix);
|
||||
eTo.DNSLabelPrefix(DNSLabelPrefix);
|
||||
eTo.keyVaultIdAndSecret(keyVaultIdAndSecret);
|
||||
eTo.virtualNetworkName(virtualNetworkName);
|
||||
eTo.subnetId(subnetId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(super.hashCode(), virtualNetworkAddressPrefix, subnetAddressPrefix, DNSLabelPrefix, customData, keyVaultIdAndSecret, virtualNetworkName, subnetId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AzureTemplateOptions other = (AzureTemplateOptions) obj;
|
||||
return super.equals(other)
|
||||
&& equal(this.customData, other.customData)
|
||||
&& equal(this.virtualNetworkAddressPrefix, other.virtualNetworkAddressPrefix)
|
||||
&& equal(this.subnetAddressPrefix, other.subnetAddressPrefix)
|
||||
&& equal(this.DNSLabelPrefix, other.DNSLabelPrefix)
|
||||
&& equal(this.keyVaultIdAndSecret, other.keyVaultIdAndSecret)
|
||||
&& equal(this.virtualNetworkName, other.virtualNetworkName)
|
||||
&& equal(this.subnetId, other.subnetId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Objects.ToStringHelper string() {
|
||||
Objects.ToStringHelper toString = super.string().omitNullValues();
|
||||
toString.add("customData", customData);
|
||||
toString.add("virtualNetworkAddressPrefix", virtualNetworkAddressPrefix);
|
||||
toString.add("subnetAddressPrefix", subnetAddressPrefix);
|
||||
toString.add("DNSLabelPrefix", DNSLabelPrefix);
|
||||
toString.add("keyVaultIdAndSecret", keyVaultIdAndSecret);
|
||||
toString.add("virtualNetworkName", virtualNetworkName);
|
||||
toString.add("subnetId", subnetId);
|
||||
return toString;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#customData
|
||||
*/
|
||||
public static AzureTemplateOptions customData(String customData) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.customData(customData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#virtualNetworkAddressPrefix
|
||||
*/
|
||||
public static AzureTemplateOptions virtualNetworkAddressPrefix(String virtualNetworkAddressPrefix) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.virtualNetworkAddressPrefix(virtualNetworkAddressPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#subnetAddressPrefix
|
||||
*/
|
||||
public static AzureTemplateOptions subnetAddressPrefix(String subnetAddressPrefix) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.subnetAddressPrefix(subnetAddressPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#DNSLabelPrefix
|
||||
*/
|
||||
public static AzureTemplateOptions DNSLabelPrefix(String DNSLabelPrefix) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.DNSLabelPrefix(DNSLabelPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#keyVaultIdAndSecret
|
||||
*/
|
||||
public static AzureTemplateOptions keyVaultIdAndSecret(String keyVaultIdAndSecret) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.keyVaultIdAndSecret(keyVaultIdAndSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#virtualNetworkName
|
||||
*/
|
||||
public static AzureTemplateOptions virtualNetworkName(String virtualNetworkName) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.virtualNetworkName(virtualNetworkName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AzureTemplateOptions#subnetId
|
||||
*/
|
||||
public static AzureTemplateOptions subnetId(String subnetId) {
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
return options.subnetId(subnetId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.compute.strategy;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -28,8 +29,13 @@ import javax.inject.Singleton;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
|
||||
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceGroup;
|
||||
import org.jclouds.azurecompute.arm.domain.Subnet;
|
||||
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
|
||||
import org.jclouds.azurecompute.arm.features.SubnetApi;
|
||||
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
|
@ -40,7 +46,7 @@ import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIn
|
|||
import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||
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 com.google.common.collect.Multimap;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
@ -54,6 +60,7 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
|
|||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final AzureComputeApi api;
|
||||
private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
|
||||
|
||||
@Inject
|
||||
protected CreateResourceGroupThenCreateNodes(
|
||||
|
@ -62,11 +69,12 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
|
|||
GroupNamingConvention.Factory namingConvention,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
|
||||
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
|
||||
AzureComputeApi api) {
|
||||
AzureComputeApi api, AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants) {
|
||||
super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
|
||||
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
|
||||
this.api = checkNotNull(api, "api cannot be null");
|
||||
checkNotNull(userExecutor, "userExecutor cannot be null");
|
||||
this.azureComputeConstants = azureComputeConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,23 +82,59 @@ public class CreateResourceGroupThenCreateNodes extends CreateNodesWithGroupEnco
|
|||
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
|
||||
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
|
||||
String azureGroupName = this.azureComputeConstants.azureResourceGroup();
|
||||
|
||||
AzureTemplateOptions options = template.getOptions().as(AzureTemplateOptions.class);
|
||||
// create resource group for jclouds group if it does not already exist
|
||||
ResourceGroupApi resourceGroupApi = api.getResourceGroupApi();
|
||||
ResourceGroup resourceGroup = resourceGroupApi.get(group);
|
||||
ResourceGroup resourceGroup = resourceGroupApi.get(azureGroupName);
|
||||
final String location = template.getLocation().getId();
|
||||
final String resourceGroupName;
|
||||
|
||||
if (resourceGroup == null){
|
||||
|
||||
final Map<String, String> tags = ImmutableMap.of("description", "jClouds managed VMs");
|
||||
resourceGroupName = resourceGroupApi.create(group, location, tags).name();
|
||||
} else {
|
||||
resourceGroupName = resourceGroup.name();
|
||||
resourceGroupApi.create(azureGroupName, location, tags).name();
|
||||
}
|
||||
|
||||
Map<?, ListenableFuture<Void>> responses = super.execute(resourceGroupName, count, template, goodNodes, badNodes,
|
||||
String vnetName = azureGroupName + "virtualnetwork";
|
||||
String subnetName = azureGroupName + "subnet";
|
||||
|
||||
if (options.getVirtualNetworkName() != null) {
|
||||
vnetName = options.getVirtualNetworkName();
|
||||
}
|
||||
|
||||
this.getOrCreateVirtualNetworkWithSubnet(vnetName, subnetName, location, options, azureGroupName);
|
||||
|
||||
|
||||
Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes,
|
||||
customizationResponses);
|
||||
|
||||
return responses;
|
||||
}
|
||||
|
||||
protected synchronized void getOrCreateVirtualNetworkWithSubnet(
|
||||
final String virtualNetworkName, final String subnetName, final String location,
|
||||
AzureTemplateOptions options, final String azureGroupName) {
|
||||
|
||||
//Subnets belong to a virtual network so that needs to be created first
|
||||
VirtualNetworkApi vnApi = api.getVirtualNetworkApi(azureGroupName);
|
||||
VirtualNetwork vn = vnApi.get(virtualNetworkName);
|
||||
|
||||
if (vn == null) {
|
||||
VirtualNetwork.VirtualNetworkProperties virtualNetworkProperties = VirtualNetwork.VirtualNetworkProperties.builder()
|
||||
.addressSpace(VirtualNetwork.AddressSpace.create(Arrays.asList(this.azureComputeConstants.azureDefaultVnetAddressPrefixProperty())))
|
||||
.subnets(
|
||||
Arrays.asList(
|
||||
Subnet.create(subnetName, null, null,
|
||||
Subnet.SubnetProperties.builder().addressPrefix(this.azureComputeConstants.azureDefaultSubnetAddressPrefixProperty()).build())))
|
||||
.build();
|
||||
vn = vnApi.createOrUpdate(virtualNetworkName, location, virtualNetworkProperties);
|
||||
}
|
||||
|
||||
SubnetApi subnetApi = api.getSubnetApi(azureGroupName, virtualNetworkName);
|
||||
Subnet subnet = subnetApi.get(subnetName);
|
||||
|
||||
options.virtualNetworkName(virtualNetworkName);
|
||||
options.subnetId(subnet.id());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,4 +41,10 @@ public class AzureComputeProperties {
|
|||
|
||||
public static final String TIMEOUT_RESOURCE_DELETED = "jclouds.azurecompute.arm.timeout.resourcedeleted";
|
||||
|
||||
public static final String DEFAULT_VNET_ADDRESS_SPACE_PREFIX = "jclouds.azurecompute.arm.vnet.addressprefix";
|
||||
|
||||
public static final String DEFAULT_SUBNET_ADDRESS_PREFIX = "jclouds.azurecompute.arm.subnet.addressprefix";
|
||||
|
||||
public static final String DEFAULT_DATADISKSIZE = "jclouds.azurecompute.arm.datadisksize";
|
||||
|
||||
}
|
||||
|
|
|
@ -31,8 +31,25 @@ public abstract class DeploymentTemplate {
|
|||
//Empty placeholders as we want to generate the empty JSON object
|
||||
@AutoValue
|
||||
public abstract static class Parameters {
|
||||
public static Parameters create() {
|
||||
return new AutoValue_DeploymentTemplate_Parameters();
|
||||
|
||||
@Nullable
|
||||
public abstract KeyVaultReference publicKeyFromAzureKeyVault();
|
||||
|
||||
public static Parameters create(KeyVaultReference reference)
|
||||
{
|
||||
return new AutoValue_DeploymentTemplate_Parameters(reference);
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
public abstract static class TemplateParameters {
|
||||
|
||||
@Nullable
|
||||
public abstract TemplateParameterType publicKeyFromAzureKeyVault();
|
||||
|
||||
public static TemplateParameters create(TemplateParameterType publicKeyFromAzureKeyVault)
|
||||
{
|
||||
return new AutoValue_DeploymentTemplate_TemplateParameters(publicKeyFromAzureKeyVault);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +57,7 @@ public abstract class DeploymentTemplate {
|
|||
|
||||
public abstract String contentVersion();
|
||||
|
||||
public abstract Parameters parameters();
|
||||
public abstract TemplateParameters parameters();
|
||||
|
||||
public abstract Map<String, String> variables();
|
||||
|
||||
|
@ -52,7 +69,7 @@ public abstract class DeploymentTemplate {
|
|||
@SerializedNames({"$schema", "contentVersion", "parameters", "variables", "resources" , "outputs"})
|
||||
public static DeploymentTemplate create(final String schema,
|
||||
final String contentVersion,
|
||||
final Parameters parameters,
|
||||
final TemplateParameters parameters,
|
||||
final Map<String, String> variables,
|
||||
final List<ResourceDefinition> resources,
|
||||
final List<?> outputs) {
|
||||
|
@ -83,7 +100,7 @@ public abstract class DeploymentTemplate {
|
|||
|
||||
public abstract Builder contentVersion(String type);
|
||||
|
||||
public abstract Builder parameters(Parameters parameters);
|
||||
public abstract Builder parameters(TemplateParameters parameters);
|
||||
|
||||
public abstract Builder variables(Map<String, String> variables);
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.azurecompute.arm.domain;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
// Simple helper class to serialize / deserialize keyvault reference.
|
||||
|
||||
@AutoValue
|
||||
public abstract class KeyVaultReference {
|
||||
|
||||
@AutoValue
|
||||
public abstract static class Reference {
|
||||
|
||||
public abstract IdReference keyVault();
|
||||
|
||||
public abstract String secretName();
|
||||
|
||||
@SerializedNames({"keyVault", "secretName"})
|
||||
public static Reference create(final IdReference keyVault, final String secretName) {
|
||||
return new AutoValue_KeyVaultReference_Reference(keyVault, secretName);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Reference reference();
|
||||
|
||||
@SerializedNames({"reference"})
|
||||
public static KeyVaultReference create(final Reference reference) {
|
||||
return new AutoValue_KeyVaultReference(reference);
|
||||
}
|
||||
}
|
|
@ -38,13 +38,17 @@ public abstract class NetworkInterfaceCardProperties {
|
|||
@Nullable
|
||||
public abstract List<IpConfiguration> ipConfigurations();
|
||||
|
||||
@SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations"})
|
||||
public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid, final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations) {
|
||||
@Nullable
|
||||
public abstract IdReference networkSecurityGroup();
|
||||
|
||||
@SerializedNames({"provisioningState", "resourceGuid", "enableIPForwarding", "ipConfigurations", "networkSecurityGroup"})
|
||||
public static NetworkInterfaceCardProperties create(final String provisioningState, final String resourceGuid, final Boolean enableIPForwarding, final List<IpConfiguration> ipConfigurations, final IdReference networkSecurityGroup) {
|
||||
NetworkInterfaceCardProperties.Builder builder = NetworkInterfaceCardProperties.builder()
|
||||
.provisioningState(provisioningState)
|
||||
.resourceGuid(resourceGuid)
|
||||
.enableIPForwarding(enableIPForwarding)
|
||||
.ipConfigurations(ipConfigurations == null ? null : ImmutableList.copyOf(ipConfigurations));
|
||||
.ipConfigurations(ipConfigurations == null ? null : ImmutableList.copyOf(ipConfigurations))
|
||||
.networkSecurityGroup(networkSecurityGroup);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
@ -66,6 +70,8 @@ public abstract class NetworkInterfaceCardProperties {
|
|||
|
||||
abstract List<IpConfiguration> ipConfigurations();
|
||||
|
||||
public abstract Builder networkSecurityGroup(IdReference networkSecurityGroup);
|
||||
|
||||
abstract NetworkInterfaceCardProperties autoBuild();
|
||||
|
||||
public NetworkInterfaceCardProperties build() {
|
||||
|
|
|
@ -52,15 +52,22 @@ public abstract class OSDisk {
|
|||
@Nullable
|
||||
public abstract String createOption();
|
||||
|
||||
@SerializedNames({"osType", "name", "vhd", "caching", "createOption"})
|
||||
/**
|
||||
* The url of the custom image
|
||||
*/
|
||||
@Nullable
|
||||
public abstract VHD image();
|
||||
|
||||
@SerializedNames({"osType", "name", "vhd", "caching", "createOption", "image"})
|
||||
public static OSDisk create(final String osType, final String name, final VHD vhd,
|
||||
final String caching, final String createOption) {
|
||||
final String caching, final String createOption, final VHD image) {
|
||||
return builder()
|
||||
.osType(osType)
|
||||
.name(name)
|
||||
.vhd(vhd)
|
||||
.caching(caching)
|
||||
.createOption(createOption)
|
||||
.image(image)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -71,15 +78,11 @@ public abstract class OSDisk {
|
|||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
public abstract Builder osType(String osType);
|
||||
|
||||
public abstract Builder name(String name);
|
||||
|
||||
public abstract Builder caching(String caching);
|
||||
|
||||
public abstract Builder createOption(String createOption);
|
||||
|
||||
public abstract Builder vhd(VHD vhd);
|
||||
|
||||
public abstract Builder image(VHD image);
|
||||
public abstract OSDisk build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public abstract class StorageProfile {
|
|||
/**
|
||||
* The image reference of the storage profile
|
||||
*/
|
||||
@Nullable
|
||||
public abstract ImageReference imageReference();
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.azurecompute.arm.domain;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
// Simple helper class to serialize / deserialize id reference.
|
||||
|
||||
@AutoValue
|
||||
public abstract class TemplateParameterType {
|
||||
@Nullable
|
||||
public abstract String type();
|
||||
|
||||
@SerializedNames({"type"})
|
||||
public static TemplateParameterType create(final String type) {
|
||||
return new AutoValue_TemplateParameterType(type);
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.domain;
|
|||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class VMDeployment {
|
||||
|
||||
|
@ -28,4 +29,8 @@ public class VMDeployment {
|
|||
public VirtualMachineInstance vm;
|
||||
|
||||
public VirtualMachine virtualMachine;
|
||||
|
||||
public Map<String, String> userMetaData;
|
||||
|
||||
public Iterable<String> tags;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.jclouds.azurecompute.arm.domain;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
/**
|
||||
* A VM Size that is available in a region for a given subscription.
|
||||
|
@ -24,45 +25,51 @@ import com.google.auto.value.AutoValue;
|
|||
* @see <a href="https://msdn.microsoft.com/en-us/library/azure/mt269440.aspx" >api</a>
|
||||
*/
|
||||
@AutoValue
|
||||
public class VMHardware {
|
||||
public abstract class VMHardware {
|
||||
|
||||
/**
|
||||
* The name of the VM size.
|
||||
*/
|
||||
public String name;
|
||||
public abstract String name();
|
||||
|
||||
/**
|
||||
* The number of cores that are available in the VM size.
|
||||
*/
|
||||
public Integer numberOfCores;
|
||||
public abstract Integer numberOfCores();
|
||||
|
||||
/**
|
||||
* Specifies the size in MB of the OS Disk.
|
||||
*/
|
||||
public Integer osDiskSizeInMB;
|
||||
public abstract Integer osDiskSizeInMB();
|
||||
|
||||
/**
|
||||
* The size of the resource disk.
|
||||
*/
|
||||
public Integer resourceDiskSizeInMB;
|
||||
public abstract Integer resourceDiskSizeInMB();
|
||||
|
||||
/**
|
||||
* Specifies the available RAM in MB.
|
||||
*/
|
||||
public Integer memoryInMB;
|
||||
public abstract Integer memoryInMB();
|
||||
|
||||
/**
|
||||
* Specifies the maximum number of data disks that can be attached to the VM size.
|
||||
*/
|
||||
public Integer maxDataDiskCount;
|
||||
public abstract Integer maxDataDiskCount();
|
||||
|
||||
/**
|
||||
* Specifies the location of the HW resource
|
||||
*/
|
||||
public String location;
|
||||
public abstract String location();
|
||||
|
||||
/**
|
||||
* Specifies if this HW is globally available
|
||||
*/
|
||||
public boolean globallyAvailable;
|
||||
public abstract boolean globallyAvailable();
|
||||
|
||||
@SerializedNames({ "name", "numberOfCores", "osDiskSizeInMB", "resourceDiskSizeInMB", "memoryInMB", "maxDataDiskCount", "location", "globallyAvailable"})
|
||||
public static VMHardware create(String name, Integer numberOfCores, Integer osDiskSizeInMB, Integer resourceDiskSizeInMB, Integer memoryInMB, Integer maxDataDiskCount, String location, boolean globallyAvailable) {
|
||||
|
||||
return new AutoValue_VMHardware(name, numberOfCores, osDiskSizeInMB, resourceDiskSizeInMB, memoryInMB, maxDataDiskCount, location, globallyAvailable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,37 +17,44 @@
|
|||
package org.jclouds.azurecompute.arm.domain;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
@AutoValue
|
||||
public class VMImage {
|
||||
public abstract class VMImage {
|
||||
|
||||
/**
|
||||
* The publisher of the image reference.
|
||||
*/
|
||||
public String publisher;
|
||||
public abstract String publisher();
|
||||
|
||||
/**
|
||||
* The offer of the image reference.
|
||||
*/
|
||||
public String offer;
|
||||
public abstract String offer();
|
||||
|
||||
/**
|
||||
* The sku of the image reference.
|
||||
*/
|
||||
public String sku;
|
||||
public abstract String sku();
|
||||
|
||||
/**
|
||||
* The version of the image reference.
|
||||
*/
|
||||
public String version;
|
||||
public abstract String version();
|
||||
|
||||
/**
|
||||
* The location from where Image was fetched
|
||||
*/
|
||||
public String location;
|
||||
public abstract String location();
|
||||
|
||||
/**
|
||||
* Specifies if this image is globally available
|
||||
*/
|
||||
public boolean globallyAvailable;
|
||||
public abstract boolean globallyAvailable();
|
||||
|
||||
@SerializedNames({ "publisher", "offer", "sku", "version", "location", "globallyAvailable"})
|
||||
public static VMImage create(String publisher, String offer, String sku, String version, String location, boolean globallyAvailable) {
|
||||
|
||||
return new AutoValue_VMImage(publisher, offer, sku, version, location, globallyAvailable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,21 @@
|
|||
package org.jclouds.azurecompute.arm.features;
|
||||
import java.io.Closeable;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.GET;
|
||||
|
||||
import org.jclouds.Fallbacks;
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
|
||||
import org.jclouds.oauth.v2.filters.OAuthFilter;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The Azure Resource Manager API checks for job status and progress.
|
||||
|
@ -37,5 +43,14 @@ public interface JobApi extends Closeable{
|
|||
@GET
|
||||
@ResponseParser(ParseJobStatus.class)
|
||||
JobStatus jobStatus(@EndpointParam URI jobURI);
|
||||
|
||||
/**
|
||||
* Get status of captured custom image after capture call
|
||||
*/
|
||||
@GET
|
||||
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
|
||||
@SelectJson("resources")
|
||||
List<ResourceDefinition> captureStatus(@EndpointParam URI jobURI);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -131,5 +131,30 @@ public interface VirtualMachineApi {
|
|||
@Path("/{name}/powerOff")
|
||||
void stop(@PathParam("name") String name);
|
||||
|
||||
/**
|
||||
* Generalize the virtual machine
|
||||
*/
|
||||
@Named("generalize")
|
||||
@POST
|
||||
@Path("/{name}/generalize")
|
||||
void generalize(@PathParam("name") String name);
|
||||
|
||||
/**
|
||||
* Capture the virtual machine image
|
||||
* destinationContainerName: the name of the folder created under the "system" container in the storage account
|
||||
* Folder structure: Microsoft.Computer > Images > destinationContainerName
|
||||
* Within the folder, there will be 1 page blob for the osDisk vhd and 1 block blob for the vmTemplate json file
|
||||
*/
|
||||
@Named("capture")
|
||||
@POST
|
||||
@Payload("%7B\"vhdPrefix\":\"{vhdPrefix}\",\"destinationContainerName\":\"{destinationContainerName}\",\"overwriteVhds\":\"true\"%7D")
|
||||
@MapBinder(BindToJsonPayload.class)
|
||||
@Path("/{name}/capture")
|
||||
@ResponseParser(URIParser.class)
|
||||
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
|
||||
URI capture(@PathParam("name") String name,
|
||||
@PayloadParam("vhdPrefix") String vhdPrefix,
|
||||
@PayloadParam("destinationContainerName") String destinationContainerName);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,15 @@ import javax.inject.Singleton;
|
|||
|
||||
import com.google.common.base.Predicate;
|
||||
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.NetworkSecurityGroup;
|
||||
import org.jclouds.azurecompute.arm.domain.PublicIPAddress;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualMachine;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.azurecompute.arm.domain.StorageService;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -36,6 +43,7 @@ import java.net.URI;
|
|||
@Singleton
|
||||
public class CleanupResources implements Function<String, Boolean> {
|
||||
|
||||
private final AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
@ -46,9 +54,10 @@ public class CleanupResources implements Function<String, Boolean> {
|
|||
|
||||
@Inject
|
||||
public CleanupResources(AzureComputeApi azureComputeApi,
|
||||
AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants,
|
||||
@Named(TIMEOUT_NODE_TERMINATED) Predicate<URI> nodeTerminated,
|
||||
@Named(TIMEOUT_RESOURCE_DELETED) Predicate<URI> resourceDeleted) {
|
||||
|
||||
this.azureComputeConstants = azureComputeConstants;
|
||||
this.api = azureComputeApi;
|
||||
this.nodeTerminated = nodeTerminated;
|
||||
this.resourceDeleted = resourceDeleted;
|
||||
|
@ -58,36 +67,67 @@ public class CleanupResources implements Function<String, Boolean> {
|
|||
public Boolean apply(String id) {
|
||||
|
||||
logger.debug("Destroying %s ...", id);
|
||||
String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "storage";
|
||||
int index = id.lastIndexOf("-");
|
||||
String group = id.substring(0, index);
|
||||
String storageAccountName = id.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
|
||||
String group = azureComputeConstants.azureResourceGroup();
|
||||
|
||||
// Delete VM
|
||||
VirtualMachine vm = api.getVirtualMachineApi(group).get(id);
|
||||
if (vm != null) {
|
||||
URI uri = api.getVirtualMachineApi(group).delete(id);
|
||||
if (uri != null){
|
||||
if (uri != null) {
|
||||
boolean jobDone = nodeTerminated.apply(uri);
|
||||
boolean storageAcctDeleteStatus = false;
|
||||
boolean deploymentDeleteStatus = false;
|
||||
|
||||
if (jobDone) {
|
||||
// Delete storage account
|
||||
api.getStorageAccountApi(group).delete(storageAccountName);
|
||||
|
||||
// Delete NIC
|
||||
uri = api.getNetworkInterfaceCardApi(group).delete(id + "nic");
|
||||
if (uri != null){
|
||||
jobDone = resourceDeleted.apply(uri);
|
||||
if (jobDone) {
|
||||
|
||||
// Delete deployment
|
||||
StorageService ss = api.getStorageAccountApi(group).get(storageAccountName);
|
||||
if (ss != null) {
|
||||
storageAcctDeleteStatus = api.getStorageAccountApi(group).delete(storageAccountName);
|
||||
} else {
|
||||
storageAcctDeleteStatus = true;
|
||||
}
|
||||
Deployment deployment = api.getDeploymentApi(group).get(id);
|
||||
if (deployment != null) {
|
||||
uri = api.getDeploymentApi(group).delete(id);
|
||||
jobDone = resourceDeleted.apply(uri);
|
||||
if (jobDone) {
|
||||
// Delete public ip
|
||||
boolean ipDeleteStatus = api.getPublicIPAddressApi(group).delete(id + "publicip");
|
||||
deploymentDeleteStatus = true;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
// Delete Virtual network
|
||||
boolean vnetDeleteStatus = api.getVirtualNetworkApi(group).delete(group + "virtualnetwork");
|
||||
return ipDeleteStatus && vnetDeleteStatus;
|
||||
// Get NSG
|
||||
boolean nsgDeleteStatus = false;
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsgDeleteStatus = true;
|
||||
}
|
||||
|
||||
return deploymentDeleteStatus && storageAcctDeleteStatus && ipDeleteStatus && nsgDeleteStatus;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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 com.google.common.base.Function;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.jclouds.http.HttpUtils.releasePayload;
|
||||
|
||||
/**
|
||||
* Parses an http response code from http responser
|
||||
*/
|
||||
@Singleton
|
||||
public class StatusCodeParser implements Function<HttpResponse, String> {
|
||||
public String apply(final HttpResponse from) {
|
||||
releasePayload(from);
|
||||
final String statusCode = Integer.toString(from.getStatusCode());
|
||||
if (statusCode != null) {
|
||||
return statusCode;
|
||||
}
|
||||
throw new IllegalStateException("did not receive RequestId in: " + from);
|
||||
}
|
||||
}
|
|
@ -48,7 +48,12 @@ public class AzureComputeErrorHandler implements HttpErrorHandler {
|
|||
: message;
|
||||
switch (response.getStatusCode()) {
|
||||
case 400:
|
||||
if (message.contains("unauthorized_client")) {
|
||||
exception = new AuthorizationException(message, exception);
|
||||
}
|
||||
else {
|
||||
exception = new IllegalArgumentException(message, exception);
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
case 403:
|
||||
|
|
|
@ -16,37 +16,42 @@
|
|||
*/
|
||||
package org.jclouds.azurecompute.arm.util;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import org.jclouds.azurecompute.arm.compute.config.AzureComputeServiceContextModule;
|
||||
import org.jclouds.azurecompute.arm.domain.DeploymentProperties;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
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.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.Subnet;
|
||||
import org.jclouds.azurecompute.arm.domain.Subnet.SubnetProperties;
|
||||
import org.jclouds.azurecompute.arm.domain.TemplateParameterType;
|
||||
import org.jclouds.azurecompute.arm.domain.VHD;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualNetwork.VirtualNetworkProperties;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualNetwork.AddressSpace;
|
||||
import org.jclouds.azurecompute.arm.domain.StorageService.StorageServiceProperties;
|
||||
import org.jclouds.azurecompute.arm.domain.IdReference;
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
|
||||
import org.jclouds.azurecompute.arm.domain.NetworkSecurityGroupProperties;
|
||||
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRule;
|
||||
import org.jclouds.azurecompute.arm.domain.NetworkSecurityRuleProperties;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.json.Json;
|
||||
|
||||
|
@ -56,8 +61,10 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
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 {
|
||||
|
@ -66,11 +73,14 @@ public class DeploymentTemplateBuilder {
|
|||
}
|
||||
|
||||
private final String name;
|
||||
private final String azureGroup;
|
||||
private final String group;
|
||||
private final Template template;
|
||||
private final Json json;
|
||||
|
||||
private TemplateOptions options;
|
||||
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;
|
||||
|
@ -79,10 +89,6 @@ public class DeploymentTemplateBuilder {
|
|||
private AzureComputeServiceContextModule.AzureComputeConstants azureComputeConstants;
|
||||
|
||||
private static final String DEPLOYMENT_MODE = "Incremental";
|
||||
private static final String DEFAULT_DATA_DISK_SIZE = "1023";
|
||||
|
||||
private static final String DEFAULT_vnAddresSpacePrefix = "10.0.0.0/16";
|
||||
private static final String DEFAULT_subnetAddressPrefix = "10.0.0.0/24";
|
||||
|
||||
@Inject
|
||||
DeploymentTemplateBuilder(Json json, @Assisted("group") String group, @Assisted("name") String name, @Assisted Template template,
|
||||
|
@ -90,13 +96,16 @@ public class DeploymentTemplateBuilder {
|
|||
this.name = name;
|
||||
this.group = group;
|
||||
this.template = template;
|
||||
this.options = template.getOptions().as(TemplateOptions.class);
|
||||
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;
|
||||
|
@ -126,30 +135,53 @@ public class DeploymentTemplateBuilder {
|
|||
public DeploymentBody getDeploymentTemplate() {
|
||||
|
||||
addStorageResource();
|
||||
addVirtualNetworkResource();
|
||||
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(DeploymentTemplate.Parameters.create())
|
||||
.parameters(templateParameters)
|
||||
.build();
|
||||
|
||||
DeploymentBody body = DeploymentBody.create(template, DEPLOYMENT_MODE, DeploymentTemplate.Parameters.create());
|
||||
DeploymentBody body = DeploymentBody.create(template, DEPLOYMENT_MODE, parameters);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
public String getDeploymentTemplateJson(DeploymentProperties properties){
|
||||
public String getDeploymentTemplateJson(DeploymentProperties properties) {
|
||||
return json.toJson(properties);
|
||||
}
|
||||
|
||||
private void addStorageResource() {
|
||||
String storageAccountName = name.replaceAll("[^A-Za-z0-9 ]", "") + "storage";
|
||||
String storageAccountName = name.replaceAll("[^A-Za-z0-9 ]", "") + "stor";
|
||||
|
||||
String storageName = template.getImage().getName();
|
||||
if (storageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
|
||||
storageAccountName = storageName.substring(CUSTOM_IMAGE_PREFIX.length()); // get group name
|
||||
}
|
||||
|
||||
variables.put("storageAccountName", storageAccountName);
|
||||
|
||||
|
@ -168,47 +200,13 @@ public class DeploymentTemplateBuilder {
|
|||
resources.add(storageAccount);
|
||||
}
|
||||
|
||||
private void addVirtualNetworkResource() {
|
||||
String virtualNetworkName = group + "virtualnetwork";
|
||||
|
||||
String subnetName = group + "subnet";
|
||||
variables.put("virtualNetworkName", virtualNetworkName);
|
||||
variables.put("virtualNetworkReference", "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]");
|
||||
variables.put("subnetName", subnetName);
|
||||
variables.put("subnetReference", "[concat(variables('virtualNetworkReference'),'/subnets/',variables('subnetName'))]");
|
||||
|
||||
VirtualNetworkProperties properties = VirtualNetworkProperties.builder()
|
||||
.addressSpace(
|
||||
AddressSpace.create(Arrays.asList(DEFAULT_vnAddresSpacePrefix))
|
||||
)
|
||||
.subnets(
|
||||
Arrays.asList(
|
||||
Subnet.create("[variables('subnetName')]", null, null,
|
||||
SubnetProperties.builder()
|
||||
.addressPrefix(DEFAULT_subnetAddressPrefix).build()
|
||||
))
|
||||
)
|
||||
.build();
|
||||
|
||||
|
||||
ResourceDefinition virtualNetwork = ResourceDefinition.builder()
|
||||
.name("[variables('virtualNetworkName')]")
|
||||
.type("Microsoft.Network/virtualNetworks")
|
||||
.location(location)
|
||||
.apiVersion(STORAGE_API_VERSION)
|
||||
.properties(properties)
|
||||
.build();
|
||||
|
||||
resources.add(virtualNetwork);
|
||||
}
|
||||
|
||||
private void addPublicIpAddress() {
|
||||
String publicIPAddressName = name + "publicip";
|
||||
String dnsLabelPrefix = name; //TODO: read from Azure template properties
|
||||
String dnsLabelPrefix = options.getDNSLabelPrefix();
|
||||
|
||||
PublicIPAddressProperties.Builder properties = PublicIPAddressProperties.builder();
|
||||
|
||||
if (!dnsLabelPrefix.isEmpty()) {
|
||||
if (!Strings.isNullOrEmpty(dnsLabelPrefix)) {
|
||||
properties.dnsSettings(DnsSettings.builder().domainNameLabel(dnsLabelPrefix).build());
|
||||
variables.put("dnsLabelPrefix", dnsLabelPrefix);
|
||||
}
|
||||
|
@ -233,7 +231,11 @@ public class DeploymentTemplateBuilder {
|
|||
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()
|
||||
|
@ -244,9 +246,22 @@ public class DeploymentTemplateBuilder {
|
|||
|
||||
ipConfigurations.add(ipConfig);
|
||||
|
||||
NetworkInterfaceCardProperties networkInterfaceCardProperties = NetworkInterfaceCardProperties.builder()
|
||||
.ipConfigurations(ipConfigurations)
|
||||
.build();
|
||||
// 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);
|
||||
|
@ -257,16 +272,58 @@ public class DeploymentTemplateBuilder {
|
|||
.type("Microsoft.Network/networkInterfaces")
|
||||
.location(location)
|
||||
.apiVersion(STORAGE_API_VERSION)
|
||||
.dependsOn(Arrays.asList("[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"))
|
||||
.dependsOn(depends)
|
||||
.properties(networkInterfaceCardProperties)
|
||||
.build();
|
||||
|
||||
resources.add(networkInterfaceCard);
|
||||
}
|
||||
|
||||
private void addVirtualMachine() {
|
||||
private void addNetworkSecurityGroup() {
|
||||
int ports[] = options.getInboundPorts();
|
||||
if ((ports != null) && (ports.length > 0)) {
|
||||
variables.put("networkSecurityGroupName", name + "nsg");
|
||||
variables.put("networkSecurityGroupNameReference", "[resourceId('Microsoft.Network/networkSecurityGroups',variables('networkSecurityGroupName'))]");
|
||||
|
||||
List<NetworkSecurityRule> rules = new ArrayList<NetworkSecurityRule>();
|
||||
for (int i = 0; i < ports.length; i++) {
|
||||
NetworkSecurityRuleProperties ruleProperties = NetworkSecurityRuleProperties.builder()
|
||||
.description("default-allow-port-" + ports[i])
|
||||
.protocol(NetworkSecurityRuleProperties.Protocol.All)
|
||||
.access(NetworkSecurityRuleProperties.Access.Allow)
|
||||
.sourcePortRange("*")
|
||||
.destinationPortRange(Integer.toString(ports[i]))
|
||||
.sourceAddressPrefix("*")
|
||||
.destinationAddressPrefix("*")
|
||||
.priority(1234 + i)
|
||||
.direction(NetworkSecurityRuleProperties.Direction.Inbound)
|
||||
.build();
|
||||
|
||||
NetworkSecurityRule networkSecurityRule = NetworkSecurityRule.create(
|
||||
"default-allow-port-" + ports[i],
|
||||
null,
|
||||
null,
|
||||
ruleProperties);
|
||||
|
||||
rules.add(networkSecurityRule);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addVirtualMachine() {
|
||||
//Build OS Profile
|
||||
final String computerName = name + "pc";
|
||||
|
||||
|
@ -275,51 +332,52 @@ public class DeploymentTemplateBuilder {
|
|||
.adminUsername(loginUser)
|
||||
.computerName(computerName);
|
||||
|
||||
boolean usePublicKey = options.getPublicKey() != null;
|
||||
profileBuilder.adminPassword(loginPassword);
|
||||
//boolean usePublicKey = options.getPublicKey() != null;
|
||||
|
||||
if (usePublicKey) {
|
||||
OSProfile.LinuxConfiguration configuration = OSProfile.LinuxConfiguration.create("true",
|
||||
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')]",
|
||||
options.getPublicKey())
|
||||
"[parameters('publicKeyFromAzureKeyVault')]"
|
||||
))
|
||||
);
|
||||
));
|
||||
profileBuilder.linuxConfiguration(configuration);
|
||||
} else {
|
||||
profileBuilder.adminPassword(loginPassword);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(options.getCustomData())){
|
||||
String encodedCustomData = base64().encode(options.getCustomData().getBytes());
|
||||
profileBuilder.customData(encodedCustomData);
|
||||
}
|
||||
|
||||
OSProfile osProfile = profileBuilder.build();
|
||||
|
||||
//Build Image Reference
|
||||
final String imagePublisher = template.getImage().getProviderId();
|
||||
final String imageOffer = template.getImage().getName();
|
||||
final String imageSku = template.getImage().getVersion();
|
||||
|
||||
ImageReference imageReference = ImageReference.builder()
|
||||
.publisher(imagePublisher)
|
||||
.offer(imageOffer)
|
||||
.sku(imageSku)
|
||||
.version("latest")
|
||||
.build();
|
||||
|
||||
//Build OsDisk
|
||||
final String storageAccountContainerName = "vhds";
|
||||
final String storageAccountContainerName = name + "vhds";
|
||||
variables.put("storageAccountContainerName", storageAccountContainerName);
|
||||
|
||||
final String osDiskName = name + "osdisk";
|
||||
variables.put("osDiskName", osDiskName);
|
||||
|
||||
OSDisk osDisk = OSDisk.builder()
|
||||
.name("[variables('osDiskName')]")
|
||||
.vhd(
|
||||
VHD.create("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('osDiskName'),'.vhd')]")
|
||||
)
|
||||
.caching("ReadWrite")
|
||||
.createOption("FromImage")
|
||||
.build();
|
||||
boolean usingMarketplaceImage = true;
|
||||
String cusotomImageUri = "";
|
||||
|
||||
// TODO: make new fields for group information
|
||||
String publisher = template.getImage().getProviderId();
|
||||
String storageName = template.getImage().getName();
|
||||
String sku = template.getImage().getDescription(); // this is actual VHD
|
||||
if (storageName.startsWith(CUSTOM_IMAGE_PREFIX)) {
|
||||
storageName = storageName.substring(CUSTOM_IMAGE_PREFIX.length()); // get group name
|
||||
cusotomImageUri = sku;
|
||||
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";
|
||||
|
@ -328,7 +386,7 @@ public class DeploymentTemplateBuilder {
|
|||
List<DataDisk> dataDisks = new ArrayList<DataDisk>();
|
||||
DataDisk dataDisk = DataDisk.builder()
|
||||
.name("[variables('dataDiskName')]")
|
||||
.diskSizeGB(DEFAULT_DATA_DISK_SIZE)
|
||||
.diskSizeGB(azureComputeConstants.azureDefaultDataDiskSizeProperty())
|
||||
.lun(0)
|
||||
.vhd(
|
||||
VHD.create("[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('storageAccountContainerName'),'/',variables('dataDiskName'),'.vhd')]")
|
||||
|
@ -339,11 +397,20 @@ public class DeploymentTemplateBuilder {
|
|||
dataDisks.add(dataDisk);
|
||||
|
||||
//Create Storage Profile
|
||||
StorageProfile storageProfile = StorageProfile.builder()
|
||||
.imageReference(imageReference)
|
||||
StorageProfile.Builder storageProfileBuilder = StorageProfile.builder()
|
||||
.osDisk(osDisk)
|
||||
.dataDisks(dataDisks)
|
||||
.build();
|
||||
.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(
|
||||
|
@ -370,19 +437,54 @@ public class DeploymentTemplateBuilder {
|
|||
.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(STORAGE_API_VERSION)
|
||||
.apiVersion("2015-06-15")
|
||||
.dependsOn(Arrays.asList("[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
|
||||
"[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceCardName'))]"))
|
||||
.tags(ImmutableMap.of("displayName", "VirtualMachine"))
|
||||
.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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,284 +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;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Module;
|
||||
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
|
||||
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.RunScriptOnNodesException;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.providers.ProviderMetadata;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
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;
|
||||
|
||||
import static org.jclouds.compute.predicates.NodePredicates.inGroup;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
@Test(groups = "live", testName = "AzureComputeServiceContextLiveTest")
|
||||
public class AzureComputeServiceContextLiveTest extends BaseComputeServiceContextLiveTest {
|
||||
|
||||
public String azureGroup;
|
||||
protected static final int RAND = new Random().nextInt(999);
|
||||
|
||||
@Override
|
||||
protected Module getSshModule() {
|
||||
return new SshjSshClientModule();
|
||||
}
|
||||
|
||||
@Override protected Properties setupProperties() {
|
||||
azureGroup = "jc" + RAND;
|
||||
|
||||
Properties properties = super.setupProperties();
|
||||
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
|
||||
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
|
||||
|
||||
AzureLiveTestUtils.defaultProperties(properties);
|
||||
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
|
||||
|
||||
properties.put(RESOURCE_GROUP_NAME, azureGroup);
|
||||
return properties;
|
||||
}
|
||||
|
||||
public AzureComputeServiceContextLiveTest() {
|
||||
provider = "azurecompute-arm";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefault() throws RunNodesException {
|
||||
|
||||
final String groupName = this.azureGroup;
|
||||
final TemplateBuilder templateBuilder = view.getComputeService().templateBuilder();
|
||||
templateBuilder.osFamily(OsFamily.UBUNTU);
|
||||
templateBuilder.osVersionMatches("14.04");
|
||||
templateBuilder.hardwareId("Standard_A0");
|
||||
templateBuilder.locationId("westus");
|
||||
|
||||
final Template template = templateBuilder.build();
|
||||
|
||||
try {
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(groupName, 1, template);
|
||||
assertThat(nodes).hasSize(1);
|
||||
} finally {
|
||||
// Do not destroy view.getComputeService().destroyNodesMatching(inGroup(groupName));
|
||||
}
|
||||
}
|
||||
|
||||
private LoginCredentials getLogin() {
|
||||
Credentials credentials = new Credentials("jclouds", "Password1!");
|
||||
LoginCredentials login = LoginCredentials.fromCredentials(credentials);
|
||||
return login;
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testDefault")
|
||||
public void testExec() throws RunScriptOnNodesException {
|
||||
final String groupName = this.azureGroup;
|
||||
String command = "echo hello";
|
||||
|
||||
Map<? extends NodeMetadata, ExecResponse> responses = view.getComputeService().runScriptOnNodesMatching(//
|
||||
inGroup(groupName), // predicate used to select nodes
|
||||
exec(command), // what you actually intend to run
|
||||
overrideLoginCredentials(getLogin()) // use my local user &
|
||||
// ssh key
|
||||
.runAsRoot(false) // don't attempt to run as root (sudo)
|
||||
.wrapInInitScript(false)); // run command directly
|
||||
|
||||
assertTrue(responses.size() > 0);
|
||||
}
|
||||
|
||||
public static Predicate<ComputeMetadata> nameStartsWith(final String prefix) {
|
||||
Preconditions.checkNotNull(prefix, "prefix must be defined");
|
||||
|
||||
return new Predicate<ComputeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(ComputeMetadata computeMetadata) {
|
||||
return computeMetadata.getName().startsWith(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "nameStartsWith(" + prefix + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testExec")
|
||||
public void testStop() throws RunScriptOnNodesException {
|
||||
final String groupName = this.azureGroup;
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().suspendNodesMatching(inGroup(groupName));
|
||||
assertTrue(nodes.size() > 0);
|
||||
|
||||
boolean allStopped = false;
|
||||
while (!allStopped) {
|
||||
nodes = view.getComputeService().listNodesDetailsMatching(nameStartsWith(groupName));
|
||||
for (NodeMetadata node : nodes) {
|
||||
if (node.getStatus() != NodeMetadata.Status.SUSPENDED)
|
||||
{
|
||||
// Not stopped yet
|
||||
allStopped = false;
|
||||
try {
|
||||
Thread.sleep(15 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
allStopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(allStopped);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testStop")
|
||||
public void testStart() throws RunScriptOnNodesException {
|
||||
final String groupName = this.azureGroup;
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().resumeNodesMatching(inGroup(groupName));
|
||||
assertTrue(nodes.size() > 0);
|
||||
|
||||
boolean allStarted = false;
|
||||
while (!allStarted) {
|
||||
nodes = view.getComputeService().listNodesDetailsMatching(nameStartsWith(groupName));
|
||||
for (NodeMetadata node : nodes) {
|
||||
if (node.getStatus() != NodeMetadata.Status.RUNNING)
|
||||
{
|
||||
// Not started yet
|
||||
allStarted = false;
|
||||
try {
|
||||
Thread.sleep(15 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
allStarted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(allStarted);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testStart")
|
||||
public void testRestart() throws RunScriptOnNodesException {
|
||||
final String groupName = this.azureGroup;
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().rebootNodesMatching(inGroup(groupName));
|
||||
assertTrue(nodes.size() > 0);
|
||||
|
||||
boolean allRestarted = false;
|
||||
while (!allRestarted) {
|
||||
nodes = view.getComputeService().listNodesDetailsMatching(nameStartsWith(groupName));
|
||||
for (NodeMetadata node : nodes) {
|
||||
if (node.getStatus() != NodeMetadata.Status.RUNNING)
|
||||
{
|
||||
// Not started yet
|
||||
allRestarted = false;
|
||||
try {
|
||||
Thread.sleep(30 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
allRestarted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(allRestarted);
|
||||
|
||||
view.getComputeService().destroyNodesMatching(inGroup(groupName));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testRestart")
|
||||
public void testLinuxNode() throws RunNodesException {
|
||||
final String groupName = this.azureGroup;
|
||||
final TemplateBuilder templateBuilder = view.getComputeService().templateBuilder();
|
||||
templateBuilder.osFamily(OsFamily.UBUNTU);
|
||||
templateBuilder.osVersionMatches("14.04");
|
||||
templateBuilder.hardwareId("Standard_A0");
|
||||
templateBuilder.locationId("westus");
|
||||
final Template template = templateBuilder.build();
|
||||
|
||||
try {
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(groupName, 1, template);
|
||||
assertThat(nodes).hasSize(1);
|
||||
} finally {
|
||||
view.getComputeService().destroyNodesMatching(inGroup(groupName));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testLinuxNode")
|
||||
public void testWindowsNode() throws RunNodesException {
|
||||
final String groupName = this.azureGroup;
|
||||
final TemplateBuilder templateBuilder = view.getComputeService().templateBuilder();
|
||||
templateBuilder.imageId("global/MicrosoftWindowsServer/WindowsServer/Windows-Server-Technical-Preview");
|
||||
templateBuilder.hardwareId("Standard_A0");
|
||||
templateBuilder.locationId("westus");
|
||||
final Template template = templateBuilder.build();
|
||||
|
||||
try {
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(groupName, 1, template);
|
||||
assertThat(nodes).hasSize(1);
|
||||
} finally {
|
||||
view.getComputeService().destroyNodesMatching(inGroup(groupName));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProviderMetadata createProviderMetadata() {
|
||||
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
|
||||
return pm;
|
||||
}
|
||||
|
||||
protected String setIfTestSystemPropertyPresent(Properties overrides, String key) {
|
||||
if (System.getProperties().containsKey("test." + key)) {
|
||||
String val = System.getProperty("test." + key);
|
||||
overrides.setProperty(key, val);
|
||||
return val;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -16,33 +16,57 @@
|
|||
*/
|
||||
package org.jclouds.azurecompute.arm.compute;
|
||||
|
||||
import org.jclouds.compute.RunScriptOnNodesException;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.OperatingSystem;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
||||
import org.jclouds.compute.predicates.NodePredicates;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.scriptbuilder.statements.java.InstallJDK;
|
||||
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.jclouds.providers.ProviderMetadata;
|
||||
|
||||
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
|
||||
|
||||
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 org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
|
||||
|
||||
import com.google.inject.Module;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
|
||||
import org.jclouds.logging.config.LoggingModule;
|
||||
|
||||
|
||||
/**
|
||||
* Live tests for the {@link org.jclouds.compute.ComputeService} integration.
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeServiceLiveTest")
|
||||
public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||
public String azureGroup;
|
||||
protected int nonBlockDurationSeconds = 30;
|
||||
|
||||
public AzureComputeServiceLiveTest() {
|
||||
provider = "azurecompute-arm";
|
||||
nonBlockDurationSeconds = 300;
|
||||
group = "az-u";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggingModule getLoggingModule() {
|
||||
return new SLF4JLoggingModule();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,18 +80,42 @@ public class AzureComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
return pm;
|
||||
}
|
||||
|
||||
@Override protected Properties setupProperties() {
|
||||
azureGroup = "jc" + System.getProperty("user.name").substring(0, 3);
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties properties = super.setupProperties();
|
||||
long scriptTimeout = TimeUnit.MILLISECONDS.convert(20, TimeUnit.MINUTES);
|
||||
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
|
||||
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
|
||||
properties.put(RESOURCE_GROUP_NAME, azureGroup);
|
||||
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
|
||||
properties.put(RESOURCE_GROUP_NAME, "a4");
|
||||
|
||||
AzureLiveTestUtils.defaultProperties(properties);
|
||||
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Template refreshTemplate() {
|
||||
return this.template = addRunScriptToTemplate(this.buildTemplate(this.client.templateBuilder()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Template addRunScriptToTemplate(Template template) {
|
||||
template.getOptions().runScript(Statements.newStatementList(new Statement[]{AdminAccess.standard(), Statements.exec("sleep 50"), InstallJDK.fromOpenJDK()}));
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test( enabled = false)
|
||||
protected void weCanCancelTasks(NodeMetadata node) throws InterruptedException, ExecutionException {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(String group, OperatingSystem os, LoginCredentials creds) throws RunScriptOnNodesException {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.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 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;
|
||||
|
||||
/**
|
||||
* Live tests for the {@link org.jclouds.compute.extensions.ImageExtension} integration.
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "AzureComputeImageExtensionLiveTest")
|
||||
public class AzureComputeImageExtensionLiveTest extends BaseImageExtensionLiveTest {
|
||||
|
||||
public AzureComputeImageExtensionLiveTest() {
|
||||
provider = "azurecompute-arm";
|
||||
}
|
||||
|
||||
public static String NAME_PREFIX = "%s";
|
||||
|
||||
@Override
|
||||
protected Module getSshModule() {
|
||||
return new SshjSshClientModule();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties properties = super.setupProperties();
|
||||
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
|
||||
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
|
||||
properties.put(RESOURCE_GROUP_NAME, "a5");
|
||||
|
||||
properties.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000);
|
||||
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);
|
||||
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
|
||||
|
||||
return properties;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProviderMetadata createProviderMetadata() {
|
||||
AzureComputeProviderMetadata pm = AzureComputeProviderMetadata.builder().build();
|
||||
return pm;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ package org.jclouds.azurecompute.arm.features;
|
|||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions;
|
||||
import org.jclouds.azurecompute.arm.domain.Deployment;
|
||||
import org.jclouds.azurecompute.arm.domain.Deployment.ProvisioningState;
|
||||
import org.jclouds.azurecompute.arm.domain.DeploymentBody;
|
||||
|
@ -141,7 +142,7 @@ public class DeploymentApiLiveTest extends BaseAzureComputeApiLiveTest {
|
|||
public void testCreate() {
|
||||
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 TemplateOptions();
|
||||
TemplateOptions options = new AzureTemplateOptions();
|
||||
options.authorizePublicKey(rsakey);
|
||||
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
|
||||
DeploymentBody deploymentTemplateBody = templateBuilder.getDeploymentTemplate();
|
||||
|
|
|
@ -18,18 +18,17 @@ package org.jclouds.azurecompute.arm.features;
|
|||
|
||||
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
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.OSProfile;
|
||||
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.domain.VirtualNetwork.VirtualNetworkProperties;
|
||||
import org.jclouds.azurecompute.arm.util.DeploymentTemplateBuilder;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.HardwareBuilder;
|
||||
|
@ -56,6 +55,8 @@ import static org.testng.Assert.fail;
|
|||
public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
|
||||
|
||||
final String group = "jcgroup";
|
||||
final String vnetName = group + "virtualnetwork";
|
||||
final String subnetId = "";
|
||||
|
||||
@Test
|
||||
public void testResourceGroup() {
|
||||
|
@ -71,22 +72,6 @@ public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
|
|||
assertTrue(variables.containsKey(parseVariableName(resource.name())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVirtualNetwork() {
|
||||
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/virtualNetworks");
|
||||
|
||||
VirtualNetworkProperties properties = (VirtualNetworkProperties) resource.properties();
|
||||
assertTrue(properties.addressSpace().addressPrefixes().size() > 0);
|
||||
assertTrue(properties.subnets().size() > 0);
|
||||
|
||||
assertTrue(variables.containsKey(parseVariableName(resource.name())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPublicIpAddress() {
|
||||
DeploymentTemplateBuilder builder = getMockDeploymentTemplateBuilderWithEmptyOptions();
|
||||
|
@ -147,42 +132,49 @@ public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testVirtualMachineWithSSH() {
|
||||
void testCustomOptions(){
|
||||
final String dnsLabelPrefix = "mydnslabel";
|
||||
final String customData = "echo customData";
|
||||
final String customData64 = "ZWNobyBjdXN0b21EYXRh";
|
||||
final String keyvaultString = "/url/to/vault/:publickeysecret";
|
||||
|
||||
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()
|
||||
.customData(customData)
|
||||
.DNSLabelPrefix(dnsLabelPrefix)
|
||||
.keyVaultIdAndSecret(keyvaultString);
|
||||
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.authorizePublicKey(rsakey);
|
||||
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);
|
||||
Template template = builder.getTemplate();
|
||||
|
||||
DeploymentBody deploymentBody = builder.getDeploymentTemplate();
|
||||
|
||||
List<ResourceDefinition> resources = deploymentBody.template().resources();
|
||||
Map<String, String> variables = deploymentBody.template().variables();
|
||||
ResourceDefinition publicIpResource = getResourceByType(resources, "Microsoft.Network/publicIPAddresses");
|
||||
assertNotNull(publicIpResource);
|
||||
|
||||
ResourceDefinition resource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
|
||||
assertNotNull(resource);
|
||||
PublicIPAddressProperties ipProperties = (PublicIPAddressProperties) publicIpResource.properties();
|
||||
assertEquals(ipProperties.dnsSettings().domainNameLabel(), dnsLabelPrefix);
|
||||
|
||||
VirtualMachineProperties properties = (VirtualMachineProperties) resource.properties();
|
||||
assertEquals(properties.hardwareProfile().vmSize(), template.getHardware().getId());
|
||||
ResourceDefinition vmResource = getResourceByType(resources, "Microsoft.Compute/virtualMachines");
|
||||
assertNotNull(vmResource);
|
||||
|
||||
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");
|
||||
VirtualMachineProperties virtualMachineProperties = (VirtualMachineProperties) vmResource.properties();
|
||||
assertEquals(virtualMachineProperties.osProfile().customData(), customData64);
|
||||
|
||||
// Check that ssh key is in place
|
||||
OSProfile.LinuxConfiguration osConfig = properties.osProfile().linuxConfiguration();
|
||||
assertEquals(osConfig.disablePasswordAuthentication(), "true");
|
||||
assertTrue(osConfig.ssh().publicKeys().size() > 0);
|
||||
assertEquals(osConfig.ssh().publicKeys().get(0).keyData(), rsakey);
|
||||
|
||||
assertTrue(variables.containsKey(parseVariableName(resource.name())));
|
||||
//populated when keyvault is used to get public key.
|
||||
assertNotNull(virtualMachineProperties.osProfile().linuxConfiguration().ssh().publicKeys());
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -193,13 +185,19 @@ public class DeploymentTemplateBuilderTest extends BaseAzureComputeApiMockTest {
|
|||
}
|
||||
|
||||
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithEmptyOptions() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
options.virtualNetworkName(vnetName);
|
||||
options.subnetId(subnetId);
|
||||
|
||||
Template template = getMockTemplate(options);
|
||||
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, "mydeployment", template);
|
||||
return templateBuilder;
|
||||
}
|
||||
|
||||
private DeploymentTemplateBuilder getMockDeploymentTemplateBuilderWithOptions(TemplateOptions options) {
|
||||
((AzureTemplateOptions)options).virtualNetworkName(vnetName);
|
||||
((AzureTemplateOptions)options).subnetId(subnetId);
|
||||
|
||||
Template template = getMockTemplate(options);
|
||||
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(group, "mydeployment", template);
|
||||
return templateBuilder;
|
||||
|
|
|
@ -18,12 +18,15 @@ package org.jclouds.azurecompute.arm.features;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
|
||||
import org.jclouds.azurecompute.arm.functions.ParseJobStatus.JobStatus;
|
||||
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiMockTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
@Test(groups = "unit", testName = "JobApiMockTest", singleThreaded = true)
|
||||
public class JobApiMockTest extends BaseAzureComputeApiMockTest {
|
||||
|
@ -70,4 +73,24 @@ public class JobApiMockTest extends BaseAzureComputeApiMockTest {
|
|||
assertSent(server, "GET", requestUrl);
|
||||
}
|
||||
|
||||
public void testCaptureJobStatus() throws IOException, InterruptedException {
|
||||
server.enqueue(jsonResponse("/resourceDefinition.json").setResponseCode(200));
|
||||
|
||||
List<ResourceDefinition> resourceDefinitionsList = api.getJobApi().captureStatus(URI.create(requestUrl));
|
||||
|
||||
assertTrue(resourceDefinitionsList.size() > 0);
|
||||
|
||||
assertSent(server, "GET", requestUrl);
|
||||
}
|
||||
|
||||
public void testCaptureJobStatusFailed() throws InterruptedException {
|
||||
server.enqueue(response404());
|
||||
|
||||
List<ResourceDefinition> resourceDefinitionsList = api.getJobApi().captureStatus(URI.create(requestUrl));
|
||||
|
||||
assertEquals(resourceDefinitionsList.size(), 0);
|
||||
|
||||
assertSent(server, "GET", requestUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -107,7 +107,8 @@ public class NetworkInterfaceCardApiMockTest extends BaseAzureComputeApiMockTest
|
|||
NetworkInterfaceCardProperties.create(null, null, null,
|
||||
Arrays.asList(IpConfiguration.create("myipconfig", null, null, null,
|
||||
IpConfigurationProperties.create(null, null, "Dynamic", IdReference.create(SubnetID), null))
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
final Map<String, String> tags = ImmutableMap.of("mycustomtag", "foobar");
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
package org.jclouds.azurecompute.arm.features;
|
||||
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
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;
|
||||
|
@ -31,6 +33,7 @@ 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;
|
||||
|
@ -47,12 +50,50 @@ public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiv
|
|||
private int pollingInterval = 3; // how frequently to poll for create status
|
||||
private String resourceGroup;
|
||||
private String deploymentName;
|
||||
private String vnetName;
|
||||
private String subnetId;
|
||||
|
||||
@BeforeClass
|
||||
@Override
|
||||
public void setup() {
|
||||
super.setup();
|
||||
resourceGroup = getResourceGroupName();
|
||||
|
||||
//Subnets belong to a virtual network so that needs to be created first
|
||||
VirtualNetwork vn = getOrCreateVirtualNetwork(VIRTUAL_NETWORK_NAME);
|
||||
assertNotNull(vn);
|
||||
vnetName = vn.name();
|
||||
|
||||
//Subnet needs to be up & running before NIC can be created
|
||||
Subnet subnet = getOrCreateSubnet(DEFAULT_SUBNET_NAME, VIRTUAL_NETWORK_NAME);
|
||||
assertNotNull(subnet);
|
||||
assertNotNull(subnet.id());
|
||||
subnetId = subnet.id();
|
||||
}
|
||||
|
||||
@Test(groups = "live")
|
||||
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(groups = "live")
|
||||
|
@ -74,6 +115,34 @@ public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiv
|
|||
assertNotNull(deployment);
|
||||
}
|
||||
|
||||
@Test(groups = "live")
|
||||
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(groups = "live")
|
||||
public void testValidateDeploymentTemplateLinuxNodeWithSSH() {
|
||||
Long now = System.currentTimeMillis();
|
||||
|
@ -81,7 +150,10 @@ public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiv
|
|||
|
||||
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 TemplateOptions();
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
options.virtualNetworkName(vnetName);
|
||||
options.subnetId(subnetId);
|
||||
|
||||
options.authorizePublicKey(rsakey);
|
||||
DeploymentTemplateBuilder templateBuilder = getDeploymentTemplateBuilderWithOptions(options);
|
||||
|
||||
|
@ -103,8 +175,12 @@ public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiv
|
|||
|
||||
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 TemplateOptions();
|
||||
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();
|
||||
|
@ -144,7 +220,7 @@ public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiv
|
|||
|
||||
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("northeurope").description("North Europe").parent(provider).build();
|
||||
Location region = (new LocationBuilder()).scope(LocationScope.REGION).id(LOCATION).description(LOCATIONDESCRIPTION).parent(provider).build();
|
||||
|
||||
OperatingSystem os = OperatingSystem.builder()
|
||||
.family(OsFamily.UBUNTU)
|
||||
|
@ -168,7 +244,10 @@ public class TemplateToDeploymentTemplateLiveTest extends BaseAzureComputeApiLiv
|
|||
}
|
||||
|
||||
private DeploymentTemplateBuilder getDeploymentTemplateBuilderWithEmptyOptions() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
AzureTemplateOptions options = new AzureTemplateOptions();
|
||||
options.virtualNetworkName(vnetName);
|
||||
options.subnetId(subnetId);
|
||||
|
||||
Template template = getTemplate(options);
|
||||
DeploymentTemplateBuilder templateBuilder = api.deploymentTemplateFactory().create(resourceGroup, deploymentName, template);
|
||||
return templateBuilder;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package org.jclouds.azurecompute.arm.features;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.gson.internal.LinkedTreeMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.jclouds.azurecompute.arm.domain.DataDisk;
|
||||
import org.jclouds.azurecompute.arm.domain.DiagnosticsProfile;
|
||||
import org.jclouds.azurecompute.arm.domain.HardwareProfile;
|
||||
|
@ -33,16 +35,28 @@ import org.jclouds.azurecompute.arm.domain.VirtualMachine;
|
|||
import org.jclouds.azurecompute.arm.domain.VirtualMachineInstance;
|
||||
import org.jclouds.azurecompute.arm.domain.VirtualMachineProperties;
|
||||
import org.jclouds.azurecompute.arm.functions.ParseJobStatus;
|
||||
import org.jclouds.azurecompute.arm.internal.AzureLiveTestUtils;
|
||||
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
|
||||
import org.jclouds.util.Predicates2;
|
||||
import org.jclouds.azurecompute.arm.domain.ResourceDefinition;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
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_SCRIPT_COMPLETE;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
|
@ -60,6 +74,23 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
|
|||
nicName = nic.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties properties = super.setupProperties();
|
||||
long scriptTimeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES);
|
||||
properties.setProperty(TIMEOUT_SCRIPT_COMPLETE, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_RUNNING, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_PORT_OPEN, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_TERMINATED, scriptTimeout + "");
|
||||
properties.setProperty(TIMEOUT_NODE_SUSPENDED, scriptTimeout + "");
|
||||
properties.put(RESOURCE_GROUP_NAME, getResourceGroupName());
|
||||
|
||||
AzureLiveTestUtils.defaultProperties(properties);
|
||||
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
if (vmName == null) {
|
||||
vmName = String.format("%3.24s",
|
||||
|
@ -70,7 +101,6 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
|
|||
|
||||
@Test
|
||||
public void testCreate() {
|
||||
|
||||
StorageAccountApi storageApi = api.getStorageAccountApi(getResourceGroupName());
|
||||
StorageService storageAccount = storageApi.get(getStorageServiceName());
|
||||
String blob = storageAccount.storageServiceProperties().primaryEndpoints().get("blob");
|
||||
|
@ -109,22 +139,7 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
|
|||
public void testStop() {
|
||||
api().stop(getName());
|
||||
//Poll until resource is ready to be used
|
||||
boolean jobDone = Predicates2.retry(new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String name) {
|
||||
String status = "";
|
||||
List<VirtualMachineInstance.VirtualMachineStatus> statuses = api().getInstanceDetails(name).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");
|
||||
}
|
||||
}, 60 * 4 * 1000).apply(getName());
|
||||
assertTrue(jobDone, "stop operation did not complete in the configured timeout");
|
||||
|
||||
nodeSuspendedPredicate.apply(getName());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testGet")
|
||||
|
@ -194,11 +209,53 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
|
|||
@Test(dependsOnMethods = "testCreate")
|
||||
public void testList() {
|
||||
List<VirtualMachine> list = api().list();
|
||||
VirtualMachine vm = api().get(getName());
|
||||
assertTrue(list.contains(vm));
|
||||
final VirtualMachine vm = api().get(getName());
|
||||
|
||||
boolean vmPresent = Iterables.any(list, new Predicate<VirtualMachine>() {
|
||||
public boolean apply(VirtualMachine input) {
|
||||
return input.name().equals(vm.name());
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(vmPresent);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = {"testRestart", "testList", "testGet"}, alwaysRun = true)
|
||||
@Test(dependsOnMethods = "testRestart")
|
||||
public void testGeneralize() throws IllegalStateException {
|
||||
api().stop(getName());
|
||||
//Poll until resource is ready to be used
|
||||
|
||||
if (nodeSuspendedPredicate.apply(getName())) {
|
||||
api().generalize(getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testGeneralize")
|
||||
public void testCapture() throws IllegalStateException {
|
||||
URI uri = api().capture(getName(), getName(), getName());
|
||||
if (uri != null) {
|
||||
if (imageAvailablePredicate.apply(uri)) {
|
||||
List<ResourceDefinition> definitions = api.getJobApi().captureStatus(uri);
|
||||
if (definitions != null) {
|
||||
for (ResourceDefinition definition : definitions) {
|
||||
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);
|
||||
|
||||
Assert.assertNotNull(osProperties.get("name"));
|
||||
Assert.assertNotNull(datadiskObject.get("name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCapture", alwaysRun = true)
|
||||
public void testDelete() throws Exception {
|
||||
URI uri = api().delete(getName());
|
||||
|
||||
|
@ -227,8 +284,10 @@ public class VirtualMachineApiLiveTest extends BaseAzureComputeApiLiveTest {
|
|||
VHD vhd = VHD.create(blob + "vhds/" + getName() + ".vhd");
|
||||
VHD vhd2 = VHD.create(blob + "vhds/" + getName() + "data.vhd");
|
||||
DataDisk dataDisk = DataDisk.create(getName() + "data", "100", 0, vhd2, "Empty");
|
||||
OSDisk osDisk = OSDisk.create(null, getName(), vhd, "ReadWrite", "FromImage");
|
||||
StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, null);
|
||||
List<DataDisk> dataDisks = new ArrayList<DataDisk>();
|
||||
dataDisks.add(dataDisk);
|
||||
OSDisk osDisk = OSDisk.create(null, getName(), vhd, "ReadWrite", "FromImage", null);
|
||||
StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
|
||||
OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
|
||||
null);
|
||||
OSProfile osProfile = OSProfile.create(getName(), "azureuser", "RFe3&432dg", null, null, windowsConfig);
|
||||
|
|
|
@ -74,7 +74,7 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
|
|||
assertEquals(actual.statuses().get(0).code(), expected.statuses().get(0).code());
|
||||
assertEquals(actual.statuses().get(0).displayStatus(), expected.statuses().get(0).displayStatus());
|
||||
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" +
|
||||
"/virtualMachines/windowsmachine/instanceView?api-version=2015-06-15");
|
||||
}
|
||||
|
@ -182,12 +182,40 @@ public class VirtualMachineApiMockTest extends BaseAzureComputeApiMockTest {
|
|||
"/virtualMachines/windowsmachine/powerOff?api-version=2015-06-15");
|
||||
}
|
||||
|
||||
public void testGeneralize() throws Exception {
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
|
||||
vmAPI.generalize("vm"); // IllegalStateException if failed
|
||||
assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
|
||||
"/virtualMachines/vm/generalize?api-version=2015-06-15");
|
||||
}
|
||||
|
||||
public void testCapture() throws Exception {
|
||||
server.enqueue(response202WithHeader());
|
||||
|
||||
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
|
||||
URI uri = vmAPI.capture("vm", "prefix", "container");
|
||||
assertNotNull(uri);
|
||||
assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
|
||||
"/virtualMachines/vm/capture?api-version=2015-06-15", "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
|
||||
}
|
||||
|
||||
public void testCapture404() throws Exception {
|
||||
server.enqueue(response404());
|
||||
|
||||
final VirtualMachineApi vmAPI = api.getVirtualMachineApi("groupname");
|
||||
URI uri = vmAPI.capture("vm", "prefix", "container");
|
||||
assertNull(uri);
|
||||
assertSent(server, "POST", "/subscriptions/SUBSCRIPTIONID/resourceGroups/groupname/providers/Microsoft.Compute" +
|
||||
"/virtualMachines/vm/capture?api-version=2015-06-15", "{\"vhdPrefix\":\"prefix\",\"destinationContainerName\":\"container\"}");
|
||||
}
|
||||
|
||||
private VirtualMachineProperties getProperties() {
|
||||
HardwareProfile hwProf = HardwareProfile.create("Standard_D1");
|
||||
ImageReference imgRef = ImageReference.create("publisher", "offer", "sku", "ver");
|
||||
VHD vhd = VHD.create("https://groupname2760.blob.core.windows.net/vhds/windowsmachine201624102936.vhd");
|
||||
List<DataDisk> dataDisks = new ArrayList<DataDisk>();
|
||||
OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage");
|
||||
OSDisk osDisk = OSDisk.create("Windows", "windowsmachine", vhd, "ReadWrite", "FromImage", null);
|
||||
StorageProfile storageProfile = StorageProfile.create(imgRef, osDisk, dataDisks);
|
||||
OSProfile.WindowsConfiguration windowsConfig = OSProfile.WindowsConfiguration.create(false, null, null, true,
|
||||
null);
|
||||
|
|
|
@ -18,8 +18,11 @@ package org.jclouds.azurecompute.arm.internal;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
|
@ -28,11 +31,19 @@ import org.jclouds.apis.BaseApiLiveTest;
|
|||
import org.jclouds.azurecompute.arm.AzureComputeApi;
|
||||
import org.jclouds.azurecompute.arm.AzureComputeProviderMetadata;
|
||||
import org.jclouds.providers.ProviderMetadata;
|
||||
import com.google.inject.name.Names;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
|
||||
|
||||
public abstract class AbstractAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi> {
|
||||
|
||||
protected static final int RAND = new Random().nextInt(999);
|
||||
protected Predicate<String> nodeSuspendedPredicate;
|
||||
protected Predicate<URI> imageAvailablePredicate;
|
||||
|
||||
public AbstractAzureComputeApiLiveTest() {
|
||||
provider = "azurecompute-arm";
|
||||
|
@ -40,6 +51,10 @@ public abstract class AbstractAzureComputeApiLiveTest extends BaseApiLiveTest<Az
|
|||
|
||||
@Override protected AzureComputeApi create(Properties props, Iterable<Module> modules) {
|
||||
Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
|
||||
nodeSuspendedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>() {
|
||||
}, Names.named(TIMEOUT_NODE_SUSPENDED)));
|
||||
imageAvailablePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<URI>>() {
|
||||
}, Names.named(TIMEOUT_IMAGE_AVAILABLE)));
|
||||
return injector.getInstance(AzureComputeApi.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.util.logging.Logger;
|
|||
|
||||
public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest {
|
||||
public static final String LOCATION = "westeurope";
|
||||
public static final String LOCATIONDESCRIPTION = "West Europe";
|
||||
|
||||
public static final String DEFAULT_SUBNET_ADDRESS_SPACE = "10.2.0.0/23";
|
||||
|
||||
|
@ -61,6 +62,8 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
|
|||
|
||||
private String resourceGroupName = null;
|
||||
|
||||
private String virtualNetworkName = null;
|
||||
|
||||
protected StorageService storageService;
|
||||
|
||||
private String storageServiceName = null;
|
||||
|
@ -101,12 +104,12 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
|
|||
if (resourceGroupName == null) {
|
||||
resourceGroupName = String.format("%3.24s",
|
||||
System.getProperty("user.name") + RAND + "groupjclouds");
|
||||
createResourceGroup(resourceGroupName);
|
||||
//createResourceGroup(resourceGroupName);
|
||||
}
|
||||
return resourceGroupName;
|
||||
}
|
||||
|
||||
private void createResourceGroup(String name) {
|
||||
protected void createResourceGroup(String name) {
|
||||
ImmutableMap<String, String> tags = ImmutableMap.<String, String>builder().build();
|
||||
|
||||
final ResourceGroup resourceGroup = api.getResourceGroupApi().create(
|
||||
|
@ -117,10 +120,12 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
|
|||
api.getResourceGroupApi().delete(name);
|
||||
}
|
||||
|
||||
|
||||
@BeforeClass
|
||||
@Override
|
||||
public void setup() {
|
||||
super.setup();
|
||||
createResourceGroup(getResourceGroupName());
|
||||
storageService = getOrCreateStorageService(getStorageServiceName());
|
||||
}
|
||||
|
||||
|
@ -173,6 +178,7 @@ public class BaseAzureComputeApiLiveTest extends AbstractAzureComputeApiLiveTest
|
|||
|
||||
|
||||
vn = vnApi.createOrUpdate(VIRTUAL_NETWORK_NAME, LOCATION, virtualNetworkProperties);
|
||||
this.virtualNetworkName = virtualNetworkName;
|
||||
return vn;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.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.
|
||||
|
||||
-->
|
||||
<configuration scan="false">
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds-wire.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds-compute.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds-ssh.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<level value="warn" />
|
||||
</root>
|
||||
|
||||
<logger name="org.jclouds">
|
||||
<level value="TRACE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.wire">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="WIREFILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.headers">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="WIREFILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.compute">
|
||||
<level value="TRACE" />
|
||||
<appender-ref ref="COMPUTEFILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.ssh">
|
||||
<level value="TRACE" />
|
||||
<appender-ref ref="SSHFILE" />
|
||||
</logger>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"resources": [
|
||||
{
|
||||
"name": "[parameters('vnName')]",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"location": "westeurope",
|
||||
"apiVersion": "2015-06-15",
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[paramters('vmSize')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"osDisk": {
|
||||
"osType":"Windows",
|
||||
"name":"testmachine-osDisk.539c38a7-642c-43cc-a20b-89b0f3e56afe.vhd"
|
||||
}
|
||||
},
|
||||
"provisioningState": "0.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue