[JCLOUDS-981,JCLOUDS-982] remove Optional from AzureComputeTemplateOptions - fix reuse of existing storage service during deployment - use AutoValue.Builder in DeployParams - make network creation optional - remove AzureComuteAdapterLiveTest b/c not meaningful - fix DiskLiveTest - fix OSImageApiLiveTest - fix VMImageApiLiveTest - fix VirtualMachineApiLiveTest - fix NetworkSecurityGroupApiLiveTest - fix AzureComputeServiceContextLiveTest.testListSizes - simplify AzureComputeServiceContextModule - add AdminUsername to DeploymentParamsToXML for Windows images - fix NPE in DeploymentToNodeMetadata.status - add check role status into deployment - modify deployemtParamsToXml - fix VM deletion - fix DeploymentApiMockTest
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/f9b393de Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/f9b393de Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/f9b393de Branch: refs/heads/master Commit: f9b393de0e66f100a764e502c7f95508fc6e9053 Parents: 1c5df25 Author: Andrea Turli <[email protected]> Authored: Wed Aug 12 12:24:40 2015 +0200 Committer: Andrea Turli <[email protected]> Committed: Wed Jan 20 23:36:03 2016 +0100 ---------------------------------------------------------------------- azurecompute/README.md | 4 +- azurecompute/pom.xml | 2 +- .../AzureComputeProviderMetadata.java | 3 - .../binders/DeploymentParamsToXML.java | 28 +- .../jclouds/azurecompute/binders/RoleToXML.java | 6 +- .../compute/AzureComputeServiceAdapter.java | 219 +++++----- .../AzureComputeServiceContextModule.java | 7 +- .../AzureComputeSecurityGroupExtension.java | 129 +----- .../functions/DeploymentToNodeMetadata.java | 11 +- .../compute/functions/RoleSizeToHardware.java | 31 +- .../options/AzureComputeTemplateOptions.java | 418 +++++++++++++++++++ .../predicates/StorageServicePredicates.java | 80 ++++ ...ServiceAndVirtualNetworkThenCreateNodes.java | 194 ++------- .../AzureAdaptingComputeServiceStrategies.java | 70 ---- .../jclouds/azurecompute/domain/Deployment.java | 1 + .../azurecompute/domain/DeploymentParams.java | 165 ++------ .../features/VirtualMachineApi.java | 13 + .../options/AzureComputeTemplateOptions.java | 344 --------------- .../util/ConflictManagementPredicate.java | 7 +- .../AzureComputeProviderMetadataLive.java | 86 ---- .../binders/DeploymentParamsToXMLTest.java | 64 +++ .../AzureComputeServiceAdapterLiveTest.java | 177 -------- .../AzureComputeServiceContextLiveTest.java | 139 +++--- .../compute/AzureComputeServiceLiveTest.java | 30 +- .../features/DeploymentApiLiveTest.java | 22 +- .../features/DeploymentApiMockTest.java | 10 +- .../azurecompute/features/DiskApiLiveTest.java | 3 +- .../NetworkSecurityGroupApiLiveTest.java | 15 +- .../features/OSImageApiLiveTest.java | 17 - .../features/VMImageApiLiveTest.java | 33 +- .../features/VirtualMachineApiLiveTest.java | 41 +- .../features/VirtualNetworkApiLiveTest.java | 35 +- .../AbstractAzureComputeApiLiveTest.java | 26 +- .../internal/BaseAzureComputeApiLiveTest.java | 5 +- .../test/resources/deploymentparams-windows.xml | 2 +- .../src/test/resources/logback-test.xml | 34 ++ azurecompute/src/test/resources/logback.xml | 34 -- 37 files changed, 1035 insertions(+), 1470 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/README.md ---------------------------------------------------------------------- diff --git a/azurecompute/README.md b/azurecompute/README.md index 5deca6f..7d251d7 100644 --- a/azurecompute/README.md +++ b/azurecompute/README.md @@ -1,8 +1,8 @@ -## Annotation processing ## +## Annotation processing In order for value object and service loader auto-generation, you will need to enable annotation processing in your IDE. If you notice any inconsistencies in your IDE after you enable annotation processing, try rerunning "Make Project". -## Setting up test credentials ## +## Setting up test credentials Azure requests are signed by via SSL certificate. You need to upload one into your account in order to run tests. http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/pom.xml ---------------------------------------------------------------------- diff --git a/azurecompute/pom.xml b/azurecompute/pom.xml index 9b51a92..e950f16 100644 --- a/azurecompute/pom.xml +++ b/azurecompute/pom.xml @@ -35,7 +35,7 @@ <properties> <test.jclouds.azurecompute.subscription-id>FIXME_subscription-id</test.jclouds.azurecompute.subscription-id> <!-- note that there's no prefix of "test." in the url. This is to ensure that jclouds inteprets the value, as opposed to maven --> - <test.azurecompute.endpoint>https://management.core.windows.net/${jclouds.azurecompute.subscription-id}</test.azurecompute.endpoint> + <test.azurecompute.endpoint>https://management.core.windows.net/${test.jclouds.azurecompute.subscription-id}</test.azurecompute.endpoint> <test.azurecompute.api-version>2014-10-01</test.azurecompute.api-version> <test.azurecompute.build-version /> <test.azurecompute.identity>/path/to/cert.p12</test.azurecompute.identity> http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java index 843e264..731b52f 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java @@ -21,8 +21,6 @@ import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_P import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT; import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_FORMAT; import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_REGEXP; -import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; - import java.net.URI; import java.util.Properties; @@ -50,7 +48,6 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata { public static Properties defaultProperties() { final Properties properties = AzureManagementApiMetadata.defaultProperties(); - properties.setProperty(TEMPLATE, "osFamily=UBUNTU,loginUser=jclouds"); properties.setProperty(OPERATION_TIMEOUT, "60000"); properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "5"); properties.setProperty(OPERATION_POLL_MAX_PERIOD, "15"); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java index 515a5d2..c220551 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/DeploymentParamsToXML.java @@ -29,7 +29,6 @@ import com.jamesmurty.utils.XMLBuilder; public final class DeploymentParamsToXML implements Binder { @Override - @SuppressWarnings("unchecked") public <R extends HttpRequest> R bindToRequest(R request, Object input) { DeploymentParams params = DeploymentParams.class.cast(input); @@ -60,6 +59,12 @@ public final class DeploymentParamsToXML implements Binder { .e("JoinDomain").t(params.name()).up() .up() // Domain Join .e("StoredCertificateSettings").up() + .e("WinRM") + .e("Listeners") + .e("Listener") + .e("Protocol").t("http").up().up().up().up() + .e("AdminUsername").t(params.username()).up() + .e("AdminPassword").t(params.username()).up() .up(); // Windows ConfigurationSet } else if (params.os() == OSImage.Type.LINUX) { XMLBuilder configBuilder = builder.e("ConfigurationSet"); // Linux @@ -90,12 +95,13 @@ public final class DeploymentParamsToXML implements Binder { } inputEndpoints.up(); - //configBuilder.e("SubnetNames").up().up(); XMLBuilder subnetNames = configBuilder.e("SubnetNames"); - for (String subnetName : params.subnetNames()) { - subnetNames.e("SubnetName").t(subnetName).up() - .up(); //subnetName + if (!params.subnetNames().isEmpty()) { + for (String subnetName : params.subnetNames()) { + subnetNames.e("SubnetName").t(subnetName).up() + .up(); //subnetName + } } builder.up() //ConfigurationSets @@ -105,21 +111,21 @@ public final class DeploymentParamsToXML implements Binder { .e("HostCaching").t("ReadWrite").up() .e("MediaLink").t(params.mediaLink().toASCIIString()).up() // TODO - /// If you are using a VM image, it must be specified as VMImageName for the role, + /// If you are using a VM image, it must be specified as VMImageName for the role, // not as SourceImageNamefor OSVirtualHardDisk.</Message></Error>] .e("SourceImageName").t(params.sourceImageName()).up() .e("OS").t(params.os() == LINUX ? "Linux" : "Windows").up() .up() //OSVirtualHardDisk .e("RoleSize").t(params.size().getText()).up() .up() //Role - .up() //RoleList - .e("VirtualNetworkName").t(params.virtualNetworkName()).up(); - + .up(); //RoleList + if (params.virtualNetworkName() != null) { + builder.up().up().up().e("VirtualNetworkName").t(params.virtualNetworkName()).up(); + } if (params.reservedIPName() != null) { builder.up().up().up().e("ReservedIPName").t(params.reservedIPName()).up(); } - - // TODO: Undeprecate this method as forcing users to wrap a String in guava's ByteSource is not great. + return (R) request.toBuilder().payload(builder.asString()).build(); } catch (Exception e) { throw propagate(e); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java index 25c9b11..e5f1b26 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/binders/RoleToXML.java @@ -52,8 +52,10 @@ public class RoleToXML implements Binder { .up(); //InputEndpoint } XMLBuilder subnetNames = configBuilder.e("SubnetNames"); - for (Role.ConfigurationSet.SubnetName subnetName : configurationSet.subnetNames()) { - subnetNames.e("SubnetName").t(subnetName.name()).up(); + if (!configurationSet.subnetNames().isEmpty()) { + for (Role.ConfigurationSet.SubnetName subnetName : configurationSet.subnetNames()) { + subnetNames.e("SubnetName").t(subnetName.name()).up(); + } } if (configurationSet.networkSecurityGroup() != null && !configurationSet.networkSecurityGroup().isEmpty()) { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java index 7560e68..ec605ea 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java @@ -16,11 +16,11 @@ */ package org.jclouds.azurecompute.compute; +import static com.google.common.base.Objects.firstNonNull; import static com.google.common.base.Predicates.notNull; import static java.lang.String.format; import static java.util.concurrent.TimeUnit.SECONDS; import static org.jclouds.util.Predicates2.retry; - import java.net.URI; import java.util.List; import java.util.Set; @@ -32,18 +32,19 @@ import javax.inject.Singleton; import org.jclouds.azurecompute.AzureComputeApi; import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; +import org.jclouds.azurecompute.compute.functions.OSImageToImage; +import org.jclouds.azurecompute.compute.options.AzureComputeTemplateOptions; import org.jclouds.azurecompute.config.AzureComputeProperties; import org.jclouds.azurecompute.domain.CloudService; import org.jclouds.azurecompute.domain.Deployment; +import org.jclouds.azurecompute.domain.Deployment.RoleInstance; import org.jclouds.azurecompute.domain.DeploymentParams; import org.jclouds.azurecompute.domain.DeploymentParams.ExternalEndpoint; import org.jclouds.azurecompute.domain.Location; import org.jclouds.azurecompute.domain.OSImage; -import org.jclouds.azurecompute.domain.RoleSize; -import org.jclouds.azurecompute.domain.Deployment.RoleInstance; import org.jclouds.azurecompute.domain.Role; -import org.jclouds.azurecompute.compute.functions.OSImageToImage; -import org.jclouds.azurecompute.options.AzureComputeTemplateOptions; +import org.jclouds.azurecompute.domain.RoleSize; +import org.jclouds.azurecompute.util.ConflictManagementPredicate; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; @@ -59,7 +60,6 @@ import com.google.common.collect.FluentIterable; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.jclouds.azurecompute.util.ConflictManagementPredicate; /** * Defines the connection between the {@link AzureComputeApi} implementation and the jclouds @@ -71,6 +71,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym private static final String DEFAULT_LOGIN_USER = "jclouds"; private static final String DEFAULT_LOGIN_PASSWORD = "Azur3Compute!"; + public static final String POST_SHUTDOWN_ACTION = "StoppedDeallocated"; @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) @@ -98,35 +99,30 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym // azure-specific options final AzureComputeTemplateOptions templateOptions = template.getOptions().as(AzureComputeTemplateOptions.class); - final String loginUser = templateOptions.getLoginUser() == null - ? DEFAULT_LOGIN_USER : templateOptions.getLoginUser(); - final String loginPassword = templateOptions.getLoginPassword() == null - ? DEFAULT_LOGIN_PASSWORD : templateOptions.getLoginPassword(); + final String loginUser = firstNonNull(templateOptions.getLoginUser(), DEFAULT_LOGIN_USER); + final String loginPassword = firstNonNull(templateOptions.getLoginPassword(), DEFAULT_LOGIN_PASSWORD); final String location = template.getLocation().getId(); final int[] inboundPorts = template.getOptions().getInboundPorts(); - final String storageAccountName = templateOptions.getStorageAccountName().get(); - final String virtualNetworkName = templateOptions.getVirtualNetworkName().get(); - final String reservedIPAddress = templateOptions.getReservedIPName().orNull(); - final String subnetName = templateOptions.getSubnetName().get(); + final String storageAccountName = templateOptions.getStorageAccountName(); - logger.debug("Creating a cloud service with name '%s', label '%s' in location '%s'", name, name, location); - final String createCloudServiceRequestId - = api.getCloudServiceApi().createWithLabelInLocation(name, name, location); + String message = String.format("Creating a cloud service with name '%s', label '%s' in location '%s'", name, name, location); + logger.debug(message); + final String createCloudServiceRequestId = api.getCloudServiceApi().createWithLabelInLocation(name, name, location); if (!operationSucceededPredicate.apply(createCloudServiceRequestId)) { - final String message = generateIllegalStateExceptionMessage( - createCloudServiceRequestId, azureComputeConstants.operationTimeout()); - logger.warn(message); - throw new IllegalStateException(message); + final String exceptionMessage = generateIllegalStateExceptionMessage(message, createCloudServiceRequestId, azureComputeConstants.operationTimeout()); + logger.warn(exceptionMessage); + throw new IllegalStateException(exceptionMessage); } logger.info("Cloud Service (%s) created with operation id: %s", name, createCloudServiceRequestId); - final OSImage.Type os = template.getImage().getOperatingSystem().getFamily() == OsFamily.WINDOWS - ? OSImage.Type.WINDOWS : OSImage.Type.LINUX; + final OSImage.Type os = template.getImage().getOperatingSystem().getFamily() == OsFamily.WINDOWS ? + OSImage.Type.WINDOWS : OSImage.Type.LINUX; final Set<ExternalEndpoint> externalEndpoints = Sets.newHashSet(); for (int inboundPort : inboundPorts) { externalEndpoints.add(ExternalEndpoint.inboundTcpToLocalPort(inboundPort, inboundPort)); } + final DeploymentParams params = DeploymentParams.builder() .name(name) .os(os) @@ -136,12 +132,12 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym .mediaLink(createMediaLink(storageAccountName, name)) .size(RoleSize.Type.fromString(template.getHardware().getName())) .externalEndpoints(externalEndpoints) - .subnetName(subnetName) - .virtualNetworkName(virtualNetworkName) - .reservedIPName(reservedIPAddress) + .virtualNetworkName(templateOptions.getVirtualNetworkName()) + .subnetNames(templateOptions.getSubnetNames()) .build(); - logger.debug("Creating a deployment with params '%s' ...", params); + message = String.format("Creating a deployment with params '%s' ...", params); + logger.debug(message); if (!new ConflictManagementPredicate(api) { @Override @@ -149,13 +145,12 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym return api.getDeploymentApiForService(name).create(params); } }.apply(name)) { - final String message = generateIllegalStateExceptionMessage( - createCloudServiceRequestId, azureComputeConstants.operationTimeout()); - logger.warn(message); + final String illegalStateExceptionMessage = generateIllegalStateExceptionMessage(message, createCloudServiceRequestId, azureComputeConstants.operationTimeout()); + logger.warn(illegalStateExceptionMessage); logger.debug("Deleting cloud service (%s) ...", name); deleteCloudService(name); logger.debug("Cloud service (%s) deleted.", name); - throw new IllegalStateException(message); + throw new IllegalStateException(illegalStateExceptionMessage); } logger.info("Deployment created with name: %s", name); @@ -171,25 +166,23 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym return !deployments.isEmpty(); } }, azureComputeConstants.operationTimeout(), 1, SECONDS).apply(name)) { - final String message = format("Deployment %s was not created within %sms so it will be destroyed.", + final String illegalStateExceptionMessage = format("Deployment %s was not created within %sms so it will be destroyed.", name, azureComputeConstants.operationTimeout()); - logger.warn(message); + logger.warn(illegalStateExceptionMessage); api.getDeploymentApiForService(name).delete(name); api.getCloudServiceApi().delete(name); - throw new IllegalStateException(message); + throw new IllegalStateException(illegalStateExceptionMessage); } final Deployment deployment = deployments.iterator().next(); - return new NodeAndInitialCredentials<Deployment>(deployment, name, - LoginCredentials.builder().user(loginUser).password(loginPassword).build()); - } - public static String generateIllegalStateExceptionMessage(final String operationId, final long timeout) { - final String warnMessage = format("%s has not been completed within %sms.", operationId, timeout); - return format("%s. Please, try by increasing `%s` and try again", - warnMessage, AzureComputeProperties.OPERATION_TIMEOUT); + // check if the role inside the deployment is ready + checkRoleStatusInDeployment(name, deployment); + + return new NodeAndInitialCredentials<Deployment>(deployment, name, + LoginCredentials.builder().user(loginUser).password(loginPassword).authenticateSudo(true).build()); } @Override @@ -299,67 +292,33 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym private void trackRequest(final String requestId) { if (!operationSucceededPredicate.apply(requestId)) { final String message = generateIllegalStateExceptionMessage( - requestId, azureComputeConstants.operationTimeout()); + "tracking request", requestId, azureComputeConstants.operationTimeout()); logger.warn(message); throw new IllegalStateException(message); } } - private List<CloudService> getCloudServicesForDeployment(final String id) { - return FluentIterable.from(api.getCloudServiceApi().list()).filter(new Predicate<CloudService>() { - - @Override - public boolean apply(final CloudService input) { - final Deployment deployment - = input.status() == CloudService.Status.DELETING || input.status() == CloudService.Status.DELETED - ? null - : api.getDeploymentApiForService(input.name()).get(id); - return deployment != null && deployment.status() != Deployment.Status.DELETING; - } - }).toList(); - } - - public Deployment internalDestroyNode(final String id) { - Deployment deployment = null; - - for (CloudService cloudService : getCloudServicesForDeployment(id)) { - final List<Deployment> nodes = Lists.newArrayList(); - retry(new Predicate<String>() { - @Override - public boolean apply(final String input) { - final Deployment deployment = getNode(id); - if (deployment != null) { - nodes.add(deployment); - } - return !nodes.isEmpty(); - } - }, 30 * 60, 1, SECONDS).apply(id); + public Deployment internalDestroyNode(final String nodeId) { - if (!nodes.isEmpty()) { - deployment = nodes.iterator().next(); - } + Deployment deployment = getDeploymentFromNodeId(nodeId); - final String cloudServiceName = cloudService.name(); - logger.debug("Deleting deployment(%s) of cloud service (%s)", id, cloudServiceName); + if (deployment == null) return null; - if (!new ConflictManagementPredicate(api, operationSucceededPredicate) { + final String deploymentName = deployment.name(); + String message = String.format("Deleting deployment(%s) of cloud service (%s)", nodeId, deploymentName); + logger.debug(message); - @Override - protected String operation() { - return api.getDeploymentApiForService(cloudServiceName).delete(id); + if (deployment != null) { + for (Role role : deployment.roleList()) { + trackRequest(api.getVirtualMachineApiForDeploymentInService(deploymentName, role.roleName()).shutdown(nodeId, POST_SHUTDOWN_ACTION)); } - }.apply(id)) { - final String message = generateIllegalStateExceptionMessage( - "Delete deployment", azureComputeConstants.operationTimeout()); - logger.warn(message); - throw new IllegalStateException(message); - } - logger.debug("Deleting cloud service (%s) ...", cloudServiceName); - trackRequest(api.getCloudServiceApi().delete(cloudServiceName)); - logger.debug("Cloud service (%s) deleted.", cloudServiceName); + deleteDeployment(deploymentName, nodeId); + + logger.debug("Deleting cloud service (%s) ...", deploymentName); + trackRequest(api.getCloudServiceApi().delete(deploymentName)); + logger.debug("Cloud service (%s) deleted.", deploymentName); - if (deployment != null) { for (Role role : deployment.roleList()) { final Role.OSVirtualHardDisk disk = role.osVirtualHardDisk(); if (disk != null) { @@ -369,22 +328,41 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym protected String operation() { return api.getDiskApi().delete(disk.diskName()); } - }.apply(id)) { - final String message = generateIllegalStateExceptionMessage( + }.apply(nodeId)) { + final String illegalStateExceptionMessage = generateIllegalStateExceptionMessage("Delete disk " + disk.diskName(), "Delete disk", azureComputeConstants.operationTimeout()); - logger.warn(message); + logger.warn(illegalStateExceptionMessage); } } } } - } - return deployment; } + public Deployment getDeploymentFromNodeId(final String nodeId) { + final List<Deployment> nodes = Lists.newArrayList(); + retry(new Predicate<String>() { + @Override + public boolean apply(final String input) { + final Deployment deployment = getNode(nodeId); + if (deployment != null) { + nodes.add(deployment); + } + return !nodes.isEmpty(); + } + }, 30 * 60, 1, SECONDS).apply(nodeId); + + return Iterables.getFirst(nodes, null); + } + @Override public void destroyNode(final String id) { - internalDestroyNode(id); + logger.debug("Destroying %s ...", id); + if (internalDestroyNode(id) != null) { + logger.debug("Destroyed %s!", id); + } else { + logger.warn("Can't destroy %s!", id); + } } @Override @@ -412,7 +390,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym final CloudService cloudService = api.getCloudServiceApi().get(id); if (cloudService != null) { logger.debug("Suspending %s ...", id); - trackRequest(api.getVirtualMachineApiForDeploymentInService(id, cloudService.name()).shutdown(id)); + trackRequest(api.getVirtualMachineApiForDeploymentInService(id, cloudService.name()).shutdown(id, POST_SHUTDOWN_ACTION)); logger.debug("Suspended %s", id); } } @@ -455,7 +433,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym } }.apply(name)) { - final String deleteMessage = generateIllegalStateExceptionMessage( + final String deleteMessage = generateIllegalStateExceptionMessage("Delete cloud service " + name, "CloudService delete", azureComputeConstants.operationTimeout()); logger.warn(deleteMessage); throw new IllegalStateException(deleteMessage); @@ -471,10 +449,53 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym } }.apply(id)) { - final String deleteMessage = generateIllegalStateExceptionMessage( + final String deleteMessage = generateIllegalStateExceptionMessage("Delete deployment " + cloudServiceName, "Deployment delete", azureComputeConstants.operationTimeout()); logger.warn(deleteMessage); throw new IllegalStateException(deleteMessage); } } + + + private void checkRoleStatusInDeployment(final String name, Deployment deployment) { + if (!retry(new Predicate<Deployment>() { + + @Override + public boolean apply(Deployment deployment) { + deployment = api.getDeploymentApiForService(deployment.name()).get(name); + if (deployment.roleInstanceList() == null || deployment.roleInstanceList().isEmpty()) return false; + return Iterables.all(deployment.roleInstanceList(), new Predicate<RoleInstance>() { + @Override + public boolean apply(RoleInstance input) { + if (input.instanceStatus() == Deployment.InstanceStatus.PROVISIONING_FAILED) { + final String message = format("Deployment %s is in provisioning failed status, so it will be destroyed.", name); + logger.warn(message); + + api.getDeploymentApiForService(name).delete(name); + api.getCloudServiceApi().delete(name); + + throw new IllegalStateException(message); + } + return input.instanceStatus() == Deployment.InstanceStatus.READY_ROLE; + } + }); + } + }, azureComputeConstants.operationTimeout(), 1, SECONDS).apply(deployment)) { + final String message = format("Role %s has not reached the READY_ROLE within %sms so it will be destroyed.", + deployment.name(), azureComputeConstants.operationTimeout()); + logger.warn(message); + + api.getDeploymentApiForService(name).delete(name); + api.getCloudServiceApi().delete(name); + + throw new IllegalStateException(message); + } + } + + public static String generateIllegalStateExceptionMessage(String prefix, final String operationId, final long timeout) { + final String warnMessage = format("%s - %s has not been completed within %sms.", prefix, operationId, timeout); + return format("%s. Please, try by increasing `%s` and try again", + warnMessage, AzureComputeProperties.OPERATION_TIMEOUT); + } + } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java index 9eb689d..8d902d1 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/config/AzureComputeServiceContextModule.java @@ -21,7 +21,6 @@ import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_P import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT; import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_FORMAT; import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_REGEXP; - import java.util.concurrent.TimeUnit; import javax.inject.Named; @@ -34,14 +33,13 @@ import org.jclouds.azurecompute.compute.functions.DeploymentToNodeMetadata; import org.jclouds.azurecompute.compute.functions.LocationToLocation; import org.jclouds.azurecompute.compute.functions.OSImageToImage; import org.jclouds.azurecompute.compute.functions.RoleSizeToHardware; +import org.jclouds.azurecompute.compute.options.AzureComputeTemplateOptions; import org.jclouds.azurecompute.compute.strategy.GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes; import org.jclouds.azurecompute.compute.strategy.UseNodeCredentialsButOverrideFromTemplate; -import org.jclouds.azurecompute.compute.strategy.impl.AzureAdaptingComputeServiceStrategies; import org.jclouds.azurecompute.domain.Deployment; import org.jclouds.azurecompute.domain.Location; import org.jclouds.azurecompute.domain.OSImage; import org.jclouds.azurecompute.domain.RoleSize; -import org.jclouds.azurecompute.options.AzureComputeTemplateOptions; import org.jclouds.azurecompute.util.ConflictManagementPredicate; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.config.ComputeServiceAdapterContextModule; @@ -51,7 +49,6 @@ import org.jclouds.compute.extensions.SecurityGroupExtension; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; -import org.jclouds.compute.strategy.impl.AdaptingComputeServiceStrategies; import com.google.common.base.Function; import com.google.common.base.Predicate; @@ -74,8 +71,6 @@ public class AzureComputeServiceContextModule }).to(RoleSizeToHardware.class); bind(new TypeLiteral<Function<Deployment, NodeMetadata>>() { }).to(DeploymentToNodeMetadata.class); - bind(new TypeLiteral<AdaptingComputeServiceStrategies<Deployment, RoleSize, OSImage, Location>>() { - }).to(AzureAdaptingComputeServiceStrategies.class); bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class); bind(new TypeLiteral<Function<Location, org.jclouds.domain.Location>>() { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java index 8848127..f24c5fe 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/extensions/AzureComputeSecurityGroupExtension.java @@ -17,7 +17,7 @@ package org.jclouds.azurecompute.compute.extensions; import static com.google.common.base.Preconditions.checkNotNull; - +import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage; import java.util.List; import java.util.Set; @@ -27,16 +27,14 @@ import javax.inject.Named; import org.jclouds.azurecompute.AzureComputeApi; import org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; -import org.jclouds.azurecompute.domain.CloudService; import org.jclouds.azurecompute.domain.Deployment; -import org.jclouds.azurecompute.domain.Deployment.Status; import org.jclouds.azurecompute.domain.NetworkConfiguration; import org.jclouds.azurecompute.domain.NetworkConfiguration.VirtualNetworkSite; import org.jclouds.azurecompute.domain.NetworkSecurityGroup; import org.jclouds.azurecompute.domain.Role; import org.jclouds.azurecompute.domain.Rule; -import org.jclouds.azurecompute.util.NetworkSecurityGroups; import org.jclouds.azurecompute.util.ConflictManagementPredicate; +import org.jclouds.azurecompute.util.NetworkSecurityGroups; import org.jclouds.compute.domain.SecurityGroup; import org.jclouds.compute.domain.SecurityGroupBuilder; import org.jclouds.compute.extensions.SecurityGroupExtension; @@ -48,12 +46,10 @@ import org.jclouds.net.domain.IpProtocol; import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; import com.google.common.base.Splitter; import com.google.common.collect.FluentIterable; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; -import static org.jclouds.azurecompute.compute.AzureComputeServiceAdapter.generateIllegalStateExceptionMessage; /** * An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s. @@ -154,7 +150,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio name, name, location.getId(), null, null); final String createNSGRequestId = api.getNetworkSecurityGroupApi().create(networkSecurityGroup); if (!operationSucceededPredicate.apply(createNSGRequestId)) { - final String message = generateIllegalStateExceptionMessage( + final String message = generateIllegalStateExceptionMessage("Create NSG" + name, createNSGRequestId, azureComputeConstants.operationTimeout()); logger.warn(message); throw new IllegalStateException(message); @@ -195,7 +191,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio virtualNetworkName, subnetName, id); } }.apply(id)) { - final String message = generateIllegalStateExceptionMessage( + final String message = generateIllegalStateExceptionMessage("Remove NSG" + id + " from subnet " + subnetName, "Remove security group from subnet", azureComputeConstants.operationTimeout()); logger.warn(message); throw new IllegalStateException(message); @@ -225,59 +221,6 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio // add rule to NSG addRuleToNetworkSecurityGroup(id, ruleName, priority, ipPermission); - // add endpoint to VM - for (final CloudService service : api.getCloudServiceApi().list()) { - // TODO filter deployments - final Deployment deployment = api.getDeploymentApiForService(service.name()).get(service.name()); - if (deployment != null && deployment.status() != Status.DELETING) { - for (Deployment.VirtualIP vip : Iterables.filter(deployment.virtualIPs(), Predicates.notNull())) { - for (final Role role : deployment.roleList()) { - for (Role.ConfigurationSet configurationSet : role.configurationSets()) { - if (ipPermission.getFromPort() < ipPermission.getToPort()) { - for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) { - final String name = NetworkSecurityGroups.createRuleName( - azureComputeConstants.tcpRuleFormat(), i, i); - configurationSet.inputEndpoints().add(createInputEndpoint( - name, - ipPermission.getIpProtocol().name(), - vip.address(), - i)); - } - } else { - configurationSet.inputEndpoints().add(createInputEndpoint( - ruleName, - ipPermission.getIpProtocol().name(), - vip.address(), - ipPermission.getToPort())); - } - } - - if (!new ConflictManagementPredicate(api, operationSucceededPredicate) { - - @Override - protected String operation() { - // Check for deployment validity - final Deployment deployment = api.getDeploymentApiForService( - service.name()).get(service.name()); - if (deployment == null || deployment.status() == Status.DELETING) { - return null; - } else { - return api.getVirtualMachineApiForDeploymentInService( - deployment.name(), deployment.name()). - updateRole(role.roleName(), role); - } - } - }.apply(role.roleName())) { - final String message = generateIllegalStateExceptionMessage( - "Operation", azureComputeConstants.operationTimeout()); - logger.warn(message); - throw new IllegalStateException(message); - } - } - } - } - } - return transformNetworkSecurityGroupToSecurityGroup(id); } @@ -315,50 +258,6 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio // remove rule to NSG removeRuleFromNetworkSecurityGroup(id, ruleName); - // TODO remove endpoint from VM - for (final CloudService service : api.getCloudServiceApi().list()) { - // TODO remove endpoint from VM - final Deployment deployment = api.getDeploymentApiForService(service.name()).get(service.name()); - if (deployment != null && deployment.status() != Status.DELETING) { - for (Deployment.VirtualIP vip : Iterables.filter(deployment.virtualIPs(), Predicates.notNull())) { - for (final Role role : deployment.roleList()) { - for (Role.ConfigurationSet configurationSet : role.configurationSets()) { - for (int i = ipPermission.getFromPort(); i <= ipPermission.getToPort(); i++) { - final String name = NetworkSecurityGroups.createRuleName( - azureComputeConstants.tcpRuleFormat(), i, i); - configurationSet.inputEndpoints().remove(createInputEndpoint( - name, - ipPermission. - getIpProtocol().name().toLowerCase(), - vip.address(), - i)); - } - } - - if (!new ConflictManagementPredicate(api, operationSucceededPredicate) { - @Override - protected String operation() { - // Check for deployment validity - final Deployment deployment = api.getDeploymentApiForService( - service.name()).get(service.name()); - if (deployment == null || deployment.status() == Status.DELETING) { - return null; - } else { - return api.getVirtualMachineApiForDeploymentInService( - deployment.name(), deployment.name()).updateRole(role.roleName(), role); - } - } - }.apply(role.roleName())) { - final String message = generateIllegalStateExceptionMessage( - "Operation", azureComputeConstants.operationTimeout()); - logger.warn(message); - throw new IllegalStateException(message); - } - } - } - } - } - return transformNetworkSecurityGroupToSecurityGroup(id); } @@ -473,7 +372,7 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio destinationPortRange, // destinationPortRange Rule.Protocol.fromString(protocol))); if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) { - final String message = generateIllegalStateExceptionMessage( + final String message = generateIllegalStateExceptionMessage("Add rule " + ruleName, setRuleToNSGRequestId, azureComputeConstants.operationTimeout()); logger.warn(message); throw new IllegalStateException(message); @@ -483,27 +382,11 @@ public class AzureComputeSecurityGroupExtension implements SecurityGroupExtensio private void removeRuleFromNetworkSecurityGroup(final String id, final String ruleName) { String setRuleToNSGRequestId = api.getNetworkSecurityGroupApi().deleteRule(id, ruleName); if (!operationSucceededPredicate.apply(setRuleToNSGRequestId)) { - final String message = generateIllegalStateExceptionMessage( + final String message = generateIllegalStateExceptionMessage("Remove rule " + ruleName, setRuleToNSGRequestId, azureComputeConstants.operationTimeout()); logger.warn(message); throw new IllegalStateException(message); } } - private Role.ConfigurationSet.InputEndpoint createInputEndpoint( - final String ruleName, final String protocol, final String address, final int port) { - - return Role.ConfigurationSet.InputEndpoint.create( - ruleName, - protocol, - port, - port, - address, - false, // enabledDirectServerReturn - null, // loadBalancerName - null, // loadBalancerProbe - null //idleTimeoutInMinutes - ); - } - } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java index cfe1ece..b26532b 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/DeploymentToNodeMetadata.java @@ -16,15 +16,16 @@ */ package org.jclouds.azurecompute.compute.functions; +import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import java.util.Set; import javax.inject.Inject; import org.jclouds.azurecompute.AzureComputeApi; +import org.jclouds.azurecompute.domain.CloudService; import org.jclouds.azurecompute.domain.Deployment; import org.jclouds.azurecompute.domain.Deployment.RoleInstance; -import org.jclouds.azurecompute.domain.CloudService; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; @@ -35,7 +36,6 @@ import org.jclouds.location.predicates.LocationPredicates; import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; @@ -53,6 +53,7 @@ public class DeploymentToNodeMetadata implements Function<Deployment, NodeMetada put(Deployment.InstanceStatus.FAILED_STARTING_ROLE, NodeMetadata.Status.ERROR). put(Deployment.InstanceStatus.FAILED_STARTING_VM, NodeMetadata.Status.ERROR). put(Deployment.InstanceStatus.PREPARING, NodeMetadata.Status.PENDING). + put(Deployment.InstanceStatus.PROVISIONING, NodeMetadata.Status.PENDING). put(Deployment.InstanceStatus.READY_ROLE, NodeMetadata.Status.RUNNING). put(Deployment.InstanceStatus.RESTARTING_ROLE, NodeMetadata.Status.PENDING). put(Deployment.InstanceStatus.STARTING_ROLE, NodeMetadata.Status.PENDING). @@ -97,7 +98,7 @@ public class DeploymentToNodeMetadata implements Function<Deployment, NodeMetada RoleSizeToHardware roleSizeToHardware, Map<String, Credentials> credentialStore) { this.nodeNamingConvention = namingConvention.createWithoutPrefix(); - this.locations = Preconditions.checkNotNull(locations, "locations"); + this.locations = checkNotNull(locations, "locations"); this.osImageToImage = osImageToImage; this.roleSizeToHardware = roleSizeToHardware; this.credentialStore = credentialStore; @@ -135,11 +136,13 @@ public class DeploymentToNodeMetadata implements Function<Deployment, NodeMetada */ if (from.status() != null) { final Optional<RoleInstance> roleInstance = tryFindFirstRoleInstanceInDeployment(from); - if (roleInstance.isPresent()) { + if (roleInstance.isPresent() && roleInstance.get().instanceStatus() != null) { builder.status(INSTANCESTATUS_TO_NODESTATUS.get(roleInstance.get().instanceStatus())); } else { builder.status(STATUS_TO_NODESTATUS.get(from.status())); } + } else { + builder.status(NodeMetadata.Status.UNRECOGNIZED); } final Set<String> publicIpAddresses = Sets.newLinkedHashSet(); http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java index fd844c4..5421531 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/RoleSizeToHardware.java @@ -20,6 +20,8 @@ import org.jclouds.azurecompute.domain.RoleSize; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; @@ -34,29 +36,12 @@ public class RoleSizeToHardware implements Function<RoleSize, Hardware> { hypervisor("Hyper-V"). processors(ImmutableList.of(new Processor(from.cores(), 2))). ram(from.memoryInMb()); - - // TODO volumes - /* - * if (from.s() != null) { - * builder.volumes( - * FluentIterable.from(from.getVirtualGuestBlockDevices()).filter(new Predicate<VirtualGuestBlockDevice>() { - * @Override - * public boolean apply(VirtualGuestBlockDevice input) { - * return input.getMountType().equals("Disk"); - * } - * }) - * .transform(new Function<VirtualGuestBlockDevice, Volume>() { - * @Override - * public Volume apply(VirtualGuestBlockDevice item) { - * float volumeSize = item.getVirtualDiskImage().getCapacity(); - * return new VolumeImpl( - * item.getId() + "", - * from.isLocalDiskFlag() ? Volume.Type.LOCAL : Volume.Type.SAN, - * volumeSize, null, item.getBootableFlag() == 1, false); - * } - * }).toSet()); - * } - */ + if (from.virtualMachineResourceDiskSizeInMb() != null) { + builder.volume(new VolumeBuilder() + .size(Float.valueOf(from.virtualMachineResourceDiskSizeInMb())) + .type(Volume.Type.LOCAL) + .build()); + } return builder.build(); } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java new file mode 100644 index 0000000..ed31e71 --- /dev/null +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/options/AzureComputeTemplateOptions.java @@ -0,0 +1,418 @@ +/* + * 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.compute.options; + +import static com.google.common.base.Preconditions.checkNotNull; +import java.util.List; +import java.util.Map; + +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.scriptbuilder.domain.Statement; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableList; + +/** + * Contains options supported by the {@link org.jclouds.compute.ComputeService#createNodesInGroup( + * String, int, org.jclouds.compute.options.TemplateOptions)} operation. + * + * <h2>Usage</h2> The recommended way to instantiate a {@link AzureComputeTemplateOptions} object is to statically + * import {@code AzureComputeTemplateOptions.*} and invoke a static creation method followed by an instance mutator (if + * needed): + * <p> + * + * <pre> + * import static org.jclouds.compute.options.AzureComputeTemplateOptions.Builder.*; + * ComputeService client = // get connection + * templateBuilder.options(inboundPorts(22, 80, 8080, 443)); + * Set<? extends NodeMetadata> set = client.createNodesInGroup(tag, 2, templateBuilder.build()); + * </pre> + * + */ +public class AzureComputeTemplateOptions extends TemplateOptions implements Cloneable { + + protected String virtualNetworkName; + protected List<String> subnetNames = ImmutableList.of(); + protected String storageAccountName; + protected String storageAccountType; + protected String networkSecurityGroupName; + protected String reservedIPName; + + @Override + public AzureComputeTemplateOptions clone() { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + copyTo(options); + return options; + } + + @Override + public void copyTo(final TemplateOptions to) { + super.copyTo(to); + if (to instanceof AzureComputeTemplateOptions) { + final AzureComputeTemplateOptions eTo = AzureComputeTemplateOptions.class.cast(to); + eTo.virtualNetworkName(virtualNetworkName); + if (!subnetNames.isEmpty()) { + eTo.subnetNames(subnetNames); + } + eTo.storageAccountName(storageAccountName); + eTo.storageAccountType(storageAccountType); + eTo.reservedIPName(reservedIPName); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AzureComputeTemplateOptions)) return false; + if (!super.equals(o)) return false; + + AzureComputeTemplateOptions that = (AzureComputeTemplateOptions) o; + + if (networkSecurityGroupName != null ? !networkSecurityGroupName.equals(that.networkSecurityGroupName) : that.networkSecurityGroupName != null) + return false; + if (reservedIPName != null ? !reservedIPName.equals(that.reservedIPName) : that.reservedIPName != null) return false; + if (storageAccountName != null ? !storageAccountName.equals(that.storageAccountName) : that.storageAccountName != null) return false; + if (storageAccountType != null ? !storageAccountType.equals(that.storageAccountType) : that.storageAccountType != null) return false; + if (subnetNames != null ? !subnetNames.equals(that.subnetNames) : that.subnetNames != null) return false; + if (virtualNetworkName != null ? !virtualNetworkName.equals(that.virtualNetworkName) : that.virtualNetworkName != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (virtualNetworkName != null ? virtualNetworkName.hashCode() : 0); + result = 31 * result + (subnetNames != null ? subnetNames.hashCode() : 0); + result = 31 * result + (storageAccountName != null ? storageAccountName.hashCode() : 0); + result = 31 * result + (storageAccountType != null ? storageAccountType.hashCode() : 0); + result = 31 * result + (networkSecurityGroupName != null ? networkSecurityGroupName.hashCode() : 0); + result = 31 * result + (reservedIPName != null ? reservedIPName.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("virtualNetworkName", virtualNetworkName) + .add("subnetNames", subnetNames) + .add("storageAccountName", storageAccountName) + .add("storageAccountType", storageAccountType) + .add("networkSecurityGroupName", networkSecurityGroupName) + .add("reservedIPName", reservedIPName) + .toString(); + } + + public AzureComputeTemplateOptions virtualNetworkName(@Nullable String virtualNetworkName) { + this.virtualNetworkName = virtualNetworkName; + return this; + } + + public AzureComputeTemplateOptions subnetNames(Iterable<String> subnetNames) { + this.subnetNames = ImmutableList.copyOf(checkNotNull(subnetNames, "subnetNames")); + return this; + } + + public AzureComputeTemplateOptions subnetNames(String...subnetNames) { + return subnetNames(ImmutableList.copyOf(checkNotNull(subnetNames, "subnetNames"))); + } + + + public AzureComputeTemplateOptions networkSecurityGroupName(@Nullable String networkSecurityGroupName) { + this.networkSecurityGroupName = networkSecurityGroupName; + return this; + } + + public AzureComputeTemplateOptions storageAccountName(@Nullable String storageAccountName) { + this.storageAccountName = storageAccountName; + return this; + } + + public AzureComputeTemplateOptions storageAccountType(@Nullable String storageAccountType) { + this.storageAccountType = storageAccountType; + return this; + } + + public AzureComputeTemplateOptions reservedIPName(@Nullable String reservedIPName) { + this.reservedIPName = reservedIPName; + return this; + } + + public String getVirtualNetworkName() { + return virtualNetworkName; + } + + public List<String> getSubnetNames() { + return subnetNames; + } + + public String getStorageAccountName() { + return storageAccountName; + } + + public String getStorageAccountType() { + return storageAccountType; + } + + public String getNetworkSecurityGroupName() { + return networkSecurityGroupName; + } + + public String getReservedIPName() { + return reservedIPName; + } + + public static class Builder { + + /** + * @see #virtualNetworkName + */ + public static AzureComputeTemplateOptions virtualNetworkName(final String virtualNetworkName) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.virtualNetworkName(virtualNetworkName); + } + + /** + * @see #subnetNames + */ + public static AzureComputeTemplateOptions subnetNames(String...subnetNames) { + AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.subnetNames(subnetNames); + } + + /** + * @see #subnetNames + */ + public static AzureComputeTemplateOptions subnetNames(Iterable<String> subnetNames) { + AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.subnetNames(subnetNames); + } + + /** + * @see #storageAccountName + */ + public static AzureComputeTemplateOptions storageAccountName(final String storageAccountName) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.storageAccountName(storageAccountName); + } + + /** + * @see #storageAccountType + */ + public static AzureComputeTemplateOptions storageAccountType(final String storageAccountType) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.storageAccountType(storageAccountType); + } + + /** + * @see org.jclouds.compute.options.TemplateOptions#inboundPorts(int...) + */ + public static AzureComputeTemplateOptions inboundPorts(final int... ports) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.inboundPorts(ports); + } + + /** + * @see org.jclouds.compute.options.TemplateOptions#blockOnPort(int, int) + */ + public static AzureComputeTemplateOptions blockOnPort(final int port, final int seconds) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.blockOnPort(port, seconds); + } + + /** + * @see org.jclouds.compute.options.TemplateOptions#userMetadata(java.util.Map) + */ + public static AzureComputeTemplateOptions userMetadata(final Map<String, String> userMetadata) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.userMetadata(userMetadata); + } + + /** + * @see org.jclouds.compute.options.TemplateOptions#userMetadata(String, String) + */ + public static AzureComputeTemplateOptions userMetadata(final String key, final String value) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.userMetadata(key, value); + } + + /** + * @see org.jclouds.compute.options.TemplateOptions#nodeNames(Iterable) + */ + public static AzureComputeTemplateOptions nodeNames(final Iterable<String> nodeNames) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.nodeNames(nodeNames); + } + + /** + * @see org.jclouds.compute.options.TemplateOptions#networks(Iterable) + */ + public static AzureComputeTemplateOptions networks(final Iterable<String> networks) { + final AzureComputeTemplateOptions options = new AzureComputeTemplateOptions(); + return options.networks(networks); + } + } + + // methods that only facilitate returning the correct object type + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions blockOnPort(int port, int seconds) { + return AzureComputeTemplateOptions.class.cast(super.blockOnPort(port, seconds)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions inboundPorts(int... ports) { + return AzureComputeTemplateOptions.class.cast(super.inboundPorts(ports)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions authorizePublicKey(String publicKey) { + return AzureComputeTemplateOptions.class.cast(super.authorizePublicKey(publicKey)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions installPrivateKey(String privateKey) { + return AzureComputeTemplateOptions.class.cast(super.installPrivateKey(privateKey)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions blockUntilRunning(boolean blockUntilRunning) { + return AzureComputeTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions dontAuthorizePublicKey() { + return AzureComputeTemplateOptions.class.cast(super.dontAuthorizePublicKey()); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions nameTask(String name) { + return AzureComputeTemplateOptions.class.cast(super.nameTask(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions runAsRoot(boolean runAsRoot) { + return AzureComputeTemplateOptions.class.cast(super.runAsRoot(runAsRoot)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions runScript(Statement script) { + return AzureComputeTemplateOptions.class.cast(super.runScript(script)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions overrideLoginCredentials(LoginCredentials overridingCredentials) { + return AzureComputeTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions overrideLoginPassword(String password) { + return AzureComputeTemplateOptions.class.cast(super.overrideLoginPassword(password)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions overrideLoginPrivateKey(String privateKey) { + return AzureComputeTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions overrideLoginUser(String loginUser) { + return AzureComputeTemplateOptions.class.cast(super.overrideLoginUser(loginUser)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) { + return AzureComputeTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions userMetadata(Map<String, String> userMetadata) { + return AzureComputeTemplateOptions.class.cast(super.userMetadata(userMetadata)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions userMetadata(String key, String value) { + return AzureComputeTemplateOptions.class.cast(super.userMetadata(key, value)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions nodeNames(Iterable<String> nodeNames) { + return AzureComputeTemplateOptions.class.cast(super.nodeNames(nodeNames)); + } + + /** + * {@inheritDoc} + */ + @Override + public AzureComputeTemplateOptions networks(Iterable<String> networks) { + return AzureComputeTemplateOptions.class.cast(super.networks(networks)); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java new file mode 100644 index 0000000..4b8d3f2 --- /dev/null +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/predicates/StorageServicePredicates.java @@ -0,0 +1,80 @@ +/* + * 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.compute.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; + +import org.jclouds.azurecompute.domain.StorageService; + +import com.google.common.base.Predicate; + +/** + * Predicates for working with {@link StorageService} collections. + */ +public class StorageServicePredicates { + + + public static Predicate<StorageService> sameLocation(final String location) { + checkNotNull(location, "location must be defined"); + + return new Predicate<StorageService>() { + @Override + public boolean apply(StorageService storageService) { + return storageService.storageServiceProperties().location().equals(location); + } + + @Override + public String toString() { + return "sameLocation(" + location + ")"; + } + }; + } + + public static Predicate<StorageService> status(final StorageService.Status status) { + checkNotNull(status, "status must be defined"); + + return new Predicate<StorageService>() { + @Override + public boolean apply(StorageService storageService) { + return storageService.storageServiceProperties().status() == status; + } + + @Override + public String toString() { + return "status(" + status + ")"; + } + }; + } + + public static Predicate<StorageService> matchesName(final String defaultStorageAccountPrefix) { + checkNotNull(defaultStorageAccountPrefix, "defaultStorageAccountPrefix must be defined"); + + return new Predicate<StorageService>() { + @Override + public boolean apply(StorageService storageService) { + return storageService.serviceName().matches(format("^%s[a-z]{10}$", defaultStorageAccountPrefix)); + } + + @Override + public String toString() { + return "matchesName(" + defaultStorageAccountPrefix + ")"; + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/f9b393de/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java ---------------------------------------------------------------------- diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java index b9ad65e..0b49637 100644 --- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java +++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/strategy/GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes.java @@ -16,28 +16,26 @@ */ package org.jclouds.azurecompute.compute.strategy; +import static com.google.common.base.Objects.firstNonNull; import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.notNull; import static com.google.common.collect.Iterables.tryFind; import static java.lang.String.format; import static org.jclouds.azurecompute.compute.config.AzureComputeServiceContextModule.AzureComputeConstants; - import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.azurecompute.AzureComputeApi; +import org.jclouds.azurecompute.compute.options.AzureComputeTemplateOptions; +import org.jclouds.azurecompute.compute.predicates.StorageServicePredicates; import org.jclouds.azurecompute.config.AzureComputeProperties; -import org.jclouds.azurecompute.domain.NetworkConfiguration; -import org.jclouds.azurecompute.domain.NetworkSecurityGroup; -import org.jclouds.azurecompute.domain.StorageService; import org.jclouds.azurecompute.domain.CreateStorageServiceParams; -import org.jclouds.azurecompute.options.AzureComputeTemplateOptions; +import org.jclouds.azurecompute.domain.StorageService; import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; @@ -49,11 +47,7 @@ import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThen import com.google.common.base.Optional; import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.Inject; @@ -63,21 +57,10 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet { private static final String DEFAULT_STORAGE_ACCOUNT_PREFIX = "jclouds"; - private static final String DEFAULT_STORAGE_SERVICE_TYPE = "Standard_GRS"; - private static final String DEFAULT_VIRTUAL_NETWORK_NAME = "jclouds-virtual-network"; - - private static final String DEFAULT_ADDRESS_SPACE_ADDRESS_PREFIX = "10.0.0.0/20"; - - private static final String DEFAULT_SUBNET_NAME = "jclouds-1"; - - private static final String DEFAULT_SUBNET_ADDRESS_PREFIX = "10.0.0.0/23"; - private final AzureComputeApi api; - private final Predicate<String> operationSucceededPredicate; - private final AzureComputeConstants azureComputeConstants; @Inject @@ -113,69 +96,29 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes final Multimap<NodeMetadata, CustomizationResponse> customizationResponses) { final AzureComputeTemplateOptions templateOptions = template.getOptions().as(AzureComputeTemplateOptions.class); - final String storageAccountName = templateOptions.getStorageAccountName(). - or(generateStorageServiceName(DEFAULT_STORAGE_ACCOUNT_PREFIX)); final String location = template.getLocation().getId(); - final String storageAccountType = templateOptions.getStorageAccountType().or(DEFAULT_STORAGE_SERVICE_TYPE); - final String virtualNetworkName = templateOptions.getVirtualNetworkName().or(DEFAULT_VIRTUAL_NETWORK_NAME); - final String subnetName = templateOptions.getSubnetName().or(DEFAULT_SUBNET_NAME); - final String addressSpaceAddressPrefix = templateOptions.getAddressSpaceAddressPrefix(). - or(DEFAULT_ADDRESS_SPACE_ADDRESS_PREFIX); - final String subnetAddressPrefix = templateOptions.getSubnetAddressPrefix().or(DEFAULT_SUBNET_ADDRESS_PREFIX); - final Set<String> networkSecurityGroupNames = templateOptions.getGroups().isEmpty() ? Sets.<String>newHashSet() : templateOptions.getGroups(); - - // get or create storage service - final StorageService storageService = tryFindExistingStorageServiceAccountOrCreate( - api, location, storageAccountName, storageAccountType); - templateOptions.storageAccountName(storageService.serviceName()); - - // check existence or create virtual network - checkExistingVirtualNetworkNamedOrCreate( - virtualNetworkName, location, subnetName, addressSpaceAddressPrefix, subnetAddressPrefix); - templateOptions.virtualNetworkName(virtualNetworkName); - templateOptions.subnetName(subnetName); - - // add network security group to the subnet - if (!networkSecurityGroupNames.isEmpty()) { - String networkSecurityGroupName = Iterables.get(networkSecurityGroupNames, 0); - logger.warn("Only network security group '%s' will be applied to subnet '%s'.", - networkSecurityGroupName, subnetName); - final NetworkSecurityGroup networkSecurityGroupAppliedToSubnet = api.getNetworkSecurityGroupApi(). - getNetworkSecurityGroupAppliedToSubnet(virtualNetworkName, subnetName); - if (networkSecurityGroupAppliedToSubnet != null) { - if (!networkSecurityGroupAppliedToSubnet.name().equals(networkSecurityGroupName)) { - logger.debug("Removing a networkSecurityGroup %s is already applied to subnet '%s' ...", - networkSecurityGroupName, subnetName); - // remove existing nsg from subnet - String removeFromSubnetRequestId = api.getNetworkSecurityGroupApi(). - removeFromSubnet(virtualNetworkName, subnetName, networkSecurityGroupAppliedToSubnet.name()); - if (!operationSucceededPredicate.apply(removeFromSubnetRequestId)) { - final String warnMessage = format( - "Remove existing networkSecurityGroup(%s) to subnet(%s) has not been completed " - + "within %sms.", networkSecurityGroupName, subnetName, - azureComputeConstants.operationTimeout()); - logger.warn(warnMessage); - final String illegalStateExceptionMessage = format( - "%s. Please, try by increasing `%s` and try again", - AzureComputeProperties.OPERATION_TIMEOUT, warnMessage); - throw new IllegalStateException(illegalStateExceptionMessage); - } - } - } - // add nsg to subnet - logger.debug("Adding a networkSecurityGroup %s is already applied to subnet '%s' of virtual network %s ...", - networkSecurityGroupName, subnetName, virtualNetworkName); - final String addToSubnetId = api.getNetworkSecurityGroupApi().addToSubnet(virtualNetworkName, subnetName, - networkSecurityGroupName); - if (!operationSucceededPredicate.apply(addToSubnetId)) { - final String warnMessage = format("Add networkSecurityGroup(%s) to subnet(%s) has not been completed " - + "within %sms.", networkSecurityGroupName, subnetName, azureComputeConstants.operationTimeout()); - logger.warn(warnMessage); - final String illegalStateExceptionMessage = format("%s. Please, try by increasing `%s` and try again", - AzureComputeProperties.OPERATION_TIMEOUT, warnMessage); - throw new IllegalStateException(illegalStateExceptionMessage); + final String storageAccountName = templateOptions.getStorageAccountName(); + final String storageAccountType = firstNonNull(templateOptions.getStorageAccountType(), DEFAULT_STORAGE_SERVICE_TYPE); + final String virtualNetworkName = templateOptions.getVirtualNetworkName(); + + final StorageService storageService; + if (storageAccountName != null) { + if (api.getStorageAccountApi().get(storageAccountName) == null) { + String message = String.format("storageAccountName %s specified via AzureComputeTemplateOptions doesn't exist", storageAccountName); + logger.error(message); + throw new IllegalStateException(message); } + } else { // get suitable or create storage service + storageService = tryFindExistingStorageServiceAccountOrCreate(api, location, generateStorageServiceName(DEFAULT_STORAGE_ACCOUNT_PREFIX), storageAccountType); + templateOptions.storageAccountName(storageService.serviceName()); + } + + if (virtualNetworkName != null && templateOptions.getSubnetNames().isEmpty()) { + String message = "AzureComputeTemplateOption.subnetNames must not be empty, if AzureComputeTemplateOption.virtualNetworkName is defined."; + logger.warn(message); + throw new IllegalArgumentException(message); } + return super.execute(group, count, template, goodNodes, badNodes, customizationResponses); } @@ -184,19 +127,18 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes * the location, otherwise it creates a new storage service account with name and type in the location */ private StorageService tryFindExistingStorageServiceAccountOrCreate( - final AzureComputeApi api, final String location, final String name, final String type) { + final AzureComputeApi api, final String location, final String storageAccountName, final String type) { final List<StorageService> storageServices = api.getStorageAccountApi().list(); logger.debug("Looking for a suitable existing storage account ..."); - @SuppressWarnings("unchecked") - final Predicate<StorageService> storageServicePredicate = and(notNull(), - new SameLocationAndCreatedStorageServicePredicate(location), new Predicate<StorageService>() { - @Override - public boolean apply(final StorageService input) { - return input.serviceName().matches(format("^%s[a-z]{10}$", DEFAULT_STORAGE_ACCOUNT_PREFIX)); - } - }); + final Predicate<StorageService> storageServicePredicate = and( + notNull(), + StorageServicePredicates.sameLocation(location), + StorageServicePredicates.status(StorageService.Status.Created), + StorageServicePredicates.matchesName(DEFAULT_STORAGE_ACCOUNT_PREFIX) + ); + final Optional<StorageService> storageServiceOptional = tryFind(storageServices, storageServicePredicate); if (storageServiceOptional.isPresent()) { final StorageService storageService = storageServiceOptional.get(); @@ -204,16 +146,16 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes return storageService; } else { // create - if (!checkAvailability(name)) { - logger.warn("The storage service account name %s is not available", name); + if (!checkAvailability(storageAccountName)) { + logger.warn("The storage service account name %s is not available", storageAccountName); throw new IllegalStateException(format("Can't create a valid storage account with name %s. " - + "Please, try by choosing a different `storageAccountName` in templateOptions and try again", name)); + + "Please, try by choosing a different `storageAccountName` in templateOptions and try again", storageAccountName)); } - logger.debug("Creating a storage service account '%s' in location '%s' ...", name, location); + logger.debug("Creating a storage service account '%s' in location '%s' ...", storageAccountName, location); final String createStorageServiceRequestId = api.getStorageAccountApi().create( CreateStorageServiceParams.builder() - .serviceName(name) - .label(name) + .serviceName(storageAccountName) + .label(storageAccountName) .location(location) .accountType(StorageService.AccountType.valueOf(type)) .build()); @@ -225,54 +167,10 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes warnMessage, AzureComputeProperties.OPERATION_TIMEOUT); throw new IllegalStateException(illegalStateExceptionMessage); } - return api.getStorageAccountApi().get(name); - } - } - - private void checkExistingVirtualNetworkNamedOrCreate( - final String virtualNetworkName, final String location, final String subnetName, - final String addressSpaceAddressPrefix, final String subnetAddressPrefix) { - - logger.debug("Looking for a virtual network named '%s' ...", virtualNetworkName); - final Optional<NetworkConfiguration.VirtualNetworkSite> networkSiteOptional - = getVirtualNetworkNamed(virtualNetworkName); - if (networkSiteOptional.isPresent()) { - return; - } - final NetworkConfiguration networkConfiguration = NetworkConfiguration.create( - NetworkConfiguration.VirtualNetworkConfiguration.create(null, - ImmutableList.of(NetworkConfiguration.VirtualNetworkSite.create( - UUID.randomUUID().toString(), - virtualNetworkName, - location, - NetworkConfiguration.AddressSpace.create(addressSpaceAddressPrefix), - ImmutableList.of(NetworkConfiguration.Subnet.create( - subnetName, subnetAddressPrefix, null)))) - ) - ); - logger.debug("Creating a virtual network with configuration '%s' ...", networkConfiguration); - final String setNetworkConfigurationRequestId = api.getVirtualNetworkApi().set(networkConfiguration); - if (!operationSucceededPredicate.apply(setNetworkConfigurationRequestId)) { - final String warnMessage = format("Network configuration (%s) has not been completed within %sms.", - networkConfiguration, azureComputeConstants.operationTimeout()); - logger.warn(warnMessage); - final String illegalStateExceptionMessage = format("%s. Please, try by increasing `%s` and try again", - AzureComputeProperties.OPERATION_TIMEOUT, warnMessage); - throw new IllegalStateException(illegalStateExceptionMessage); + return api.getStorageAccountApi().get(storageAccountName); } } - private Optional<NetworkConfiguration.VirtualNetworkSite> getVirtualNetworkNamed(final String virtualNetworkName) { - return FluentIterable.from(api.getVirtualNetworkApi().list()) - .filter(new Predicate<NetworkConfiguration.VirtualNetworkSite>() { - @Override - public boolean apply(final NetworkConfiguration.VirtualNetworkSite input) { - return input.name().equals(virtualNetworkName); - } - }) - .first(); - } - private boolean checkAvailability(final String name) { return api.getStorageAccountApi().isAvailable(name).result(); } @@ -289,18 +187,4 @@ public class GetOrCreateStorageServiceAndVirtualNetworkThenCreateNodes return builder.toString(); } - private static class SameLocationAndCreatedStorageServicePredicate implements Predicate<StorageService> { - - private final String location; - - public SameLocationAndCreatedStorageServicePredicate(final String location) { - this.location = location; - } - - @Override - public boolean apply(final StorageService input) { - return input.storageServiceProperties().location().equals(location) - && input.storageServiceProperties().status().equals("Created"); - } - } }
