Repository: incubator-brooklyn Updated Branches: refs/heads/master 06b14d60d -> 88fbe107c
JcloudsLocation: make more testable - allow a custom jclouds ComputeService to be injected, so can stub out things like VM creation and deletion Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/0d5e1ba9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/0d5e1ba9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/0d5e1ba9 Branch: refs/heads/master Commit: 0d5e1ba9050d1a3b934ca68a4bc23a68a7450443 Parents: 8489436 Author: Aled Sage <[email protected]> Authored: Fri Jan 23 11:42:54 2015 +0000 Committer: Aled Sage <[email protected]> Committed: Mon Jan 26 09:17:39 2015 +0000 ---------------------------------------------------------------------- .../jclouds/ComputeServiceRegistry.java | 28 +++ .../jclouds/ComputeServiceRegistryImpl.java | 175 ++++++++++++++ .../location/jclouds/JcloudsLocation.java | 30 ++- .../location/jclouds/JcloudsLocationConfig.java | 6 + .../brooklyn/location/jclouds/JcloudsUtil.java | 186 ++++++--------- .../jclouds/AbstractJcloudsStubbedLiveTest.java | 133 +++++++++++ .../jclouds/DelegatingComputeService.java | 229 +++++++++++++++++++ .../JcloudsHardwareProfilesStubbedLiveTest.java | 78 +++++++ .../JcloudsLocationRebindMachineLiveTest.java | 8 +- .../location/jclouds/JcloudsMinRamLiveTest.java | 59 ----- 10 files changed, 740 insertions(+), 192 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistry.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistry.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistry.java new file mode 100644 index 0000000..519fa01 --- /dev/null +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistry.java @@ -0,0 +1,28 @@ +/* + * 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 brooklyn.location.jclouds; + +import org.jclouds.compute.ComputeService; + +import brooklyn.util.config.ConfigBag; + +public interface ComputeServiceRegistry { + + public ComputeService findComputeService(ConfigBag conf, boolean allowReuse); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java new file mode 100644 index 0000000..a284ea3 --- /dev/null +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java @@ -0,0 +1,175 @@ +/* + * 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 brooklyn.location.jclouds; + +import static brooklyn.util.JavaGroovyEquivalents.groovyTruth; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_AMI_QUERY; +import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_CC_AMI_QUERY; + +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +import org.jclouds.Constants; +import org.jclouds.ContextBuilder; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule; +import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brooklyn.entity.basic.Entities; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.config.ConfigBag; + +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.inject.Module; + +public class ComputeServiceRegistryImpl implements ComputeServiceRegistry, JcloudsLocationConfig { + + private static final Logger LOG = LoggerFactory.getLogger(ComputeServiceRegistryImpl.class); + + public static final ComputeServiceRegistryImpl INSTANCE = new ComputeServiceRegistryImpl(); + + protected ComputeServiceRegistryImpl() { + } + + protected final Map<Map<?,?>,ComputeService> cachedComputeServices = new ConcurrentHashMap<Map<?,?>,ComputeService>(); + + protected final Object createComputeServicesMutex = new Object(); + + @Override + public ComputeService findComputeService(ConfigBag conf, boolean allowReuse) { + String provider = checkNotNull(conf.get(CLOUD_PROVIDER), "provider must not be null"); + String identity = checkNotNull(conf.get(ACCESS_IDENTITY), "identity must not be null"); + String credential = checkNotNull(conf.get(ACCESS_CREDENTIAL), "credential must not be null"); + + Properties properties = new Properties(); + properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, Boolean.toString(true)); + properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, Boolean.toString(true)); + properties.setProperty("jclouds.ssh.max-retries", conf.getStringKey("jclouds.ssh.max-retries") != null ? + conf.getStringKey("jclouds.ssh.max-retries").toString() : "50"); + // Enable aws-ec2 lazy image fetching, if given a specific imageId; otherwise customize for specific owners; or all as a last resort + // See https://issues.apache.org/jira/browse/WHIRR-416 + if ("aws-ec2".equals(provider)) { + // TODO convert AWS-only flags to config keys + if (groovyTruth(conf.get(IMAGE_ID))) { + properties.setProperty(PROPERTY_EC2_AMI_QUERY, ""); + properties.setProperty(PROPERTY_EC2_CC_AMI_QUERY, ""); + } else if (groovyTruth(conf.getStringKey("imageOwner"))) { + properties.setProperty(PROPERTY_EC2_AMI_QUERY, "owner-id="+conf.getStringKey("imageOwner")+";state=available;image-type=machine"); + } else if (groovyTruth(conf.getStringKey("anyOwner"))) { + // set `anyOwner: true` to override the default query (which is restricted to certain owners as per below), + // allowing the AMI query to bind to any machine + // (note however, we sometimes pick defaults in JcloudsLocationFactory); + // (and be careful, this can give a LOT of data back, taking several minutes, + // and requiring extra memory allocated on the command-line) + properties.setProperty(PROPERTY_EC2_AMI_QUERY, "state=available;image-type=machine"); + /* + * by default the following filters are applied: + * Filter.1.Name=owner-id&Filter.1.Value.1=137112412989& + * Filter.1.Value.2=063491364108& + * Filter.1.Value.3=099720109477& + * Filter.1.Value.4=411009282317& + * Filter.2.Name=state&Filter.2.Value.1=available& + * Filter.3.Name=image-type&Filter.3.Value.1=machine& + */ + } + } + + // FIXME Deprecated mechanism, should have a ConfigKey for overrides + Map<String, Object> extra = Maps.filterKeys(conf.getAllConfig(), Predicates.containsPattern("^jclouds\\.")); + if (extra.size() > 0) { + LOG.warn("Jclouds using deprecated property overrides: "+Entities.sanitize(extra)); + } + properties.putAll(extra); + + String endpoint = conf.get(CLOUD_ENDPOINT); + if (!groovyTruth(endpoint)) endpoint = getDeprecatedProperty(conf, Constants.PROPERTY_ENDPOINT); + if (groovyTruth(endpoint)) properties.setProperty(Constants.PROPERTY_ENDPOINT, endpoint); + + Map<?,?> cacheKey = MutableMap.builder() + .putAll(properties) + .put("provider", provider) + .put("identity", identity) + .put("credential", credential) + .putIfNotNull("endpoint", endpoint) + .build() + .asUnmodifiable(); + + if (allowReuse) { + ComputeService result = cachedComputeServices.get(cacheKey); + if (result!=null) { + LOG.trace("jclouds ComputeService cache hit for compute service, for "+Entities.sanitize(properties)); + return result; + } + LOG.debug("jclouds ComputeService cache miss for compute service, creating, for "+Entities.sanitize(properties)); + } + + Iterable<Module> modules = getCommonModules(); + + // Synchronizing to avoid deadlock from sun.reflect.annotation.AnnotationType. + // See https://github.com/brooklyncentral/brooklyn/issues/974 + ComputeServiceContext computeServiceContext; + synchronized (createComputeServicesMutex) { + computeServiceContext = ContextBuilder.newBuilder(provider) + .modules(modules) + .credentials(identity, credential) + .overrides(properties) + .build(ComputeServiceContext.class); + } + final ComputeService computeService = computeServiceContext.getComputeService(); + if (allowReuse) { + synchronized (cachedComputeServices) { + ComputeService result = cachedComputeServices.get(cacheKey); + if (result != null) { + LOG.debug("jclouds ComputeService cache recovery for compute service, for "+Entities.sanitize(cacheKey)); + //keep the old one, discard the new one + computeService.getContext().close(); + return result; + } + LOG.debug("jclouds ComputeService created "+computeService+", adding to cache, for "+Entities.sanitize(properties)); + cachedComputeServices.put(cacheKey, computeService); + } + } + return computeService; + } + + /** returns the jclouds modules we typically install */ + protected ImmutableSet<Module> getCommonModules() { + return ImmutableSet.<Module> of( + new SshjSshClientModule(), + new SLF4JLoggingModule(), + new BouncyCastleCryptoModule()); + } + + protected String getDeprecatedProperty(ConfigBag conf, String key) { + if (conf.containsKey(key)) { + LOG.warn("Jclouds using deprecated brooklyn-jclouds property "+key+": "+Entities.sanitize(conf.getAllConfig())); + return (String) conf.getStringKey(key); + } else { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java index ec9215e..3640117 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java @@ -428,8 +428,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return getComputeService(MutableMap.of()); } public ComputeService getComputeService(Map<?,?> flags) { - return JcloudsUtil.findComputeService((flags==null || flags.isEmpty()) ? getAllConfigBag() : - ConfigBag.newInstanceExtending(getAllConfigBag(), flags)); + ConfigBag conf = (flags==null || flags.isEmpty()) + ? getAllConfigBag() + : ConfigBag.newInstanceExtending(getAllConfigBag(), flags); + return getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(conf, true); } /** @deprecated since 0.7.0 use {@link #listMachines()} */ @Deprecated @@ -552,7 +554,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im JcloudsPortForwarderExtension portForwarder = setup.get(PORT_FORWARDER); if (usePortForwarding) checkNotNull(portForwarder, "portForwarder, when use-port-forwarding enabled"); - final ComputeService computeService = JcloudsUtil.findComputeService(setup); + final ComputeService computeService = getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(setup, true); CloudMachineNamer cloudMachineNamer = getCloudMachineNamer(setup); String groupId = elvis(setup.get(GROUP_ID), cloudMachineNamer.generateNewGroupId()); NodeMetadata node = null; @@ -799,6 +801,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im throw Exceptions.propagate(e); } } + // ------------- constructing the template, etc ------------------------ @@ -1128,7 +1131,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im // TODO use key m1.putStringKey("anyOwner", true); } - ComputeService computeServiceLessRestrictive = JcloudsUtil.findComputeService(m1); + ComputeService computeServiceLessRestrictive = getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(m1, true); Set<? extends Image> imgs = computeServiceLessRestrictive.listImages(); LOG.info(""+imgs.size()+" available images at "+this); for (Image img: imgs) { @@ -1457,7 +1460,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im (rawHostname != null ? rawHostname : "<unspecified>"), getProvider()}); - ComputeService computeService = JcloudsUtil.findComputeService(setup, true); + ComputeService computeService = getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(setup, true); Set<? extends NodeMetadata> candidateNodes = computeService.listNodesDetailsMatching(new Predicate<ComputeMetadata>() { @Override @@ -1589,7 +1592,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im .configureIfNotNull(CLOUD_AVAILABILITY_ZONE_ID, nodeAvailabilityZone) .configureIfNotNull(CLOUD_REGION_ID, nodeRegion) .configure(CALLER_CONTEXT, setup.get(CALLER_CONTEXT)) - .configure(SshMachineLocation.DETECT_MACHINE_DETAILS, setup.get(SshMachineLocation.DETECT_MACHINE_DETAILS))); + .configure(SshMachineLocation.DETECT_MACHINE_DETAILS, setup.get(SshMachineLocation.DETECT_MACHINE_DETAILS)) + .configureIfNotNull(USE_PORT_FORWARDING, setup.get(USE_PORT_FORWARDING)) + .configureIfNotNull(PORT_FORWARDER, setup.get(PORT_FORWARDER)) + .configureIfNotNull(PORT_FORWARDING_MANAGER, setup.get(PORT_FORWARDING_MANAGER))); } else { LOG.warn("Using deprecated JcloudsSshMachineLocation constructor because "+this+" is not managed"); return new JcloudsSshMachineLocation(MutableMap.builder() @@ -1604,6 +1610,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im .put("callerContext", setup.get(CALLER_CONTEXT)) .putIfNotNull(CLOUD_AVAILABILITY_ZONE_ID.getName(), nodeAvailabilityZone) .putIfNotNull(CLOUD_REGION_ID.getName(), nodeRegion) + .put(USE_PORT_FORWARDING, setup.get(USE_PORT_FORWARDING)) + .put(PORT_FORWARDER, setup.get(PORT_FORWARDER)) + .put(PORT_FORWARDING_MANAGER, setup.get(PORT_FORWARDING_MANAGER)) .build(), this, node); @@ -1647,19 +1656,21 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im @Override public void release(SshMachineLocation machine) { String instanceId = vmInstanceIds.remove(machine); - if (!groovyTruth(instanceId)) { + if (instanceId == null) { + LOG.info("Attempted release of unknown machine "+machine+" in "+toString()); throw new IllegalArgumentException("Unknown machine "+machine); } LOG.info("Releasing machine {} in {}, instance id {}", new Object[] {machine, this, instanceId}); removeChild(machine); + try { releaseNode(instanceId); } catch (Exception e) { LOG.error("Problem releasing machine "+machine+" in "+this+", instance id "+instanceId+ "; discarding instance and continuing...", e); - Exceptions.propagate(e); + throw Exceptions.propagate(e); } } @@ -1675,7 +1686,6 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im String instanceId = node.getId(); LOG.info("Releasing node {} in {}, instance id {}", new Object[] {node, this, instanceId}); - ComputeService computeService = null; try { releaseNode(instanceId); } catch (Exception e) { @@ -1687,7 +1697,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected void releaseNode(String instanceId) { ComputeService computeService = null; try { - computeService = JcloudsUtil.findComputeService(getAllConfigBag()); + computeService = getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(getAllConfigBag(), true); computeService.destroyNode(instanceId); } finally { /* http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java index 0346940..4bcebad 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java @@ -230,6 +230,12 @@ public interface JcloudsLocationConfig extends CloudLocationConfig { public static final ConfigKey<String> OS_VERSION_REGEX = ConfigKeys.newStringConfigKey("osVersionRegex", "Regular expression for the OS version to load"); + public static final ConfigKey<ComputeServiceRegistry> COMPUTE_SERVICE_REGISTRY = ConfigKeys.newConfigKey( + ComputeServiceRegistry.class, + "jclouds.computeServiceRegistry", + "Registry/Factory for creating jclouds ComputeService; default is almost always fine, except where tests want to customize behaviour", + ComputeServiceRegistryImpl.INSTANCE); + // TODO // "noDefaultSshKeys" - hints that local ssh keys should not be read as defaults http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java index e707495..3016058 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java @@ -18,10 +18,6 @@ */ package brooklyn.location.jclouds; -import static brooklyn.util.JavaGroovyEquivalents.groovyTruth; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_AMI_QUERY; -import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_CC_AMI_QUERY; import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideLoginCredentials; import static org.jclouds.compute.util.ComputeServiceUtils.execHttpResponse; import static org.jclouds.scriptbuilder.domain.Statements.appendFile; @@ -34,14 +30,11 @@ import java.io.IOException; import java.net.URI; import java.util.List; import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import javax.annotation.Nullable; -import org.jclouds.Constants; import org.jclouds.ContextBuilder; import org.jclouds.aws.ec2.AWSEC2Api; import org.jclouds.blobstore.BlobStoreContext; @@ -73,7 +66,6 @@ import org.slf4j.LoggerFactory; import brooklyn.entity.basic.Entities; import brooklyn.location.jclouds.config.AlwaysRetryOnRenew; import brooklyn.util.collections.MutableList; -import brooklyn.util.collections.MutableMap; import brooklyn.util.config.ConfigBag; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.net.Protocol; @@ -86,7 +78,6 @@ import com.google.common.annotations.Beta; import com.google.common.base.Charsets; 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.base.Strings; import com.google.common.collect.ImmutableMap; @@ -102,17 +93,33 @@ public class JcloudsUtil implements JcloudsLocationConfig { private static final Logger LOG = LoggerFactory.getLogger(JcloudsUtil.class); + /** + * @deprecated since 0.7; see {@link BashCommands} + */ + @Deprecated public static String APT_INSTALL = "apt-get install -f -y -qq --force-yes"; + /** + * @deprecated since 0.7; see {@link BashCommands} + */ + @Deprecated public static String installAfterUpdatingIfNotPresent(String cmd) { String aptInstallCmd = APT_INSTALL + " " + cmd; return String.format("which %s || (%s || (apt-get update && %s))", cmd, aptInstallCmd, aptInstallCmd); } + /** + * @deprecated since 0.7 + */ + @Deprecated public static Predicate<NodeMetadata> predicateMatchingById(final NodeMetadata node) { return predicateMatchingById(node.getId()); } + /** + * @deprecated since 0.7 + */ + @Deprecated public static Predicate<NodeMetadata> predicateMatchingById(final String id) { Predicate<NodeMetadata> nodePredicate = new Predicate<NodeMetadata>() { @Override public boolean apply(NodeMetadata arg0) { @@ -125,6 +132,10 @@ public class JcloudsUtil implements JcloudsLocationConfig { return nodePredicate; } + /** + * @deprecated since 0.7; see {@link IptablesCommands} + */ + @Deprecated public static Statement authorizePortInIpTables(int port) { // TODO gogrid rules only allow ports 22, 3389, 80 and 443. // the first rule will be ignored, so we have to apply this @@ -138,7 +149,10 @@ public class JcloudsUtil implements JcloudsLocationConfig { /** * @throws RunScriptOnNodesException * @throws IllegalStateException If do not find exactly one matching node + * + * @deprecated since 0.7 */ + @Deprecated public static ExecResponse runScriptOnNode(ComputeService computeService, NodeMetadata node, Statement statement, String scriptName) throws RunScriptOnNodesException { // TODO Includes workaround for NodeMetadata's equals/hashcode method being wrong. @@ -209,110 +223,28 @@ public class JcloudsUtil implements JcloudsLocationConfig { throw new IllegalArgumentException("don't know how to handle" + os.toString()); } - static Map<Map<?,?>,ComputeService> cachedComputeServices = new ConcurrentHashMap<Map<?,?>,ComputeService> (); - - private static final Object createComputeServicesMutex = new Object(); - + /** + * @deprecated since 0.7; see {@link ComputeServiceRegistry#findComputeService(ConfigBag, boolean)} + */ + @Deprecated public static ComputeService findComputeService(ConfigBag conf) { - return findComputeService(conf, true); + return ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, true); } + + /** + * @deprecated since 0.7; see {@link ComputeServiceRegistry#findComputeService(ConfigBag, boolean)} + */ + @Deprecated public static ComputeService findComputeService(ConfigBag conf, boolean allowReuse) { - String provider = checkNotNull(conf.get(CLOUD_PROVIDER), "provider must not be null"); - String identity = checkNotNull(conf.get(ACCESS_IDENTITY), "identity must not be null"); - String credential = checkNotNull(conf.get(ACCESS_CREDENTIAL), "credential must not be null"); - - Properties properties = new Properties(); - properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, Boolean.toString(true)); - properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, Boolean.toString(true)); - properties.setProperty("jclouds.ssh.max-retries", conf.getStringKey("jclouds.ssh.max-retries") != null ? - conf.getStringKey("jclouds.ssh.max-retries").toString() : "50"); - // Enable aws-ec2 lazy image fetching, if given a specific imageId; otherwise customize for specific owners; or all as a last resort - // See https://issues.apache.org/jira/browse/WHIRR-416 - if ("aws-ec2".equals(provider)) { - // TODO convert AWS-only flags to config keys - if (groovyTruth(conf.get(IMAGE_ID))) { - properties.setProperty(PROPERTY_EC2_AMI_QUERY, ""); - properties.setProperty(PROPERTY_EC2_CC_AMI_QUERY, ""); - } else if (groovyTruth(conf.getStringKey("imageOwner"))) { - properties.setProperty(PROPERTY_EC2_AMI_QUERY, "owner-id="+conf.getStringKey("imageOwner")+";state=available;image-type=machine"); - } else if (groovyTruth(conf.getStringKey("anyOwner"))) { - // set `anyOwner: true` to override the default query (which is restricted to certain owners as per below), - // allowing the AMI query to bind to any machine - // (note however, we sometimes pick defaults in JcloudsLocationFactory); - // (and be careful, this can give a LOT of data back, taking several minutes, - // and requiring extra memory allocated on the command-line) - properties.setProperty(PROPERTY_EC2_AMI_QUERY, "state=available;image-type=machine"); - /* - * by default the following filters are applied: - * Filter.1.Name=owner-id&Filter.1.Value.1=137112412989& - * Filter.1.Value.2=063491364108& - * Filter.1.Value.3=099720109477& - * Filter.1.Value.4=411009282317& - * Filter.2.Name=state&Filter.2.Value.1=available& - * Filter.3.Name=image-type&Filter.3.Value.1=machine& - */ - } - } - - // FIXME Deprecated mechanism, should have a ConfigKey for overrides - Map<String, Object> extra = Maps.filterKeys(conf.getAllConfig(), Predicates.containsPattern("^jclouds\\.")); - if (extra.size() > 0) { - LOG.warn("Jclouds using deprecated property overrides: "+Entities.sanitize(extra)); - } - properties.putAll(extra); - - String endpoint = conf.get(CLOUD_ENDPOINT); - if (!groovyTruth(endpoint)) endpoint = getDeprecatedProperty(conf, Constants.PROPERTY_ENDPOINT); - if (groovyTruth(endpoint)) properties.setProperty(Constants.PROPERTY_ENDPOINT, endpoint); - - Map<?,?> cacheKey = MutableMap.builder() - .putAll(properties) - .put("provider", provider) - .put("identity", identity) - .put("credential", credential) - .putIfNotNull("endpoint", endpoint) - .build() - .asUnmodifiable(); - - if (allowReuse) { - ComputeService result = cachedComputeServices.get(cacheKey); - if (result!=null) { - LOG.trace("jclouds ComputeService cache hit for compute service, for "+Entities.sanitize(properties)); - return result; - } - LOG.debug("jclouds ComputeService cache miss for compute service, creating, for "+Entities.sanitize(properties)); - } - - Iterable<Module> modules = getCommonModules(); - - // Synchronizing to avoid deadlock from sun.reflect.annotation.AnnotationType. - // See https://github.com/brooklyncentral/brooklyn/issues/974 - ComputeServiceContext computeServiceContext; - synchronized (createComputeServicesMutex) { - computeServiceContext = ContextBuilder.newBuilder(provider) - .modules(modules) - .credentials(identity, credential) - .overrides(properties) - .build(ComputeServiceContext.class); - } - final ComputeService computeService = computeServiceContext.getComputeService(); - if (allowReuse) { - synchronized (cachedComputeServices) { - ComputeService result = cachedComputeServices.get(cacheKey); - if (result != null) { - LOG.debug("jclouds ComputeService cache recovery for compute service, for "+Entities.sanitize(cacheKey)); - //keep the old one, discard the new one - computeService.getContext().close(); - return result; - } - LOG.debug("jclouds ComputeService created "+computeService+", adding to cache, for "+Entities.sanitize(properties)); - cachedComputeServices.put(cacheKey, computeService); - } - } - return computeService; - } + return ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, allowReuse); + } - /** returns the jclouds modules we typically install */ + /** + * Returns the jclouds modules we typically install + * + * @deprecated since 0.7; see {@link ComputeServiceRegistry} + */ + @Deprecated public static ImmutableSet<Module> getCommonModules() { return ImmutableSet.<Module> of( new SshjSshClientModule(), @@ -349,7 +281,11 @@ public class JcloudsUtil implements JcloudsLocationConfig { return context; } - protected static String getDeprecatedProperty(ConfigBag conf, String key) { + /** + * @deprecated since 0.7 + */ + @Deprecated + protected static String getDeprecatedProperty(ConfigBag conf, String key) { if (conf.containsKey(key)) { LOG.warn("Jclouds using deprecated brooklyn-jclouds property "+key+": "+Entities.sanitize(conf.getAllConfig())); return (String) conf.getStringKey(key); @@ -358,17 +294,25 @@ public class JcloudsUtil implements JcloudsLocationConfig { } } + /** + * @deprecated since 0.7 + */ + @Deprecated // Do this so that if there's a problem with our USERNAME's ssh key, we can still get in to check - // TODO Once we're really confident there are not going to be regular problems, then delete this - public static Statement addAuthorizedKeysToRoot(File publicKeyFile) throws IOException { - String publicKey = Files.toString(publicKeyFile, Charsets.UTF_8); - return addAuthorizedKeysToRoot(publicKey); - } + // TODO Once we're really confident there are not going to be regular problems, then delete this + public static Statement addAuthorizedKeysToRoot(File publicKeyFile) throws IOException { + String publicKey = Files.toString(publicKeyFile, Charsets.UTF_8); + return addAuthorizedKeysToRoot(publicKey); + } - public static Statement addAuthorizedKeysToRoot(String publicKey) { - return newStatementList( - appendFile("/root/.ssh/authorized_keys", Splitter.on('\n').split(publicKey)), - interpret("chmod 600 /root/.ssh/authorized_keys")); + /** + * @deprecated since 0.7 + */ + @Deprecated + public static Statement addAuthorizedKeysToRoot(String publicKey) { + return newStatementList( + appendFile("/root/.ssh/authorized_keys", Splitter.on('\n').split(publicKey)), + interpret("chmod 600 /root/.ssh/authorized_keys")); } public static String getFirstReachableAddress(ComputeServiceContext context, NodeMetadata node) { @@ -471,6 +415,10 @@ public class JcloudsUtil implements JcloudsLocationConfig { } } + /** + * @deprecated since 0.7 + */ + @Deprecated public static void mapSecurityGroupRuleToIpTables(ComputeService computeService, NodeMetadata node, LoginCredentials credentials, String networkInterface, Iterable<Integer> ports) { for (Integer port : ports) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java new file mode 100644 index 0000000..3b8a4f4 --- /dev/null +++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java @@ -0,0 +1,133 @@ +/* + * 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 brooklyn.location.jclouds; + +import java.util.List; +import java.util.Set; + +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.RunNodesException; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadata.Status; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.LoginCredentials; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.BeforeMethod; + +import brooklyn.location.jclouds.ComputeServiceRegistry; +import brooklyn.location.jclouds.ComputeServiceRegistryImpl; +import brooklyn.location.jclouds.JcloudsLocation; +import brooklyn.location.jclouds.JcloudsLocationConfig; +import brooklyn.util.config.ConfigBag; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +/** + * The VM creation is stubbed out, but it still requires live access (i.e. real account credentials) + * to generate the template etc. + * + * We supply a ComputeServiceRegistry that delegates to the real instance for everything except + * VM creation and deletion. For those operations, it delegates to a NodeCreator that + * returns a dummy NodeMetadata, recording all calls made to it. + */ +public abstract class AbstractJcloudsStubbedLiveTest extends AbstractJcloudsLiveTest { + + @SuppressWarnings("unused") + private static final Logger LOG = LoggerFactory.getLogger(AbstractJcloudsStubbedLiveTest.class); + + public static final String LOCATION_SPEC = "jclouds:" + SOFTLAYER_PROVIDER + ":" + SOFTLAYER_AMS01_REGION_NAME; + + public static abstract class NodeCreator { + public final List<NodeMetadata> created = Lists.newCopyOnWriteArrayList(); + public final List<String> destroyed = Lists.newCopyOnWriteArrayList(); + + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException { + Set<NodeMetadata> result = Sets.newLinkedHashSet(); + for (int i = 0; i < count; i++) { + NodeMetadata node = newNode(group, template); + created.add(node); + result.add(node); + } + return result; + } + public void destroyNode(String id) { + destroyed.add(id); + } + protected abstract NodeMetadata newNode(String group, Template template); + } + + public static class StubbedComputeService extends DelegatingComputeService { + private final NodeCreator nodeCreator; + + public StubbedComputeService(ComputeService delegate, NodeCreator nodeCreator) { + super(delegate); + this.nodeCreator = nodeCreator; + } + @Override + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException { + return nodeCreator.createNodesInGroup(group, count, template); + } + @Override + public void destroyNode(String id) { + nodeCreator.destroyNode(id); + } + @Override + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count) { + throw new UnsupportedOperationException(); + } + @Override + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) { + throw new UnsupportedOperationException(); + } + @Override + public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { + throw new UnsupportedOperationException(); + } + } + + protected NodeCreator nodeCreator; + + @BeforeMethod(alwaysRun=true) + @Override + public void setUp() throws Exception { + super.setUp(); + nodeCreator = newNodeCreator(); + ComputeServiceRegistry computeServiceRegistry = new ComputeServiceRegistry() { + @Override + public ComputeService findComputeService(ConfigBag conf, boolean allowReuse) { + ComputeService delegate = ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, allowReuse); + return new StubbedComputeService(delegate, nodeCreator); + } + }; + jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve( + LOCATION_SPEC, + ImmutableMap.of( + JcloudsLocationConfig.COMPUTE_SERVICE_REGISTRY, computeServiceRegistry, + JcloudsLocationConfig.WAIT_FOR_SSHABLE, "false")); + } + + protected abstract NodeCreator newNodeCreator(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java new file mode 100644 index 0000000..62f621e --- /dev/null +++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java @@ -0,0 +1,229 @@ +/* + * 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 brooklyn.location.jclouds; + +import java.util.Map; +import java.util.Set; + +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.RunNodesException; +import org.jclouds.compute.RunScriptOnNodesException; +import org.jclouds.compute.domain.ComputeMetadata; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.extensions.SecurityGroupExtension; +import org.jclouds.compute.options.RunScriptOptions; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.Location; +import org.jclouds.scriptbuilder.domain.Statement; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.util.concurrent.ListenableFuture; + +public class DelegatingComputeService implements ComputeService { + + private final ComputeService delegate; + + public DelegatingComputeService(ComputeService delegate) { + this.delegate = delegate; + } + + @Override + public ComputeServiceContext getContext() { + return delegate.getContext(); + } + + @Override + public TemplateBuilder templateBuilder() { + return delegate.templateBuilder(); + } + + @Override + public TemplateOptions templateOptions() { + return delegate.templateOptions(); + } + + @Override + public Set<? extends Hardware> listHardwareProfiles() { + return delegate.listHardwareProfiles(); + } + + @Override + public Set<? extends Image> listImages() { + return delegate.listImages(); + } + + @Override + public Image getImage(String id) { + return delegate.getImage(id); + } + + @Override + public Set<? extends ComputeMetadata> listNodes() { + return delegate.listNodes(); + } + + @Override + public Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) { + return delegate.listNodesByIds(ids); + } + + @Override + public Set<? extends Location> listAssignableLocations() { + return delegate.listAssignableLocations(); + } + + @Override + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) throws RunNodesException { + return delegate.createNodesInGroup(group, count, template); + } + + @Override + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) + throws RunNodesException { + return delegate.createNodesInGroup(group, count, templateOptions); + } + + @Override + public Set<? extends NodeMetadata> createNodesInGroup(String group, int count) throws RunNodesException { + return delegate.createNodesInGroup(group, count); + } + + @Override + public void resumeNode(String id) { + delegate.resumeNode(id); + } + + @Override + public Set<? extends NodeMetadata> resumeNodesMatching(Predicate<NodeMetadata> filter) { + return delegate.resumeNodesMatching(filter); + } + + @Override + public void suspendNode(String id) { + delegate.suspendNode(id); + } + + @Override + public Set<? extends NodeMetadata> suspendNodesMatching(Predicate<NodeMetadata> filter) { + return delegate.suspendNodesMatching(filter); + } + + @Override + public void destroyNode(String id) { + delegate.destroyNode(id); + } + + @Override + public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { + return delegate.destroyNodesMatching(filter); + } + + @Override + public void rebootNode(String id) { + delegate.rebootNode(id); + } + + @Override + public Set<? extends NodeMetadata> rebootNodesMatching(Predicate<NodeMetadata> filter) { + return delegate.rebootNodesMatching(filter); + } + + @Override + public NodeMetadata getNodeMetadata(String id) { + return delegate.getNodeMetadata(id); + } + + @Override + public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) { + return delegate.listNodesDetailsMatching(filter); + } + + @Override + public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript) + throws RunScriptOnNodesException { + return delegate.runScriptOnNodesMatching(filter, runScript); + } + + @Override + public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript) + throws RunScriptOnNodesException { + return delegate.runScriptOnNodesMatching(filter, runScript); + } + + @Override + public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, + String runScript, RunScriptOptions options) throws RunScriptOnNodesException { + return delegate.runScriptOnNodesMatching(filter, runScript, options); + } + + @Override + public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, + Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException { + return delegate.runScriptOnNodesMatching(filter, runScript, options); + } + + @Override + public ExecResponse runScriptOnNode(String id, Statement runScript, RunScriptOptions options) { + return delegate.runScriptOnNode(id, runScript, options); + } + + @Override + public ListenableFuture<ExecResponse> submitScriptOnNode(String id, String runScript, RunScriptOptions options) { + return delegate.submitScriptOnNode(id, runScript, options); + } + + @Override + public ListenableFuture<ExecResponse> submitScriptOnNode(String id, Statement runScript, RunScriptOptions options) { + return delegate.submitScriptOnNode(id, runScript, options); + } + + @Override + public ExecResponse runScriptOnNode(String id, Statement runScript) { + return delegate.runScriptOnNode(id, runScript); + } + + @Override + public ExecResponse runScriptOnNode(String id, String runScript, RunScriptOptions options) { + return delegate.runScriptOnNode(id, runScript, options); + } + + @Override + public ExecResponse runScriptOnNode(String id, String runScript) { + return delegate.runScriptOnNode(id, runScript); + } + + @Override + public Optional<ImageExtension> getImageExtension() { + return delegate.getImageExtension(); + } + + @Override + public Optional<SecurityGroupExtension> getSecurityGroupExtension() { + return delegate.getSecurityGroupExtension(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java new file mode 100644 index 0000000..8d7f55e --- /dev/null +++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package brooklyn.location.jclouds; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadata.Status; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.Template; +import org.jclouds.domain.LoginCredentials; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import brooklyn.util.collections.MutableMap; + +import com.google.common.collect.ImmutableList; + +public class JcloudsHardwareProfilesStubbedLiveTest extends AbstractJcloudsStubbedLiveTest { + + @SuppressWarnings("unused") + private static final Logger log = LoggerFactory.getLogger(JcloudsHardwareProfilesStubbedLiveTest.class); + + private Template template; + + @Override + protected NodeCreator newNodeCreator() { + return new NodeCreator() { + @Override protected NodeMetadata newNode(String group, Template template) { + JcloudsHardwareProfilesStubbedLiveTest.this.template = template; + + NodeMetadata result = new NodeMetadataBuilder() + .id("myid") + .credentials(LoginCredentials.builder().identity("myuser").credential("mypassword").build()) + .loginPort(22) + .status(Status.RUNNING) + .publicAddresses(ImmutableList.of("173.194.32.123")) + .privateAddresses(ImmutableList.of("172.168.10.11")) + .build(); + return result; + } + }; + } + + @Test(groups={"Live", "Live-sanity"}) + public void testJcloudsCreateWithHardwareProfiles() throws Exception { + obtainMachine(MutableMap.of(JcloudsLocationConfig.MIN_RAM, "4096")); + assertTrue(template.getHardware().getRam() >= 4096, "template="+template); + + obtainMachine(MutableMap.of(JcloudsLocationConfig.MIN_CORES, "4")); + assertTrue(template.getHardware().getProcessors().get(0).getCores() >= 4, "template="+template); + + obtainMachine(MutableMap.of(JcloudsLocationConfig.MIN_DISK, "51")); + assertTrue(template.getHardware().getVolumes().get(0).getSize() >= 51, "template="+template); + + String hardwareId = "cpu=1,memory=6144,disk=25,type=LOCAL"; + obtainMachine(MutableMap.of(JcloudsLocationConfig.HARDWARE_ID, hardwareId)); + assertEquals(template.getHardware().getId(), hardwareId, "template="+template); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java index 7ec58cf..d2f1b84 100644 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java +++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java @@ -50,12 +50,12 @@ public class JcloudsLocationRebindMachineLiveTest extends AbstractJcloudsLiveTes jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve(AWS_EC2_PROVIDER+":"+AWS_EC2_EUWEST_REGION_NAME); } - @Test(groups = { "Live" }) + @Test(groups = { "Live", "Live-sanity" }) public void testRebindWithIncorrectId() throws Exception { try { jcloudsLocation.rebindMachine(ImmutableMap.of("id", "incorrectid", "hostname", "myhostname", "user", "myusername")); } catch (IllegalArgumentException e) { - if (e.getMessage().contains("Invalid id")) { + if (e.getMessage().contains("node not found")) { // success } else { throw e; @@ -90,7 +90,7 @@ public class JcloudsLocationRebindMachineLiveTest extends AbstractJcloudsLiveTes // Confirm can release the re-bound machine via the new jclouds location loc2.release(machine2); - assertFalse(machine2.isSshable()); + assertFalse(machine.isSshable()); assertEquals(ImmutableSet.copyOf(loc2.getChildren()), Collections.emptySet()); } @@ -118,7 +118,7 @@ public class JcloudsLocationRebindMachineLiveTest extends AbstractJcloudsLiveTes // Confirm can release the re-bound machine via the new jclouds location loc2.release(machine2); - assertFalse(machine2.isSshable()); + assertFalse(machine.isSshable()); assertEquals(ImmutableSet.copyOf(loc2.getChildren()), Collections.emptySet()); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0d5e1ba9/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMinRamLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMinRamLiveTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMinRamLiveTest.java deleted file mode 100644 index ee072f2..0000000 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMinRamLiveTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.location.jclouds; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.Test; - -import brooklyn.util.collections.MutableMap; - -import com.google.common.collect.ImmutableMap; - -public class JcloudsMinRamLiveTest extends AbstractJcloudsLiveTest { - - private static final Logger log = LoggerFactory.getLogger(JcloudsMinRamLiveTest.class); - - private static final String LOCATION_SPEC = AWS_EC2_PROVIDER + ":" + AWS_EC2_USEAST_REGION_NAME; - - @Test(groups="Live") - public void testJcloudsCreateWithMinRam() throws Exception { - jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve(LOCATION_SPEC); - jcloudsLocation.configure(MutableMap.of("minRam", "4096")); - - JcloudsSshMachineLocation m1 = obtainMachine(ImmutableMap.<String, Object>of()); - - log.info("GOT "+m1); - - jcloudsLocation.release(m1); - } - -// @Test(groups="Live") -// public void testJcloudsCreateNamedJungleBig() throws Exception { -// @SuppressWarnings("unchecked") -// MachineProvisioningLocation<SshMachineLocation> l = (MachineProvisioningLocation<SshMachineLocation>) new LocationRegistry().resolve("named:jungle-big"); -// -// SshMachineLocation m1 = l.obtain(MutableMap.<String,String>of()); -// -// log.info("GOT "+m1); -// -// l.release(m1); -// } - -}
