diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiLiveTest.java index 13269a7be56..3996577e06f 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiLiveTest.java @@ -71,7 +71,7 @@ public boolean apply(Network network) { } })); - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; vm = VirtualMachineApiLiveTest.createVirtualMachineInNetwork(network, defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java index 8a02b49fca1..eced10eb0dc 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java @@ -86,7 +86,7 @@ public boolean apply(Network network) { public void testCreateVm() { if (networksDisabled) return; - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; vm = VirtualMachineApiLiveTest.createVirtualMachineInNetwork(network, defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete, virtualMachineRunning); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiLiveTest.java index ab07d43e4b3..943ebeea01f 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiLiveTest.java @@ -174,7 +174,7 @@ public void testListSecurityGroup() throws Exception { @Test(dependsOnMethods = "testCreateIngress") public void testCreateVMInSecurityGroup() throws Exception { skipIfSecurityGroupsNotSupported(); - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; vm = VirtualMachineApiLiveTest.createVirtualMachineWithSecurityGroupInZone(zone.getId(), defaultTemplateOrPreferredInZone(defaultTemplate, client, zone.getId()), group.getId(), client, jobComplete, virtualMachineRunning); @@ -204,7 +204,7 @@ protected void checkGroup(SecurityGroup group) { @Test public void testCreateVMWithoutSecurityGroupAssignsDefault() throws Exception { skipIfSecurityGroupsNotSupported(); - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; VirtualMachine newVm = VirtualMachineApiLiveTest.createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions.NONE, zone.getId(), defaultTemplateOrPreferredInZone(defaultTemplate, client, zone.getId()), client, jobComplete, virtualMachineRunning); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiLiveTest.java index d85cd051abd..2c1ebe7ee7e 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiLiveTest.java @@ -110,7 +110,7 @@ public boolean apply(Network network) { assertNotNull(network); // Create a VM and stop it - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; vmForCreation = VirtualMachineApiLiveTest.createVirtualMachineInNetwork(network, defaultTemplate, client, jobComplete, virtualMachineRunning); assertTrue(jobComplete.apply(client.getVirtualMachineApi().stopVirtualMachine(vmForCreation.getId())), vmForCreation.toString()); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java index 1b33bb511a7..36c01aae14c 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java @@ -176,7 +176,7 @@ public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtual @Test public void testCreateVirtualMachine() throws Exception { - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; vm = createVirtualMachine(client, defaultTemplate, jobComplete, virtualMachineRunning); if (vm.getPassword() != null) { conditionallyCheckSSH(); @@ -190,7 +190,7 @@ assert in(ImmutableSet.of("ROOT", "NetworkFilesystem", "IscsiLUN", "VMFS", "PreS public void testCreateVirtualMachineWithSpecificIp() throws Exception { skipIfNotGlobalAdmin(); - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; Network network = null; try { diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java index 75bfd18e8d5..0bb726cd750 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java @@ -58,7 +58,7 @@ public void setupClient() { prefix += "nat"; try { network = find(client.getNetworkApi().listNetworks(), NetworkPredicates.supportsStaticNAT()); - String defaultTemplate = template != null ? template.getImageId() : null; + String defaultTemplate = templateBuilderSpec != null ? templateBuilderSpec.getImageId() : null; vm = VirtualMachineApiLiveTest.createVirtualMachineInNetwork(network, defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete, virtualMachineRunning); diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java index 88704e3ced6..d27924f1ff5 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java @@ -18,6 +18,8 @@ import static com.google.common.io.BaseEncoding.base16; import static org.jclouds.filesystem.util.Utils.isMacOSX; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -912,7 +914,7 @@ private void putBlobAndCheckIt(String blobKey) { @DataProvider public Object[][] ignoreOnMacOSX() { - return isMacOSX() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return isMacOSX() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } } diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java index 7a701a0a1de..7dfdd3acf7b 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java @@ -19,6 +19,8 @@ import static org.jclouds.blobstore.options.ListContainerOptions.Builder.maxResults; import static org.jclouds.filesystem.util.Utils.isMacOSX; import static org.testng.Assert.assertEquals; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import java.io.IOException; import java.util.Properties; @@ -165,14 +167,14 @@ public void testDirectory() { @DataProvider public Object[][] ignoreOnMacOSX() { - return isMacOSX() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return isMacOSX() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } @DataProvider public Object[][] ignoreOnWindows() { - return TestUtils.isWindowsOs() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return TestUtils.isWindowsOs() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } @Override diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java index 3fdd855909f..9079fa0bb2e 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java @@ -17,6 +17,8 @@ package org.jclouds.filesystem.strategy.internal; import static org.jclouds.filesystem.util.Utils.isMacOSX; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.jclouds.utils.TestUtils.randomByteSource; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -699,7 +701,7 @@ private String getAbsoluteDirectory() throws IOException { @DataProvider public Object[][] ignoreOnMacOSX() { - return isMacOSX() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return isMacOSX() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } } diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java index cd0276ca5cb..224c21ed89f 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java @@ -54,9 +54,6 @@ public class TestUtils { private static final Iterator IMAGE_RESOURCES_ITERATOR = Iterators.cycle(IMAGE_RESOURCES); - public static final Object[][] NO_INVOCATIONS = new Object[0][0]; - public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] }; - /** * Generate a random blob key simple name (with no path in the key) * @return diff --git a/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java b/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java index 5d0d7cf5b0e..0aba64155e6 100644 --- a/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java +++ b/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java @@ -24,6 +24,8 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.CERTIFICATE; import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertNotNull; import java.util.Properties; @@ -63,19 +65,19 @@ public AuthorizationApiLiveTest() { @DataProvider public Object[][] onlyRunForP12PrivateKeyCredentials() { return (CredentialType.fromValue(credentialType) == CredentialType.P12_PRIVATE_KEY_CREDENTIALS) ? - OAuthTestUtils.SINGLE_NO_ARG_INVOCATION : OAuthTestUtils.NO_INVOCATIONS; + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; } @DataProvider public Object[][] onlyRunForClientCredentialsSecret() { return (CredentialType.fromValue(credentialType) == CredentialType.CLIENT_CREDENTIALS_SECRET) ? - OAuthTestUtils.SINGLE_NO_ARG_INVOCATION : OAuthTestUtils.NO_INVOCATIONS; + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; } @DataProvider public Object[][] onlyRunForClientCredentialsP12() { return (CredentialType.fromValue(credentialType) == CredentialType.CLIENT_CREDENTIALS_P12_AND_CERTIFICATE) ? - OAuthTestUtils.SINGLE_NO_ARG_INVOCATION : OAuthTestUtils.NO_INVOCATIONS; + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; } @Test(dataProvider = "onlyRunForP12PrivateKeyCredentials") diff --git a/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java b/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java index d15f8b09c67..920ff18155f 100644 --- a/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java +++ b/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java @@ -32,9 +32,6 @@ public class OAuthTestUtils { - public static final Object[][] NO_INVOCATIONS = new Object[0][0]; - public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] }; - public static Properties defaultProperties(Properties properties) { try { properties = properties == null ? new Properties() : properties; diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java new file mode 100644 index 00000000000..f99b991f445 --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java @@ -0,0 +1,84 @@ +/* + * 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.compute.domain.internal; + +import com.google.common.base.Supplier; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.util.AutomaticHardwareIdSpec; +import org.jclouds.domain.Location; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.jclouds.compute.util.AutomaticHardwareIdSpec.automaticHardwareIdSpecBuilder; +import static org.jclouds.compute.util.AutomaticHardwareIdSpec.isAutomaticId; +import static org.jclouds.compute.util.AutomaticHardwareIdSpec.parseId; + +public class ArbitraryCpuRamTemplateBuilderImpl extends TemplateBuilderImpl { + @Inject + protected ArbitraryCpuRamTemplateBuilderImpl(@Memoized Supplier> locations, + @Memoized Supplier> images, @Memoized Supplier> hardwares, + Supplier defaultLocation, @Named("DEFAULT") Provider optionsProvider, + @Named("DEFAULT") Provider defaultTemplateProvider) { + super(locations, images, hardwares, defaultLocation, optionsProvider, defaultTemplateProvider); + } + + protected Hardware automaticHardwareForCpuAndRam(double cores, int ram) { + return new HardwareBuilder() + .id(automaticHardwareIdSpecBuilder(cores, ram).toString()) + .ram(ram) + .processor(new Processor(cores, 1.0)) + .build(); + } + + protected Hardware findHardwareWithId(Set hardwaresToSearch) { + try { + return super.findHardwareWithId(hardwaresToSearch); + } catch (NoSuchElementException ex) { + if (isAutomaticId(hardwareId)) { + AutomaticHardwareIdSpec spec = parseId(hardwareId); + return automaticHardwareForCpuAndRam(spec.getCores(), spec.getRam()); + } + else { + throw ex; + } + } + } + + protected Hardware resolveHardware(Set hardwarel, final Iterable images) { + try { + return super.resolveHardware(hardwarel, images); + } + catch (NoSuchElementException ex) { + if (super.minCores != 0 && super.minRam != 0) { + return automaticHardwareForCpuAndRam(minCores, minRam); + } + else throw new IllegalArgumentException("No hardware profile matching the given criteria was found. If " + + "you want to use exact values, please set the minCores and minRam values", ex); + } + } + +} diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java index 28654099519..f8606740c8c 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java @@ -16,33 +16,20 @@ */ package org.jclouds.compute.domain.internal; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.base.Predicates.and; -import static com.google.common.collect.Iterables.filter; -import static com.google.common.collect.Iterables.find; -import static com.google.common.collect.Iterables.size; -import static com.google.common.collect.Iterables.transform; -import static com.google.common.collect.Iterables.tryFind; -import static com.google.common.collect.Lists.newArrayList; -import static java.lang.String.format; -import static org.jclouds.compute.util.ComputeServiceUtils.getCores; -import static org.jclouds.compute.util.ComputeServiceUtils.getCoresAndSpeed; -import static org.jclouds.compute.util.ComputeServiceUtils.getSpace; - -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.regex.Pattern; - -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; - +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Ordering; +import com.google.common.primitives.Doubles; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.Hardware; @@ -59,20 +46,31 @@ import org.jclouds.domain.Location; import org.jclouds.logging.Logger; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.base.Objects; -import com.google.common.base.Objects.ToStringHelper; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.base.Supplier; -import com.google.common.collect.ComparisonChain; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Ordering; -import com.google.common.primitives.Doubles; +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.and; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.size; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Iterables.tryFind; +import static com.google.common.collect.Lists.newArrayList; +import static java.lang.String.format; +import static org.jclouds.compute.util.ComputeServiceUtils.getCores; +import static org.jclouds.compute.util.ComputeServiceUtils.getCoresAndSpeed; +import static org.jclouds.compute.util.ComputeServiceUtils.getSpace; public class TemplateBuilderImpl implements TemplateBuilder { @Resource @@ -348,7 +346,6 @@ public String toString() { return "imageDescription(" + imageDescription + ")"; } }; - private final Predicate hardwareIdPredicate = new Predicate() { @Override public boolean apply(Hardware input) { @@ -727,7 +724,7 @@ private Image loadImageWithId(Iterable images) { return image.get(); } - private Hardware findHardwareWithId(Set hardwaresToSearch) { + protected Hardware findHardwareWithId(Set hardwaresToSearch) { Hardware hardware; // TODO: switch to GetHardwareStrategy in version 1.5 hardware = tryFind(hardwaresToSearch, hardwareIdPredicate).orNull(); diff --git a/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java index e7f33844243..6ac36c7f08c 100644 --- a/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java @@ -33,6 +33,7 @@ import javax.inject.Named; import javax.inject.Singleton; +import com.google.common.base.Objects; import org.jclouds.Constants; import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.domain.ComputeMetadata; @@ -75,7 +76,8 @@ public AddNode(String name, String group, Template template) { public AtomicReference call() throws Exception { NodeMetadata node = null; logger.debug(">> adding node location(%s) name(%s) image(%s) hardware(%s)", template.getLocation().getId(), - name, template.getImage().getProviderId(), template.getHardware().getProviderId()); + name, Objects.firstNonNull(template.getImage().getProviderId(), template.getImage().getId()), + Objects.firstNonNull(template.getHardware().getProviderId(), template.getHardware().getId())); node = addNodeWithGroupStrategy.createNodeWithGroupEncodedIntoName(group, name, template); logger.debug("<< %s node(%s)", formatStatus(node), node.getId()); return new AtomicReference(node); diff --git a/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java b/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java new file mode 100644 index 00000000000..6aaa44a84b5 --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java @@ -0,0 +1,72 @@ +/* + * 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.compute.util; + +import com.google.common.base.Splitter; + +import java.util.Map; + +public class AutomaticHardwareIdSpec { + + private double cores; + private int ram; + + public static boolean isAutomaticId(String id) { + return id.startsWith("automatic:"); + } + + public static AutomaticHardwareIdSpec parseId(String hardwareId) { + AutomaticHardwareIdSpec spec = new AutomaticHardwareIdSpec(); + String hardwareSpec = hardwareId.substring(10); + Map specValues = Splitter.on(';') + .trimResults() + .omitEmptyStrings() + .withKeyValueSeparator('=') + .split(hardwareSpec); + if (!specValues.containsKey("ram") || !specValues.containsKey("cores")) { + throw new IllegalArgumentException(String.format("Omitted keys on hardwareId: %s. Please set number " + + "of cores and ram amount.", hardwareId)); + } + spec.ram = Integer.parseInt(specValues.get("ram")); + spec.cores = Double.parseDouble(specValues.get("cores")); + return spec; + } + + public static AutomaticHardwareIdSpec automaticHardwareIdSpecBuilder(double cores, int ram) { + AutomaticHardwareIdSpec spec = new AutomaticHardwareIdSpec(); + if (cores == 0 || ram == 0) { + throw new IllegalArgumentException(String.format("Omitted or wrong minCores and minRam. If you" + + " want to use exact values, please set the minCores and minRam values.")); + } + spec.cores = cores; + spec.ram = ram; + return spec; + } + + @Override + public String toString() { + return String.format("automatic:cores=%s;ram=%s", cores, ram); + } + + public double getCores() { + return cores; + } + + public int getRam() { + return ram; + } +} diff --git a/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java b/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java new file mode 100644 index 00000000000..568a60b9073 --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java @@ -0,0 +1,275 @@ +/* + * 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.compute.domain.internal; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Atomics; +import com.google.inject.Provider; +import com.google.inject.util.Providers; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.strategy.GetImageStrategy; +import org.jclouds.compute.suppliers.ImageCacheSupplier; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +@Test(groups = "unit", singleThreaded = true, testName = "ArbitraryCpuRamTemplateBuilderImplTest") +public class ArbitraryCpuRamTemplateBuilderImplTest { + private Location provider = new LocationBuilder() + .scope(LocationScope.PROVIDER) + .id("generic-provider") + .description("generic-provider") + .build(); + + private Location region = new LocationBuilder() + .scope(LocationScope.REGION) + .id("us-east-1") + .description("us-east-1") + .parent(provider) + .build(); + + private OperatingSystem os = OperatingSystem.builder() + .name("osName") + .version("osVersion") + .description("osDescription") + .arch("X86_32") + .build(); + + private Image image = new ImageBuilder() + .id("imageId") + .providerId("imageId") + .name("imageName") + .description("imageDescription") + .version("imageVersion") + .operatingSystem(os) + .status(Image.Status.AVAILABLE) + .location(null) + .build(); + + private Hardware hardware = new HardwareBuilder() + .ram(2048) + .processor(new Processor(2, 1)) + .id("hardwareId") + .name("hardwareName") + .location(region) + .uri(URI.create("uri")) + .build(); + + private final String errorMessage = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values"; + + @Test + public void testAutoGeneratedHardwareFromId(){ + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), + optionsProvider, templateBuilderProvider); + + Hardware hardware = templateBuilder.hardwareId("automatic:cores=2;ram=256").build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(256); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("automatic:cores=2.0;ram=256"); + } + + @Test + public void testAutoGeneratedHardwareWithMinCoresAndMinRam(){ + Supplier> locations = Suppliers.> ofInstance(ImmutableSet.of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + templateBuilder.minCores(4); + Template template = templateBuilder.build(); + Hardware hardware = template.getHardware(); + assertThat(hardware.getRam()).isEqualTo(1024); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(4.0); + assertThat(hardware.getId()).isEqualTo("automatic:cores=4.0;ram=1024"); + } + + @Test + public void testExistingHardwareProfileMatchHardwareProfileWithMinCoresMinRam() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(2); + templateBuilder.minRam(1024); + Template template = templateBuilder.build(); + Hardware hardware = template.getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("hardwareId"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testOnlyRamTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet.of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(4096); + templateBuilder.build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testOnlyCoresTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(4); + templateBuilder.build(); + } + + @Test + public void testOnlyRamMatchHardwareProfileTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet.of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + templateBuilder.build(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("hardwareId"); + } + + @Test + public void testOnlyCoresMatchHardwareProfileTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(1); + templateBuilder.build(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("hardwareId"); + } + +} diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java index 245d6bcab69..d8f3ccc0d46 100644 --- a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java @@ -33,6 +33,7 @@ import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.logging.Logger.getAnonymousLogger; +import static org.assertj.core.api.Assertions.assertThat; import static org.jclouds.Constants.PROPERTY_USER_THREADS; import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask; import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript; @@ -44,6 +45,8 @@ import static org.jclouds.compute.predicates.NodePredicates.runningInGroup; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.jclouds.util.Predicates2.retry; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -81,6 +84,7 @@ import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl; import org.jclouds.compute.util.OpenSocketFinder; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; @@ -96,6 +100,7 @@ import org.jclouds.ssh.SshException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeGroups; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.base.Function; @@ -218,7 +223,7 @@ public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception { } catch (Exception e) { } - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); template.getOptions().blockOnPort(22, 120); try { Set nodes = client.createNodesInGroup(group, 1, template); @@ -272,6 +277,24 @@ public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception { } } + @Test + public void testWeCanCancelTasks() throws Exception { + String group = this.group + "w"; + try { + client.destroyNodesMatching(inGroup(group)); + } catch (Exception e) { + + } + template = buildTemplate(templateBuilder()); + try { + Set nodes = client.createNodesInGroup(group, 1, template); + NodeMetadata node = getOnlyElement(nodes); + weCanCancelTasks(node); + } finally { + client.destroyNodesMatching(inGroup(group)); + } + } + @Test(enabled = false) protected void tryBadPassword(String group, Credentials good) throws AssertionError { try { @@ -321,7 +344,7 @@ protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetada @Test(enabled = true, dependsOnMethods = { "testImagesCache" }) public void testTemplateMatch() throws Exception { - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); Template toMatch = client.templateBuilder().imageId(template.getImage().getId()).build(); assertEquals(toMatch.getImage(), template.getImage()); } @@ -362,7 +385,7 @@ public void testCreateTwoNodesWithRunScript() throws Exception { @Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript") public void testCreateTwoNodesWithOneSpecifiedName() throws Exception { - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); template.getOptions().nodeNames(ImmutableSet.of("first-node")); Set nodes; try { @@ -386,8 +409,8 @@ public void testCreateTwoNodesWithOneSpecifiedName() throws Exception { this.nodes = newTreeSet(concat(this.nodes, nodes)); } - private Template refreshTemplate() { - return template = addRunScriptToTemplate(buildTemplate(client.templateBuilder())); + protected Template refreshTemplate() { + return template = addRunScriptToTemplate(buildTemplate(templateBuilder())); } protected static Template addRunScriptToTemplate(Template template) { @@ -425,7 +448,7 @@ public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() if (existingLocationIsAssignable) { getAnonymousLogger().info("creating another node based on existing nodes' location: " + existingLocation); - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); template = addRunScriptToTemplate(client.templateBuilder().fromTemplate(template) .locationId(existingLocation.getId()).build()); } else { @@ -460,7 +483,7 @@ public void testConcurrentUseOfComputeServiceToCreateNodes() throws Exception { final int groupNum = i; final String group = "twin" + groupNum; groups.add(group); - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); template.getOptions().inboundPorts(22, 8080).blockOnPort(22, 300 + groupNum); ListenableFuture future = userExecutor.submit(new Callable() { public NodeMetadata call() throws Exception { @@ -512,6 +535,14 @@ protected void checkNodes(Iterable nodes, String group, } } + protected TemplateBuilder templateBuilder() { + TemplateBuilder templateBuilder = client.templateBuilder(); + if (templateBuilderSpec != null) { + templateBuilder = templateBuilder.from(templateBuilderSpec); + } + return templateBuilder; + } + protected Template buildTemplate(TemplateBuilder templateBuilder) { return templateBuilder.build(); } @@ -719,7 +750,7 @@ protected void createAndRunAServiceInGroup(String group) throws RunNodesExceptio ImmutableSet tags = ImmutableSet.of(group); Stopwatch watch = Stopwatch.createStarted(); - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); template.getOptions().inboundPorts(22, 8080).blockOnPort(22, 300).userMetadata(userMetadata).tags(tags); NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, template)); @@ -820,7 +851,7 @@ public void testOptionToNotBlock() throws Exception { } // no inbound ports - template = buildTemplate(client.templateBuilder()); + template = buildTemplate(templateBuilder()); template.getOptions().blockUntilRunning(false).inboundPorts(); try { long time = currentTimeMillis(); @@ -915,6 +946,26 @@ protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node, String taskName) } } + @DataProvider + public Object[][] onlyIfAutomaticHardwareSupported() { + return client.templateBuilder() instanceof ArbitraryCpuRamTemplateBuilderImpl ? + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testCreateNodeWithCustomHardware() throws Exception { + Template template = buildTemplate(templateBuilder() + .hardwareId("automatic:cores=2;ram=4096")); + try { + NodeMetadata node = getOnlyElement(client.createNodesInGroup("custom", 1, template)); + assertThat(node.getHardware().getRam()).isEqualTo(4096); + assertThat(node.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + } + finally { + client.destroyNodesMatching(inGroup("custom")); + } + } + @AfterClass(groups = { "integration", "live" }) @Override protected void tearDownContext() { diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java index a54579d960a..4b7043bbe28 100644 --- a/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/internal/BaseGenericComputeServiceContextLiveTest.java @@ -35,7 +35,7 @@ public abstract class BaseGenericComputeServiceContextLiveTest extends BaseViewLiveTest { - protected TemplateBuilderSpec template; + protected TemplateBuilderSpec templateBuilderSpec; protected LoginCredentials loginCredentials = LoginCredentials.builder().user("root").build(); // isolate tests from eachother, as default credentialStore is static @@ -47,15 +47,15 @@ protected Properties setupProperties() { Properties overrides = super.setupProperties(); String spec = setIfTestSystemPropertyPresent(overrides, provider + ".template"); if (spec != null) { - template = TemplateBuilderSpec.parse(spec); - if (template.getLoginUser() != null) { - Iterable userPass = Splitter.on(':').split(template.getLoginUser()); + templateBuilderSpec = TemplateBuilderSpec.parse(spec); + if (templateBuilderSpec.getLoginUser() != null) { + Iterable userPass = Splitter.on(':').split(templateBuilderSpec.getLoginUser()); Builder loginCredentialsBuilder = LoginCredentials.builder(); loginCredentialsBuilder.user(Iterables.get(userPass, 0)); if (Iterables.size(userPass) == 2) loginCredentialsBuilder.password(Iterables.get(userPass, 1)); - if (template.getAuthenticateSudo() != null) - loginCredentialsBuilder.authenticateSudo(template.getAuthenticateSudo()); + if (templateBuilderSpec.getAuthenticateSudo() != null) + loginCredentialsBuilder.authenticateSudo(templateBuilderSpec.getAuthenticateSudo()); loginCredentials = loginCredentialsBuilder.build(); } } diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java index 8792cd140bf..5e27d5ae331 100644 --- a/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java @@ -16,7 +16,10 @@ */ package org.jclouds.compute.internal; +import static org.assertj.core.api.Assertions.assertThat; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -29,10 +32,14 @@ import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl; +import org.jclouds.compute.util.AutomaticHardwareIdSpec; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.LoginCredentials; import org.jclouds.rest.config.CredentialStoreModule; +import org.testng.SkipException; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.base.Splitter; @@ -191,9 +198,11 @@ protected void tryOverrideUsingPropertyKey(String propertyKey) { ComputeServiceContext context = null; try { Properties overrides = setupProperties(); - String login = template != null && template.getLoginUser() != null ? template.getLoginUser() : "foo:bar"; + String login = templateBuilderSpec != null && templateBuilderSpec.getLoginUser() != null ? templateBuilderSpec + .getLoginUser() : "foo:bar"; overrides.setProperty(propertyKey + ".image.login-user", login); - boolean auth = template != null && template.getAuthenticateSudo() != null ? template.getAuthenticateSudo() : true; + boolean auth = templateBuilderSpec != null && templateBuilderSpec.getAuthenticateSudo() != null ? templateBuilderSpec + .getAuthenticateSudo() : true; overrides.setProperty(propertyKey + ".image.authenticate-sudo", auth + ""); context = createView(overrides, ImmutableSet.of(credentialStoreModule)); @@ -223,4 +232,100 @@ static void assertEqualsTemplate(Template actual, Template expected){ assertTrue(actual.getLocation().getScope().compareTo(expected.getLocation().getScope()) <= 0); } + @DataProvider + public Object[][] onlyIfAutomaticHardwareSupported() { + return view.getComputeService().templateBuilder() instanceof ArbitraryCpuRamTemplateBuilderImpl ? + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareFromId() { + Template template = view.getComputeService().templateBuilder() + .hardwareId("automatic:cores=2;ram=1024").build(); + assertThat(template.getHardware().getId()).isEqualTo("automatic:cores=2;ram=1024"); + assertThat(template.getHardware().getRam()).isEqualTo(1024); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareMatchHardwareProfile() { + if (!view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder() + .minRam(2048).minCores(2).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isFalse(); + assertThat(template.getHardware().getRam()).isGreaterThanOrEqualTo(2048); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isGreaterThanOrEqualTo(2); + } + else { + throw new SkipException("Hardware profile list is empty, this provider can not match any hardware profile" + + "to the specified minRam and minCores."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareWithMinCoresAndMinRam() { + if (view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder() + .minRam(2048).minCores(2).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isTrue(); + assertThat(template.getHardware().getRam()).isEqualTo(2048); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + } + else { + throw new SkipException("Hardware profile list not empty."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareWithOnlyMinCoresMatchHardwareProfile() { + if (!view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder().minCores(4).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isFalse(); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isGreaterThanOrEqualTo(4); + } + else { + throw new SkipException("Hardware profile list is empty, this provider can not match any hardware profile" + + "to the specified minRam and minCores."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareWithOnlyMinRamMatchHardwareProfile() { + if (!view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder().minRam(4096).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isFalse(); + assertThat(template.getHardware().getRam()).isGreaterThanOrEqualTo(4096); + } + else { + throw new SkipException("Hardware profile list is empty, this provider can not match any hardware profile" + + "to the specified minRam and minCores."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}, + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values") + public void testAutoGeneratedHardwareWithOnlyMinRamNotMatchHardwareProfile() { + if (view.getComputeService().listHardwareProfiles().isEmpty()) { + view.getComputeService().templateBuilder().minRam(4096).build(); + } + else { + throw new SkipException("Hardware profile list not empty."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}, + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values") + public void testAutoGeneratedHardwareWithOnlyMinCoresNotMatchHardwareProfile() { + if (view.getComputeService().listHardwareProfiles().isEmpty()) { + view.getComputeService().templateBuilder().minCores(4).build(); + } + else { + throw new SkipException("Hardware profile list not empty."); + } + } + } diff --git a/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java b/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java new file mode 100644 index 00000000000..9dc72a20993 --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java @@ -0,0 +1,52 @@ +/* + * 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.compute.util; + +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@Test(groups = "unit", testName = "AutomaticHardwareIdSpecTest") +public class AutomaticHardwareIdSpecTest { + @Test + public void isAutomaticIdTest() { + assertThat(AutomaticHardwareIdSpec.isAutomaticId("automatic:cores=2;ram=256")).isTrue(); + } + + @Test + public void isNotAutomaticId() { + assertThat(AutomaticHardwareIdSpec.isAutomaticId("Hi, I'm a non automatic id.")).isFalse(); + } + + @Test + public void parseAutomaticIdTest() { + AutomaticHardwareIdSpec parser = AutomaticHardwareIdSpec.parseId("automatic:cores=2;ram=256"); + assertThat(parser.getRam()).isEqualTo(256); + assertThat(parser.getCores()).isEqualTo(2); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void parseAutomaticIdMissingValuesTest() { + AutomaticHardwareIdSpec.parseId("automatic:cores=2"); + } + + @Test + public void generateAutomaticIdTest() { + AutomaticHardwareIdSpec spec = AutomaticHardwareIdSpec.parseId("automatic:cores=2;ram=1024"); + assertThat(spec.toString()).isEqualTo("automatic:cores=2.0;ram=1024"); + } +} diff --git a/core/src/test/java/org/jclouds/utils/TestUtils.java b/core/src/test/java/org/jclouds/utils/TestUtils.java index 70823461540..cce923b97ee 100644 --- a/core/src/test/java/org/jclouds/utils/TestUtils.java +++ b/core/src/test/java/org/jclouds/utils/TestUtils.java @@ -27,6 +27,9 @@ */ public class TestUtils { + public static final Object[][] NO_INVOCATIONS = new Object[0][0]; + public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] }; + public static boolean isJava6() { return System.getProperty("java.version", "").contains("1.6."); } diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java index baaec3faf56..3756051b64f 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java @@ -78,6 +78,8 @@ import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; +import org.jclouds.compute.domain.internal.TemplateBuilderImpl; +import org.jclouds.googlecomputeengine.compute.domain.internal.GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl; public final class GoogleComputeEngineServiceContextModule extends ComputeServiceAdapterContextModule { @@ -91,6 +93,8 @@ protected void configure() { bind(new TypeLiteral>() { }).to(GoogleComputeEngineServiceAdapter.class); + bind(TemplateBuilderImpl.class).to(GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.class); + // Use compute service to supply locations, which are always zones. install(new LocationsFromComputeServiceAdapterModule() { }); diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java new file mode 100644 index 00000000000..774dce93746 --- /dev/null +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java @@ -0,0 +1,59 @@ +/* + * 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.googlecomputeengine.compute.domain.internal; + +import com.google.common.base.Supplier; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.Location; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.net.URI; +import java.util.Set; + +public class GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl extends ArbitraryCpuRamTemplateBuilderImpl { + @Inject + protected GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(@Memoized Supplier> locations, + @Memoized Supplier> images, + @Memoized Supplier> hardwares, Supplier defaultLocation, + @Named("DEFAULT") Provider optionsProvider, + @Named("DEFAULT") Provider defaultTemplateProvider) { + super(locations, images, hardwares, defaultLocation, optionsProvider, defaultTemplateProvider); + } + + protected Hardware automaticHardwareForCpuAndRam(double cores, int ram) { + if (location == null) { + location = defaultLocation.get(); + } + String uri = location.getDescription() + "/machineTypes/custom-" + (int)cores + "-" + ram; + return new HardwareBuilder() + .id(uri) + .ram(ram) + .processor(new Processor((int)cores, 1.0)) + .providerId(uri) + .uri(URI.create(uri)) + .build(); + } + +} diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java index 6f72bee0423..7e7407ebe18 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java @@ -16,27 +16,30 @@ */ package org.jclouds.googlecomputeengine.compute.functions; -import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName; - -import javax.inject.Inject; -import java.net.URI; -import java.util.List; -import java.util.Map; - import com.google.common.base.Function; +import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata.Status; import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.Processor; import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.domain.Location; import org.jclouds.googlecomputeengine.domain.Image; import org.jclouds.googlecomputeengine.domain.Instance; +import javax.inject.Inject; +import java.net.URI; +import java.util.List; +import java.util.Map; + +import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName; + public final class InstanceToNodeMetadata implements Function { private final Map toPortableNodeStatus; @@ -73,13 +76,21 @@ public final class InstanceToNodeMetadata implements Function collectPublicAddresses(Instance input) { } return publicAddressesBuilder.build(); } + + public static boolean isCustomMachineTypeURI(URI machineType) { + return machineType.toString().contains("machineTypes/custom"); + } + + public static Hardware machineTypeURIToCustomHardware(URI machineType) { + String uri = machineType.toString(); + String values = uri.substring(uri.lastIndexOf('/') + 8); + List hardwareValues = Splitter.on('-') + .trimResults() + .splitToList(values); + return new HardwareBuilder() + .id(uri) + .providerId(uri) + .processor(new Processor(Double.parseDouble(hardwareValues.get(0)), 1.0)) + .ram(Integer.parseInt(hardwareValues.get(1))) + .uri(machineType) + .build(); + } } diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java index ca381dbd4d5..d8bd28ed39e 100644 --- a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java @@ -17,6 +17,9 @@ package org.jclouds.googlecomputeengine.compute; import static com.google.common.collect.Iterables.contains; +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.assertj.core.api.Assertions.assertThat; +import static org.jclouds.compute.predicates.NodePredicates.inGroup; import static org.jclouds.util.Strings2.toStringAndClose; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -33,9 +36,9 @@ import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; import org.jclouds.compute.internal.BaseComputeServiceLiveTest; import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.googlecloud.internal.TestProperties; import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions; @@ -95,7 +98,7 @@ public void testCreatePreemptibleNodeWithSsd() throws Exception { assertTrue(instance.scheduling().preemptible()); } finally { - client.destroyNodesMatching(NodePredicates.inGroup(group)); + client.destroyNodesMatching(inGroup(group)); } } /** @@ -152,4 +155,20 @@ protected void checkVolumes(Hardware hardware) { // Hardware profiles might not have volumes. } + @Override + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testCreateNodeWithCustomHardware() throws Exception { + Template template = buildTemplate(templateBuilder() + .hardwareId("automatic:cores=2;ram=4096")); + try { + NodeMetadata node = getOnlyElement(client.createNodesInGroup("custom", 1, template)); + assertThat(node.getHardware().getRam()).isEqualTo(4096); + assertThat(node.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + assertThat(node.getHardware().getId()).isEqualTo(node.getLocation().getDescription() + "/machineTypes/custom-2-4096"); + } + finally { + client.destroyNodesMatching(inGroup("custom")); + } + } + } diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java index dbbedb3f13c..a954e21056f 100644 --- a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java @@ -17,6 +17,7 @@ package org.jclouds.googlecomputeengine.compute; import static com.google.common.base.Objects.firstNonNull; +import static org.assertj.core.api.Assertions.assertThat; import static org.jclouds.compute.domain.OsFamily.COREOS; import static org.jclouds.compute.domain.OsFamily.DEBIAN; import static org.jclouds.compute.domain.OsFamily.WINDOWS; @@ -25,6 +26,7 @@ import static org.testng.Assert.assertTrue; import java.io.IOException; +import java.net.URI; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -76,4 +78,17 @@ protected Set getIso3166Codes() { return ImmutableSet. of(); } + @Override + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareFromId() { + Template template = view.getComputeService().templateBuilder() + .hardwareId("automatic:cores=2;ram=1024").build(); + assertThat(template.getHardware().getId()).isEqualTo(template.getLocation() + .getDescription() + "/machineTypes/custom-2-1024"); + assertThat(template.getHardware().getRam()).isEqualTo(1024); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + assertThat(template.getHardware().getUri()).isEqualTo(URI.create(template.getLocation() + .getDescription() + "/machineTypes/custom-2-1024")); + } + } diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java new file mode 100644 index 00000000000..98b31443fd1 --- /dev/null +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java @@ -0,0 +1,278 @@ +/* + * 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.googlecomputeengine.compute.domain.internal; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Atomics; +import com.google.inject.Provider; +import com.google.inject.util.Providers; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.TemplateBuilderImpl; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.strategy.GetImageStrategy; +import org.jclouds.compute.suppliers.ImageCacheSupplier; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +@Test(groups = "unit", singleThreaded = true, testName = "GoogleComputeEngineTemplateBuilderImplTest") +public class GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest { + private Location provider = new LocationBuilder() + .scope(LocationScope.PROVIDER) + .id("google-compute-engine") + .description("google-compute-engine") + .build(); + + private Location region = new LocationBuilder() + .scope(LocationScope.REGION) + .id("us-east-1") + .description("http://localhost/projects/party/zones/us-east-1") + .parent(provider) + .build(); + + private OperatingSystem os = OperatingSystem.builder() + .name("osName") + .version("osVersion") + .description("osDescription") + .arch("X86_32") + .build(); + + private Image image = new ImageBuilder() + .id("imageId") + .providerId("imageId") + .name("imageName") + .description("imageDescription") + .version("imageVersion") + .operatingSystem(os) + .status(Image.Status.AVAILABLE) + .location(null) + .build(); + + private Hardware hardware = new HardwareBuilder() + .ram(2048) + .processor(new Processor(2, 1)) + .id("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2") + .name("n2-standard-2") + .location(region) + .uri(URI.create("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2")) + .build(); + + private final String errorMessage = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values"; + + @Test + public void testAutoGeneratedHardwareFromIdTest(){ + Supplier> locations = Suppliers.> ofInstance(ImmutableSet.of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + + TemplateBuilderImpl templateBuilder = + new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), + optionsProvider, templateBuilderProvider); + + Hardware hardware = templateBuilder.hardwareId("automatic:cores=2;ram=1024").build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(1024); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getUri()).isEqualTo(URI.create("http://localhost/projects/party/zones/us-east-1/machineTypes/custom-2-1024")); + assertThat(hardware.getId()).isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/custom-2-1024"); + } + + @Test + public void testAutoGeneratedHardwareWithMinCoresAndMinRamDontMatchTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(4096); + templateBuilder.minCores(2); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(4096); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/custom-2-4096"); + } + + @Test + public void testAutoGeneratedHardwareMatchHardwareProfile() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + templateBuilder.minCores(2); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testAutoGeneratedHardwareWithOnlyMinCoresTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(4); + templateBuilder.build().getHardware(); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testAutoGeneratedHardwareWithOnlyMinRamTest() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(4096); + templateBuilder.build().getHardware(); + } + + @Test + public void testAutoGeneratedHardwareWithOnlyMinCoresMatchedHardware() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(2); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()) + .isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2"); + } + + @Test + public void testAutoGeneratedHardwareOnlyRamMatchHardwareProfile() { + Supplier> locations = Suppliers.> ofInstance(ImmutableSet + .of(region)); + Supplier> images = Suppliers.> ofInstance(ImmutableSet.of(image)); + Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of(hardware)); + Provider optionsProvider = createMock(Provider.class); + Provider templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()) + .isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2"); + } + +} diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadataTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadataTest.java index 8fa40b012b8..1621ab310fc 100644 --- a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadataTest.java +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadataTest.java @@ -16,13 +16,6 @@ */ package org.jclouds.googlecomputeengine.compute.functions; -import static com.google.common.collect.Maps.uniqueIndex; -import static org.testng.Assert.assertEquals; - -import java.net.URI; -import java.util.Map; -import java.util.Set; - import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.base.Predicate; @@ -49,6 +42,16 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import static com.google.common.collect.Maps.uniqueIndex; +import static org.assertj.core.api.Assertions.assertThat; +import static org.jclouds.googlecomputeengine.compute.functions.InstanceToNodeMetadata.isCustomMachineTypeURI; +import static org.jclouds.googlecomputeengine.compute.functions.InstanceToNodeMetadata.machineTypeURIToCustomHardware; +import static org.testng.Assert.assertEquals; + @Test(groups = "unit", testName = "InstanceToNodeMetadataTest", singleThreaded = true) // BeforeMethod = singleThreaded public class InstanceToNodeMetadataTest { @@ -199,4 +202,26 @@ public final void testInstanceWithGroupNull() { assertEquals(nodeMetadata.getId(), instance.selfLink().toString()); assertEquals(nodeMetadata.getTags(), ImmutableSet.of("aTag", "Group-port-42")); } + + @Test + public void isCustomMachineTypeTest() { + URI uri = URI.create("https://www.googleapis.com/compute/v1/projects/jclouds-dev/zones/asia-east1-a/machineTypes/custom-1-1024"); + assertThat(isCustomMachineTypeURI(uri)).isTrue(); + + URI uri2 = URI.create("https://www.googleapis.com/compute/v1/projects/jclouds-dev/"); + assertThat(isCustomMachineTypeURI(uri2)).isFalse(); + } + + @Test + public void machineTypeParserTest() { + URI uri = URI.create("https://www.googleapis.com/compute/v1/projects/jclouds-dev/zones/asia-east1-a/machineTypes/custom-1-1024"); + Hardware hardware = machineTypeURIToCustomHardware(uri); + assertThat(hardware.getRam()).isEqualTo(1024); + assertThat(hardware.getProcessors().get(0).getCores()).isEqualTo(1); + assertThat(hardware.getUri()) + .isEqualTo(URI.create("https://www.googleapis.com/compute/v1/projects/jclouds-dev/zones/asia-east1-a/machineTypes/custom-1-1024")); + assertThat(hardware.getId()) + .isEqualTo("https://www.googleapis.com/compute/v1/projects/jclouds-dev/zones/asia-east1-a/machineTypes/custom-1-1024"); + } + }