JCLOUDS-664 Azurecompute-arm image capture userdata keyvault

This commit is contained in:
Rita Zhang 2016-05-16 18:55:01 -07:00 committed by Ignasi Barrera
parent cadd60dc22
commit 10d9b38976
41 changed files with 1783 additions and 629 deletions

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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");
}
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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());
}
};
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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";
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -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();
}
}

View File

@ -29,6 +29,7 @@ public abstract class StorageProfile {
/**
* The image reference of the storage profile
*/
@Nullable
public abstract ImageReference imageReference();
/**

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.functions;
import 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);
}
}

View File

@ -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:

View File

@ -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());
}
}

View File

@ -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;
}
}
}

View File

@ -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"));
}
}

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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");

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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"
}
}
]
}