http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java index 3dba382..fe77f5e 100644 --- a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java +++ b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java @@ -33,12 +33,11 @@ import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import brooklyn.entity.BrooklynAppLiveTestSupport; -import brooklyn.location.Location; -import brooklyn.location.LocationSpec; -import brooklyn.location.MachineProvisioningLocation; -import brooklyn.location.basic.LocalhostMachineProvisioningLocation; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.policy.os.CreateUserPolicy; +import org.apache.brooklyn.location.Location; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.MachineProvisioningLocation; +import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.basic.SshMachineLocation; import brooklyn.util.internal.ssh.SshTool; import brooklyn.util.text.Identifiers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java index a89e089..4184163 100644 --- a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java +++ b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java @@ -37,9 +37,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import brooklyn.entity.BrooklynAppUnitTestSupport; -import brooklyn.location.LocationSpec; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.policy.os.CreateUserPolicy; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.basic.SshMachineLocation; import brooklyn.util.internal.ssh.SshTool; import com.google.common.collect.ImmutableList; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java new file mode 100644 index 0000000..b5f4dab --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java @@ -0,0 +1,158 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.util.List; +import java.util.Map; + +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.exceptions.CompoundRuntimeException; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; + +public class AbstractJcloudsLiveTest { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractJcloudsLiveTest.class); + + public static final String BROOKLYN_PROPERTIES_PREFIX = "brooklyn.location.jclouds."; + public static final String BROOKLYN_PROPERTIES_LEGACY_PREFIX = "brooklyn.jclouds."; + + public static final String AWS_EC2_PROVIDER = "aws-ec2"; + public static final String AWS_EC2_MICRO_HARDWARE_ID = "t1.micro"; + public static final String AWS_EC2_SMALL_HARDWARE_ID = "m1.small"; + public static final String AWS_EC2_EUWEST_REGION_NAME = "eu-west-1"; + public static final String AWS_EC2_USEAST_REGION_NAME = "us-east-1"; + + public static final String RACKSPACE_PROVIDER = "rackspace-cloudservers-uk"; + + public static final String SOFTLAYER_PROVIDER = "softlayer"; + public static final String SOFTLAYER_AMS01_REGION_NAME = "ams01"; + + protected BrooklynProperties brooklynProperties; + protected LocalManagementContext managementContext; + + protected List<JcloudsSshMachineLocation> machines; + protected JcloudsLocation jcloudsLocation; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + machines = Lists.newCopyOnWriteArrayList(); + managementContext = newManagementContext(); + + // Don't let any defaults from brooklyn.properties (except credentials) interfere with test + brooklynProperties = managementContext.getBrooklynProperties(); + stripBrooklynProperties(brooklynProperties); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + List<Exception> exceptions = Lists.newArrayList(); + try { + if (machines != null) { + for (JcloudsSshMachineLocation machine : machines) { + try { + releaseMachine(machine); + } catch (Exception e) { + LOG.warn("Error releasing machine "+machine+"; continuing...", e); + exceptions.add(e); + } + } + machines.clear(); + } + } finally { + try { + if (managementContext != null) Entities.destroyAll(managementContext); + } catch (Exception e) { + LOG.warn("Error destroying management context", e); + exceptions.add(e); + } + } + + // TODO Debate about whether to: + // - use destroyAllCatching (i.e. not propagating exception) + // Benefit is that other tests in class will subsequently be run, rather than bailing out. + // - propagate exceptions from tearDown + // Benefit is that we don't hide errors; release(...) etc should not be throwing exceptions. + if (exceptions.size() > 0) { + throw new CompoundRuntimeException("Error in tearDown of "+getClass(), exceptions); + } + } + + protected LocalManagementContext newManagementContext() { + // loads properties, by default, but not OSGi or anything else + return LocalManagementContextForTests.builder(true).useDefaultProperties().build(); + } + + protected void stripBrooklynProperties(BrooklynProperties props) { + // remove all location properties except for identity and credential + // (so key, scripts, etc settings don't interfere with tests) + for (String key : ImmutableSet.copyOf(props.asMapWithStringKeys().keySet())) { + if (key.startsWith(BROOKLYN_PROPERTIES_PREFIX) && !(key.endsWith("identity") || key.endsWith("credential"))) { + props.remove(key); + } + if (key.startsWith(BROOKLYN_PROPERTIES_LEGACY_PREFIX) && !(key.endsWith("identity") || key.endsWith("credential"))) { + props.remove(key); + } + + // Also removes scriptHeader (e.g. if doing `. ~/.bashrc` and `. ~/.profile`, then that can cause "stdin: is not a tty") + if (key.startsWith("brooklyn.ssh")) { + props.remove(key); + } + } + } + + protected void assertSshable(SshMachineLocation machine) { + int result = machine.execScript("simplecommand", ImmutableList.of("true")); + assertEquals(result, 0); + } + + // Use this utility method to ensure machines are released on tearDown + protected JcloudsSshMachineLocation obtainMachine(Map<?, ?> conf) throws Exception { + assertNotNull(jcloudsLocation); + JcloudsSshMachineLocation result = (JcloudsSshMachineLocation)jcloudsLocation.obtain(conf); + machines.add(checkNotNull(result, "result")); + return result; + } + + protected JcloudsSshMachineLocation obtainMachine() throws Exception { + return obtainMachine(ImmutableMap.of()); + } + + protected void releaseMachine(JcloudsSshMachineLocation machine) { + assertNotNull(jcloudsLocation); + machines.remove(machine); + jcloudsLocation.release(machine); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java new file mode 100644 index 0000000..9c70305 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java @@ -0,0 +1,125 @@ +/* + * 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.apache.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.Template; +import org.jclouds.compute.options.TemplateOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.BeforeMethod; + +import brooklyn.util.config.ConfigBag; + +import com.google.common.base.Predicate; +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/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java new file mode 100644 index 0000000..acf838e --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java @@ -0,0 +1,188 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import java.util.Collections; +import java.util.Map; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.location.LocationSpec; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Template; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.reflect.TypeToken; + +import brooklyn.config.BrooklynProperties; +import brooklyn.config.ConfigKey; +import brooklyn.entity.basic.ConfigKeys; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.config.ConfigBag; +import brooklyn.util.exceptions.CompoundRuntimeException; +import brooklyn.util.exceptions.Exceptions; + +public class BailOutJcloudsLocation extends JcloudsLocation { + + // Don't care which image; not actually provisioning + private static final String US_EAST_IMAGE_ID = "us-east-1/ami-7d7bfc14"; + public static final RuntimeException BAIL_OUT_FOR_TESTING = new RuntimeException("early termination for test"); + + public static final ConfigKey<Function<ConfigBag, Void>> BUILD_TEMPLATE_INTERCEPTOR = ConfigKeys.newConfigKey( + new TypeToken<Function<ConfigBag, Void>>() {}, + "buildtemplateinterceptor"); + + public static final ConfigKey<Boolean> BUILD_TEMPLATE = ConfigKeys.newBooleanConfigKey( + "buildtemplate"); + + private static final long serialVersionUID = -3373789512935057842L; + + ConfigBag lastConfigBag; + Template template; + + public BailOutJcloudsLocation() { + super(); + } + + public BailOutJcloudsLocation(Map<?, ?> conf) { + super(conf); + } + + @Override + public Template buildTemplate(ComputeService computeService, ConfigBag config) { + lastConfigBag = config; + if (getConfig(BUILD_TEMPLATE_INTERCEPTOR) != null) { + getConfig(BUILD_TEMPLATE_INTERCEPTOR).apply(config); + } + if (Boolean.TRUE.equals(getConfig(BUILD_TEMPLATE))) { + template = super.buildTemplate(computeService, config); + } + throw BAIL_OUT_FOR_TESTING; + } + + public Template getTemplate() { + return template; + } + + public void tryObtain() { + tryObtain(Collections.emptyMap()); + } + + public void tryObtain(Map<?, ?> flags) { + tryObtainAndCheck(flags, Predicates.alwaysTrue()); + } + + public void tryObtainAndCheck(Map<?, ?> flags, Predicate<? super ConfigBag> test) { + try { + obtain(flags); + } catch (Exception e) { + if (e == BAIL_OUT_FOR_TESTING || e.getCause() == BAIL_OUT_FOR_TESTING + || (e instanceof CompoundRuntimeException && ((CompoundRuntimeException) e).getAllCauses().contains(BAIL_OUT_FOR_TESTING))) { + test.apply(lastConfigBag); + } else { + throw Exceptions.propagate(e); + } + } + } + + @Override + @VisibleForTesting + public UserCreation createUserStatements(@Nullable Image image, ConfigBag config) { + return super.createUserStatements(image, config); + } + + + public static BailOutJcloudsLocation newBailOutJcloudsLocation(ManagementContext mgmt) { + return newBailOutJcloudsLocation(mgmt, Collections.<ConfigKey<?>, Object>emptyMap()); + } + + public static BailOutJcloudsLocation newBailOutJcloudsLocation(ManagementContext mgmt, Map<ConfigKey<?>, ?> config) { + Map<ConfigKey<?>, ?> allConfig = MutableMap.<ConfigKey<?>, Object>builder() + .put(IMAGE_ID, "bogus") + .put(CLOUD_PROVIDER, "aws-ec2") + .put(ACCESS_IDENTITY, "bogus") + .put(CLOUD_REGION_ID, "bogus") + .put(ACCESS_CREDENTIAL, "bogus") + .put(USER, "fred") + .put(MIN_RAM, 16) + .put(JcloudsLocation.MACHINE_CREATE_ATTEMPTS, 1) + .putAll(config) + .build(); + return mgmt.getLocationManager().createLocation( + LocationSpec.create(BailOutJcloudsLocation.class).configure(allConfig)); + } + + + // todo better name + + /** As {@link BailOutJcloudsLocation}, counting the number of {@link #buildTemplate} calls. */ + public static class CountingBailOutJcloudsLocation extends BailOutJcloudsLocation { + private static final long serialVersionUID = 2433684033045735773L; + int buildTemplateCount = 0; + @Override + public Template buildTemplate(ComputeService computeService, ConfigBag config) { + buildTemplateCount++; + return super.buildTemplate(computeService, config); + } + } + + public static CountingBailOutJcloudsLocation newCountingBailOutJcloudsLocation(ManagementContext mgmt, Map flags) { + LocationSpec<CountingBailOutJcloudsLocation> spec = LocationSpec.create(CountingBailOutJcloudsLocation.class) + .configure(flags); + return mgmt.getLocationManager().createLocation(spec); + } + + /** @see #newBailOutJcloudsLocationForLiveTest(LocalManagementContext, Map)} */ + public static BailOutJcloudsLocation newBailOutJcloudsLocationForLiveTest(LocalManagementContext mgmt) { + return newBailOutJcloudsLocationForLiveTest(mgmt, Collections.<ConfigKey<?>, Object>emptyMap()); + } + + /** + * Takes identity and access credential from management context's Brooklyn properties and sets + * inbound ports to [22, 80, 9999]. + */ + public static BailOutJcloudsLocation newBailOutJcloudsLocationForLiveTest(LocalManagementContext mgmt, Map<ConfigKey<?>, ?> config) { + BrooklynProperties brooklynProperties = mgmt.getBrooklynProperties(); + String identity = (String) brooklynProperties.get("brooklyn.location.jclouds.aws-ec2.identity"); + if (identity == null) identity = (String) brooklynProperties.get("brooklyn.jclouds.aws-ec2.identity"); + String credential = (String) brooklynProperties.get("brooklyn.location.jclouds.aws-ec2.credential"); + if (credential == null) credential = (String) brooklynProperties.get("brooklyn.jclouds.aws-ec2.credential"); + + Map<ConfigKey<?>, ?> allConfig = MutableMap.<ConfigKey<?>, Object>builder() + .put(CLOUD_PROVIDER, AbstractJcloudsLiveTest.AWS_EC2_PROVIDER) + .put(CLOUD_REGION_ID, AbstractJcloudsLiveTest.AWS_EC2_USEAST_REGION_NAME) + .put(IMAGE_ID, US_EAST_IMAGE_ID) // so Brooklyn does not attempt to load all EC2 images + .put(ACCESS_IDENTITY, identity) + .put(ACCESS_CREDENTIAL, credential) + .put(INBOUND_PORTS, "[22, 80, 9999]") + .put(BUILD_TEMPLATE, true) + .putAll(config) + .build(); + + return newBailOutJcloudsLocation(mgmt, allConfig); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java new file mode 100644 index 0000000..3fda145 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java @@ -0,0 +1,103 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import org.apache.brooklyn.location.jclouds.pool.MachineSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.location.jclouds.pool.MachinePoolPredicates; +import org.apache.brooklyn.location.jclouds.pool.ReusableMachineTemplate; +import brooklyn.management.internal.LocalManagementContext; + +public class BrooklynMachinePoolLiveTest { + + public static final Logger log = LoggerFactory.getLogger(BrooklynMachinePoolLiveTest.class); + + public static class SamplePool extends BrooklynMachinePool { + public SamplePool(JcloudsLocation l) { + super(l); + } + + public final static ReusableMachineTemplate + USUAL_VM = + new ReusableMachineTemplate("usual").templateOwnedByMe(). + tagOptional("tagForUsualVm"). + metadataOptional("metadataForUsualVm", "12345"). + minRam(1024).minCores(2); + + public final static ReusableMachineTemplate + ANYONE_NOT_TINY_VM = + new ReusableMachineTemplate("anyone"). + minRam(512).minCores(1).strict(false); + + public static final ReusableMachineTemplate + VM_LARGE1 = + new ReusableMachineTemplate("vm.large1").templateOwnedByMe(). + minRam(16384).minCores(4), + VM_SMALL1 = + new ReusableMachineTemplate("vm.small1").templateOwnedByMe().smallest(); + + { registerTemplates(USUAL_VM, ANYONE_NOT_TINY_VM, VM_LARGE1, VM_SMALL1); } + } + + + private LocalManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = new LocalManagementContext(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) managementContext.terminate(); + } + + @Test(groups="Live") + public void buildClaimAndDestroy() { + SamplePool p = new SamplePool(resolve("aws-ec2:us-west-1")); + log.info("buildClaimAndDestroy: created pool"); + p.refresh(); + log.info("buildClaimAndDestroy: refreshed pool"); + p.ensureExists(2, SamplePool.USUAL_VM); + log.info("buildClaimAndDestroy: ensure have 2"); + SshMachineLocation l = p.obtain(SamplePool.USUAL_VM); + Assert.assertNotNull(l); + log.info("buildClaimAndDestroy: claimed 1"); + MachineSet unclaimedUsual = p.unclaimed(MachinePoolPredicates.matching(SamplePool.USUAL_VM)); + log.info("buildClaimAndDestroy: unclaimed now "+unclaimedUsual); + Assert.assertTrue(!unclaimedUsual.isEmpty(), "should have been unclaimed machines (can fail if there are some we cannot connect to, ie blacklisted)"); + p.destroy(unclaimedUsual); + p.destroy(l); + unclaimedUsual = p.unclaimed(MachinePoolPredicates.matching(SamplePool.USUAL_VM)); + log.info("buildClaimAndDestroy: destroyed, unclaimed now "+unclaimedUsual); + log.info("end"); + } + + + private JcloudsLocation resolve(String spec) { + return (JcloudsLocation) managementContext.getLocationRegistry().resolve(new JcloudsLocationResolver().getPrefix() + ":" + spec); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/DelegatingComputeService.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/DelegatingComputeService.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/DelegatingComputeService.java new file mode 100644 index 0000000..8e718e2 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/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 org.apache.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/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsAddressesLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsAddressesLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsAddressesLiveTest.java new file mode 100644 index 0000000..2694ed5 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsAddressesLiveTest.java @@ -0,0 +1,228 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.basic.Locations; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import brooklyn.util.collections.MutableMap; +import brooklyn.util.stream.Streams; + +/** + * Tests that the correct address is advertised for the VM - for its public/private, + * its subnet hostname, etc. + */ +public class JcloudsAddressesLiveTest extends AbstractJcloudsLiveTest { + + private static final Logger LOG = LoggerFactory.getLogger(JcloudsAddressesLiveTest.class); + + public static final String AWS_EC2_REGION_NAME = AWS_EC2_USEAST_REGION_NAME; + public static final String AWS_EC2_LOCATION_SPEC = "jclouds:" + AWS_EC2_PROVIDER + (AWS_EC2_REGION_NAME == null ? "" : ":" + AWS_EC2_REGION_NAME); + + // Image: {id=us-east-1/ami-7d7bfc14, providerId=ami-7d7bfc14, name=RightImage_CentOS_6.3_x64_v5.8.8.5, location={scope=REGION, id=us-east-1, description=us-east-1, parent=aws-ec2, iso3166Codes=[US-VA]}, os={family=centos, arch=paravirtual, version=6.0, description=rightscale-us-east/RightImage_CentOS_6.3_x64_v5.8.8.5.manifest.xml, is64Bit=true}, description=rightscale-us-east/RightImage_CentOS_6.3_x64_v5.8.8.5.manifest.xml, version=5.8.8.5, status=AVAILABLE[available], loginUser=root, userMetadata={owner=411009282317, rootDeviceType=instance-store, virtualizationType=paravirtual, hypervisor=xen}} + public static final String AWS_EC2_CENTOS_IMAGE_ID = "us-east-1/ami-7d7bfc14"; + + // Image: {id=us-east-1/ami-d0f89fb9, providerId=ami-d0f89fb9, name=ubuntu/images/ebs/ubuntu-precise-12.04-amd64-server-20130411.1, location={scope=REGION, id=us-east-1, description=us-east-1, parent=aws-ec2, iso3166Codes=[US-VA]}, os={family=ubuntu, arch=paravirtual, version=12.04, description=099720109477/ubuntu/images/ebs/ubuntu-precise-12.04-amd64-server-20130411.1, is64Bit=true}, description=099720109477/ubuntu/images/ebs/ubuntu-precise-12.04-amd64-server-20130411.1, version=20130411.1, status=AVAILABLE[available], loginUser=ubuntu, userMetadata={owner=099720109477, rootDeviceType=ebs, virtualizationType=paravirtual, hypervisor=xen}} + public static final String AWS_EC2_UBUNTU_IMAGE_ID = "us-east-1/ami-d0f89fb9"; + + // Image: {id=us-east-1/ami-5e008437, providerId=ami-5e008437, name=RightImage_Ubuntu_10.04_x64_v5.8.8.3, location={scope=REGION, id=us-east-1, description=us-east-1, parent=aws-ec2, iso3166Codes=[US-VA]}, os={family=ubuntu, arch=paravirtual, version=10.04, description=rightscale-us-east/RightImage_Ubuntu_10.04_x64_v5.8.8.3.manifest.xml, is64Bit=true}, description=rightscale-us-east/RightImage_Ubuntu_10.04_x64_v5.8.8.3.manifest.xml, version=5.8.8.3, status=AVAILABLE[available], loginUser=root, userMetadata={owner=411009282317, rootDeviceType=instance-store, virtualizationType=paravirtual, hypervisor=xen}} + // Uses "root" as loginUser + public static final String AWS_EC2_UBUNTU_10_IMAGE_ID = "us-east-1/ami-5e008437"; + + public static final String RACKSPACE_LOCATION_SPEC = "jclouds:" + RACKSPACE_PROVIDER; + + // Image: {id=LON/c52a0ca6-c1f2-4cd1-b7d6-afbcd1ebda22, providerId=c52a0ca6-c1f2-4cd1-b7d6-afbcd1ebda22, name=CentOS 6.0, location={scope=ZONE, id=LON, description=LON, parent=rackspace-cloudservers-uk, iso3166Codes=[GB-SLG]}, os={family=centos, name=CentOS 6.0, version=6.0, description=CentOS 6.0, is64Bit=true}, description=CentOS 6.0, status=AVAILABLE, loginUser=root, userMetadata={os_distro=centos, com.rackspace__1__visible_core=1, com.rackspace__1__build_rackconnect=1, com.rackspace__1__options=0, image_type=base, cache_in_nova=True, com.rackspace__1__source=kickstart, org.openstack__1__os_distro=org.centos, com.rackspace__1__release_build_date=2013-07-25_18-56-29, auto_disk_config=True, com.rackspace__1__release_version=5, os_type=linux, com.rackspace__1__visible_rackconnect=1, com.rackspace__1__release_id=210, com.rackspace__1__visible_managed=0, com.rackspace__1__build_core=1, org.openstack__1__os_version=6.0, org.openstack__1__architecture=x64, com.rackspace__1__build_ma naged=0}} + public static final String RACKSPACE_CENTOS_IMAGE_NAME_REGEX = "CentOS 6.0"; + + protected JcloudsSshMachineLocation machine; + + @Test(groups = {"Live"}) + protected void testAwsEc2Addresses() throws Exception { + jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve(AWS_EC2_LOCATION_SPEC); + + machine = createEc2Machine(ImmutableMap.<String,Object>of()); + assertSshable(machine); + + String locationAddress = machine.getAddress().getHostName(); + InetAddress address = machine.getAddress(); + Set<String> publicAddresses = machine.getPublicAddresses(); + Set<String> privateAddresses = machine.getPrivateAddresses(); + String subnetIp = machine.getSubnetIp(); + String hostname = machine.getHostname(); + String subnetHostname = machine.getSubnetHostname(); + String msg = "locationAddress="+locationAddress+"; address="+address+"; publicAddrs="+publicAddresses+"; privateAddrs="+privateAddresses+"; subnetIp="+subnetIp+"; hostname="+hostname+"; subnetHostname="+subnetHostname; + LOG.info("node: "+msg); + + // On AWS, machine advertises its FQ hostname that is accessible from inside and outside the region + assertReachable(machine, locationAddress, msg); + assertReachableFromMachine(machine, locationAddress, msg); + + assertReachable(machine, address, msg); + + assertTrue(publicAddresses.size() > 0, msg); + for (String publicAddress: publicAddresses) { + assertReachable(machine, publicAddress, msg); + } + + // On AWS, private address is not reachable from outside. + // If you ran this test from the same AWS region, it would fail! + assertTrue(privateAddresses.size() > 0, msg); + for (String privateAddress: privateAddresses) { + assertReachableFromMachine(machine, privateAddress, msg); + assertNotReachable(machine, privateAddress, msg); + } + + assertNotNull(subnetIp, msg); + assertReachableFromMachine(machine, subnetIp, msg); + + // hostname is reachable from inside; not necessarily reachable from outside + assertNotNull(hostname, msg); + assertReachableFromMachine(machine, hostname, msg); + + assertNotNull(subnetHostname, msg); + assertReachableFromMachine(machine, subnetHostname, msg); + } + + @Test(groups = {"Live"}) + protected void testRackspaceAddresses() throws Exception { + jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve(RACKSPACE_LOCATION_SPEC); + + machine = createRackspaceMachine(ImmutableMap.<String,Object>of()); + assertSshable(machine); + + String locationAddress = machine.getAddress().getHostAddress(); + InetAddress address = machine.getAddress(); + Set<String> publicAddresses = machine.getPublicAddresses(); + Set<String> privateAddresses = machine.getPrivateAddresses(); + String subnetIp = machine.getSubnetIp(); + String hostname = machine.getHostname(); + String subnetHostname = machine.getSubnetHostname(); + String msg = "locationAddress="+locationAddress+"; address="+address+"; publicAddrs="+publicAddresses+"; privateAddrs="+privateAddresses+"; subnetIp="+subnetIp+"; hostname="+hostname+"; subnetHostname="+subnetHostname; + LOG.info("node: "+msg); + + // On Rackspace, IP is accessible from inside and outside. + assertReachable(machine, locationAddress, msg); + assertReachableFromMachine(machine, locationAddress, msg); + + assertReachable(machine, address, msg); + + assertTrue(publicAddresses.size() > 0, msg); + for (String publicAddress: publicAddresses) { + assertReachable(machine, publicAddress, msg); + } + + // On Rackspace, don't care if no private addresses + for (String privateAddress: privateAddresses) { + assertReachableFromMachine(machine, privateAddress, msg); + assertNotReachable(machine, privateAddress, msg); + } + + assertNotNull(subnetIp, msg); + assertReachableFromMachine(machine, subnetIp, msg); + + // hostname is reachable from inside; not necessarily reachable from outside + assertNotNull(hostname, msg); + assertReachableFromMachine(machine, hostname, msg); + + assertNotNull(subnetHostname, msg); + assertReachableFromMachine(machine, subnetHostname, msg); + } + + private void assertReachable(SshMachineLocation machine, InetAddress addr, String msg) { + assertReachable(machine, addr.getHostAddress(), msg); + } + + private void assertReachable(SshMachineLocation machine, String addr, String msg) { + assertReachability(true, machine, addr, msg); + } + + private void assertNotReachable(SshMachineLocation machine, String addr, String msg) { + assertReachability(false, machine, addr, msg); + } + + private void assertReachability(boolean expectedReachable, SshMachineLocation machine, String addr, String msg) { + SshMachineLocation tmpMachine = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .configure(machine.config().getBag().getAllConfig()) + .configure("address", addr)); + try { + boolean sshable = tmpMachine.isSshable(); + assertEquals(sshable, expectedReachable, addr+" not sshable; "+msg); + } finally { + Locations.unmanage(tmpMachine); + } + } + + // TODO Assumes that "ping" will work; i.e. that ICMP is not firewall'ed + private void assertReachableFromMachine(SshMachineLocation machine, String addr, String msg) { + OutputStream outStream = new ByteArrayOutputStream(); + OutputStream errStream = new ByteArrayOutputStream(); + int result = machine.execScript(MutableMap.of("out", outStream, "err", errStream), "reach "+addr, ImmutableList.of("ping -c 1 "+addr)); + String outString = outStream.toString(); + String errString = errStream.toString(); + assertEquals(result, 0, "result="+0+"; err="+errString+"; out="+outString+"; msg="+msg); + } + + @Override + protected void releaseMachine(JcloudsSshMachineLocation machine) { + jcloudsLocation.release(machine); + } + + private JcloudsSshMachineLocation createEc2Machine(Map<String,? extends Object> conf) throws Exception { + return obtainMachine(MutableMap.<String,Object>builder() + .putAll(conf) + .putIfAbsent("imageId", AWS_EC2_CENTOS_IMAGE_ID) + .putIfAbsent("hardwareId", AWS_EC2_SMALL_HARDWARE_ID) + .putIfAbsent("inboundPorts", ImmutableList.of(22)) + .build()); + } + + private JcloudsSshMachineLocation createRackspaceMachine(Map<String,? extends Object> conf) throws Exception { + return obtainMachine(MutableMap.<String,Object>builder() + .putAll(conf) + .putIfAbsent("inboundPorts", ImmutableList.of(22)) + .build()); + } + + protected void assertSshable(Map<?,?> machineConfig) { + SshMachineLocation machineWithThatConfig = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .configure(machineConfig)); + try { + assertSshable(machineWithThatConfig); + } finally { + Streams.closeQuietly(machineWithThatConfig); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java new file mode 100644 index 0000000..2f708f3 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java @@ -0,0 +1,178 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.net.InetAddress; +import java.util.Map; +import java.util.Set; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.collections.MutableMap; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public class JcloudsByonLocationResolverAwsLiveTest extends AbstractJcloudsLiveTest { + + private static final String AWS_REGION = "eu-west-1"; + private static final String AWS_LOCATION_SPEC = "jclouds:aws-ec2:"+AWS_REGION; + + private String awsVmUser; + private String awsVmInstanceId; + private String awsVmIp; + private String awsVmHostname; + + private LocalManagementContext classManagementContext; + private JcloudsLocation classEc2Loc; + private JcloudsSshMachineLocation classEc2Vm; + + @BeforeClass(groups="Live") + public void setUpClass() throws Exception { + classManagementContext = newManagementContext(); + classEc2Loc = (JcloudsLocation) classManagementContext.getLocationRegistry().resolve(AWS_LOCATION_SPEC); + classEc2Vm = (JcloudsSshMachineLocation)classEc2Loc.obtain(MutableMap.<String,Object>builder() + .put("hardwareId", AWS_EC2_SMALL_HARDWARE_ID) + .put("inboundPorts", ImmutableList.of(22)) + .build()); + awsVmUser = classEc2Vm.getUser(); + awsVmInstanceId = classEc2Vm.getNode().getProviderId(); // id without region (e.g. "i-6ff96d2f" instead of "eu-west-1/i-6ff96d2f") + awsVmIp = classEc2Vm.getAddress().getHostAddress(); + awsVmHostname = classEc2Vm.getAddress().getHostName(); + } + + @AfterClass(alwaysRun=true) + public void tearDownClass() throws Exception { + try { + if (classEc2Vm != null) { + classEc2Loc.release(classEc2Vm); + } + } finally { + if (classManagementContext != null) classManagementContext.terminate(); + } + } + + // TODO Requires that a VM already exists; could create that VM first to make test more robust + @Test(groups={"Live"}) + public void testResolvesJcloudsByonAws() throws Exception { + String spec = "jcloudsByon:(provider=\"aws-ec2\",region=\""+AWS_REGION+"\",user=\""+awsVmUser+"\",hosts=\""+awsVmInstanceId+"\",anotherprop=myval)"; + + FixedListMachineProvisioningLocation<JcloudsSshMachineLocation> loc = resolve(spec); + + Set<JcloudsSshMachineLocation> machines = loc.getAllMachines(); + JcloudsSshMachineLocation machine = Iterables.getOnlyElement(machines); + assertEquals(machine.getParent().getProvider(), "aws-ec2"); + assertEquals(machine.getAddress().getHostAddress(), awsVmIp); + assertEquals(machine.getAddress().getHostName(), awsVmHostname); + assertEquals(machine.getUser(), awsVmUser); + assertEquals(machine.config().getBag().getStringKey("anotherprop"), "myval"); + + assertTrue(machine.isSshable()); + } + + @Test(groups={"Live"}) + public void testResolvesNamedJcloudsByon() throws Exception { + String spec = "jcloudsByon:(provider=\"aws-ec2\",region=\""+AWS_REGION+"\",user=\""+awsVmUser+"\",hosts=\""+awsVmInstanceId+"\")"; + brooklynProperties.put("brooklyn.location.named.mynamed", spec); + + FixedListMachineProvisioningLocation<JcloudsSshMachineLocation> loc = resolve("named:mynamed"); + assertEquals(loc.obtain().getAddress(), InetAddress.getByName(awsVmHostname)); + } + + @Test(groups={"Live"}) + public void testJcloudsPropertiesPrecedence() throws Exception { + String spec = "jcloudsByon:(provider=\"aws-ec2\",region=\""+AWS_REGION+"\",user=\""+awsVmUser+"\",hosts=\""+awsVmInstanceId+"\")"; + brooklynProperties.put("brooklyn.location.named.mynamed", spec); + + // prefer those in spec string over everything else + brooklynProperties.put("brooklyn.location.named.mynamed.user", "user-inNamed"); + brooklynProperties.put("brooklyn.location.jclouds.aws-ec2.user", "user-inProviderSpecific"); + brooklynProperties.put("brooklyn.jclouds.aws-ec2.user", "user-inProviderSpecificDeprecated"); + brooklynProperties.put("brooklyn.location.jclouds.user", "user-inJcloudsGeneric"); + brooklynProperties.put("brooklyn.jclouds.user", "user-inJcloudsGenericDeprecated"); + brooklynProperties.put("brooklyn.location.user", "user-inLocationGeneric"); + + // prefer those in "named" over everything else (except spec string itself) + brooklynProperties.put("brooklyn.location.named.mynamed.privateKeyFile", "privateKeyFile-inNamed"); + brooklynProperties.put("brooklyn.location.jclouds.aws-ec2.privateKeyFile", "privateKeyFile-inProviderSpecific"); + brooklynProperties.put("brooklyn.jclouds.aws-ec2.privateKeyFile", "privateKeyFile-inProviderSpecificDeprecated"); + brooklynProperties.put("brooklyn.location.jclouds.privateKeyFile", "privateKeyFile-inJcloudsGeneric"); + brooklynProperties.put("brooklyn.jclouds.privateKeyFile", "privateKeyFile-inJcloudsGenericDeprecated"); + brooklynProperties.put("brooklyn.location.privateKeyFile", "privateKeyFile-inLocationGeneric"); + + // prefer those in provider-specific over generic + brooklynProperties.put("brooklyn.location.jclouds.aws-ec2.publicKeyFile", "publicKeyFile-inProviderSpecific"); + brooklynProperties.put("brooklyn.jclouds.aws-ec2.publicKeyFile", "publicKeyFile-inProviderSpecificDeprecated"); + brooklynProperties.put("brooklyn.location.jclouds.publicKeyFile", "publicKeyFile-inJcloudsGeneric"); + brooklynProperties.put("brooklyn.jclouds.publicKeyFile", "publicKeyFile-inJcloudsGenericDeprecated"); + brooklynProperties.put("brooklyn.location.publicKeyFile", "publicKeyFile-inLocationGeneric"); + + // prefer those in provider-specific (deprecated scope) over generic + brooklynProperties.put("brooklyn.jclouds.aws-ec2.securityGroups", "securityGroups-inProviderSpecificDeprecated"); + brooklynProperties.put("brooklyn.location.jclouds.securityGroups", "securityGroups-inJcloudsGeneric"); + brooklynProperties.put("brooklyn.jclouds.securityGroups", "securityGroups-inJcloudsGenericDeprecated"); + brooklynProperties.put("brooklyn.location.securityGroups", "securityGroups-inLocationGeneric"); + + // prefer those in jclouds-generic over location-generic + brooklynProperties.put("brooklyn.location.jclouds.loginUser", "loginUser-inJcloudsGeneric"); + brooklynProperties.put("brooklyn.jclouds.loginUser", "loginUser-inJcloudsGenericDeprecated"); + brooklynProperties.put("brooklyn.location.loginUser", "loginUser-inLocationGeneric"); + + // prefer those in jclouds-generic (deprecated) over location-generic + brooklynProperties.put("brooklyn.jclouds.imageId", "imageId-inJcloudsGenericDeprecated"); + brooklynProperties.put("brooklyn.location.imageId", "imageId-inLocationGeneric"); + + // prefer location-generic if nothing else + brooklynProperties.put("brooklyn.location.keyPair", "keyPair-inLocationGeneric"); + + // prefer deprecated properties in "named" over those less specific + brooklynProperties.put("brooklyn.location.named.mynamed.private-key-data", "privateKeyData-inNamed"); + brooklynProperties.put("brooklyn.jclouds.aws-ec2.privateKeyData", "privateKeyData-inProviderSpecific"); + brooklynProperties.put("brooklyn.jclouds.privateKeyData", "privateKeyData-inJcloudsGeneric"); + + // prefer "named" over everything else: confirm deprecated don't get transformed to overwrite it accidentally + brooklynProperties.put("brooklyn.location.named.mynamed.privateKeyPassphrase", "privateKeyPassphrase-inNamed"); + brooklynProperties.put("brooklyn.jclouds.aws-ec2.private-key-passphrase", "privateKeyPassphrase-inProviderSpecific"); + brooklynProperties.put("brooklyn.jclouds.private-key-passphrase", "privateKeyPassphrase-inJcloudsGeneric"); + + Map<String, Object> conf = resolve("named:mynamed").obtain().config().getBag().getAllConfig(); + + assertEquals(conf.get("user"), awsVmUser); + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed"); + assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inProviderSpecific"); + assertEquals(conf.get("securityGroups"), "securityGroups-inProviderSpecificDeprecated"); + assertEquals(conf.get("loginUser"), "loginUser-inJcloudsGeneric"); + assertEquals(conf.get("imageId"), "imageId-inJcloudsGenericDeprecated"); + assertEquals(conf.get("keyPair"), "keyPair-inLocationGeneric"); + assertEquals(conf.get("privateKeyData"), "privateKeyData-inNamed"); + assertEquals(conf.get("privateKeyPassphrase"), "privateKeyPassphrase-inNamed"); + } + + @SuppressWarnings("unchecked") + private FixedListMachineProvisioningLocation<JcloudsSshMachineLocation> resolve(String spec) { + return (FixedListMachineProvisioningLocation<JcloudsSshMachineLocation>) managementContext.getLocationRegistry().resolve(spec); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java new file mode 100644 index 0000000..31831a8 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java @@ -0,0 +1,105 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Set; + +import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.collections.MutableMap; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public class JcloudsByonLocationResolverSoftlayerLiveTest extends AbstractJcloudsLiveTest { + + private static final String SOFTLAYER_REGION = "dal05"; + private static final String SOFTLAYER_LOCATION_SPEC = "jclouds:softlayer:"+SOFTLAYER_REGION; + + private String slVmUser; + private String slVmInstanceId; + private String slVmIp; + private String slVmHostname; + + private LocalManagementContext classManagementContext; + private JcloudsLocation classEc2Loc; + private JcloudsSshMachineLocation classVm; + + @BeforeClass(groups="Live") + public void setUpClass() throws Exception { + classManagementContext = newManagementContext(); + classEc2Loc = (JcloudsLocation) classManagementContext.getLocationRegistry().resolve(SOFTLAYER_LOCATION_SPEC); + classVm = (JcloudsSshMachineLocation)classEc2Loc.obtain(MutableMap.<String,Object>builder() + .put("inboundPorts", ImmutableList.of(22)) + .build()); + slVmUser = classVm.getUser(); + slVmInstanceId = classVm.getJcloudsId(); + slVmIp = classVm.getAddress().getHostAddress(); + slVmHostname = classVm.getNode().getHostname(); + } + + @AfterClass(alwaysRun=true) + public void tearDownClass() throws Exception { + try { + if (classVm != null) { + classEc2Loc.release(classVm); + } + } finally { + if (classManagementContext != null) classManagementContext.terminate(); + } + } + + @Test(groups={"Live"}) + public void testResolvesJcloudsByonSoftlayer() throws Exception { + checkSoftlayer("jcloudsByon:(provider=\"softlayer\",region=\""+SOFTLAYER_REGION+"\",hosts=\""+slVmInstanceId+"\",user=\""+slVmUser+"\")"); + checkSoftlayer("jcloudsByon:(provider=\"softlayer\",region=\""+SOFTLAYER_REGION+"\",hosts=\""+slVmHostname+"\")"); + checkSoftlayer("jcloudsByon:(provider=\"softlayer\",region=\""+SOFTLAYER_REGION+"\",hosts=\""+slVmIp+"\")"); + checkSoftlayer("jcloudsByon:(provider=\"softlayer\",hosts=\""+slVmIp+"\")"); + } + + private void checkSoftlayer(String spec) { + FixedListMachineProvisioningLocation<JcloudsSshMachineLocation> loc = resolve(spec); + + Set<JcloudsSshMachineLocation> machines = loc.getAllMachines(); + JcloudsSshMachineLocation machine = Iterables.getOnlyElement(machines); + assertEquals(machine.getParent().getProvider(), "softlayer"); + assertEquals(machine.getNode().getId(), slVmInstanceId); + assertEquals(machine.getAddress().getHostAddress(), slVmIp); + assertTrue(slVmHostname.equals(machine.getAddress().getHostName()) || slVmIp.equals(machine.getAddress().getHostName()), + "address hostname is: "+machine.getAddress().getHostName()); + assertTrue(slVmHostname.equals(machine.getNode().getHostname()) || slVmIp.equals(machine.getNode().getHostname()), + "node hostname is: "+machine.getNode().getHostname()); + + // could also assert this, given a user credential, but not currently set up +// assertTrue(machine.isSshable()); + } + + @SuppressWarnings("unchecked") + private FixedListMachineProvisioningLocation<JcloudsSshMachineLocation> resolve(String spec) { + return (FixedListMachineProvisioningLocation<JcloudsSshMachineLocation>) managementContext.getLocationRegistry().resolve(spec); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java new file mode 100644 index 0000000..3f7c837 --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java @@ -0,0 +1,81 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import static org.testng.Assert.fail; + +import java.util.NoSuchElementException; + +import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.Entities; +import brooklyn.management.internal.LocalManagementContext; + +public class JcloudsByonLocationResolverTest { + + private LocalManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testThrowsOnInvalid() throws Exception { + assertThrowsNoSuchElement("wrongprefix:(hosts=\"1.1.1.1\")"); + assertThrowsIllegalArgument("jcloudsByon"); // no hosts + assertThrowsIllegalArgument("jcloudsByon:()"); // no hosts + assertThrowsIllegalArgument("jcloudsByon:(hosts=\"\")"); // empty hosts + assertThrowsIllegalArgument("jcloudsByon:(hosts=\"i-72b1b132\""); // no closing bracket + assertThrowsIllegalArgument("jcloudsByon:(hosts=\"i-72b1b132\", name)"); // no value for name + assertThrowsIllegalArgument("jcloudsByon:(hosts=\"i-72b1b132\", name=)"); // no value for name + } + + @SuppressWarnings("unchecked") + private FixedListMachineProvisioningLocation<JcloudsSshMachineLocation> resolve(String spec) { + return (FixedListMachineProvisioningLocation<JcloudsSshMachineLocation>) managementContext.getLocationRegistry().resolve(spec); + } + + private void assertThrowsNoSuchElement(String val) { + try { + resolve(val); + fail(); + } catch (NoSuchElementException e) { + // success + } + } + + private void assertThrowsIllegalArgument(String val) { + try { + resolve(val); + fail(); + } catch (IllegalArgumentException e) { + // success + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsHardwareProfilesStubbedLiveTest.java new file mode 100644 index 0000000..8f9b1ea --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/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 org.apache.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/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java new file mode 100644 index 0000000..7bce1ab --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.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.apache.brooklyn.location.jclouds; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.location.Location; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import org.apache.brooklyn.location.basic.LocationConfigKeys; +import brooklyn.management.internal.LocalManagementContext; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Shane Witbeck + */ +public class JcloudsLocationMetadataTest implements JcloudsLocationConfig { + + protected BrooklynProperties brooklynProperties; + protected LocalManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(BrooklynProperties.Factory.builderEmpty().build()); + brooklynProperties = managementContext.getBrooklynProperties(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + + @Test + public void testGetsDefaultAwsEc2Metadata() throws Exception { + Location loc = managementContext.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-1"); + + assertEquals(loc.getConfig(LocationConfigKeys.LATITUDE), 40.0d); + assertEquals(loc.getConfig(LocationConfigKeys.LONGITUDE), -120.0d); + assertEquals(loc.getConfig(LocationConfigKeys.ISO_3166), ImmutableSet.of("US-CA")); + } + + @Test + public void testCanOverrideDefaultAwsEc2Metadata() throws Exception { + brooklynProperties.put("[email protected]", "41.2"); + Location loc = managementContext.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-1"); + + assertEquals(loc.getConfig(LocationConfigKeys.LATITUDE), 41.2d); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java new file mode 100644 index 0000000..006f62e --- /dev/null +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationRebindMachineLiveTest.java @@ -0,0 +1,138 @@ +/* + * 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.apache.brooklyn.location.jclouds; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.net.InetAddress; +import java.util.Collections; + +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +public class JcloudsLocationRebindMachineLiveTest extends AbstractJcloudsLiveTest { + + private static final Logger LOG = LoggerFactory.getLogger(JcloudsLocationRebindMachineLiveTest.class); + + private static final String EUWEST_IMAGE_ID = AWS_EC2_EUWEST_REGION_NAME+"/"+"ami-89def4fd"; + private static final String IMAGE_OWNER = "411009282317"; + + @BeforeMethod(alwaysRun=true) + @Override + public void setUp() throws Exception { + super.setUp(); + jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve(AWS_EC2_PROVIDER+":"+AWS_EC2_EUWEST_REGION_NAME); + } + + @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("node not found")) { + // success + } else { + throw e; + } + } + } + + @Test(groups = { "Live" }) + public void testRebindVm() throws Exception { + // FIXME How to create a machine - go directly through jclouds instead? + // Going through LocationRegistry.resolve, loc and loc2 might be same instance + + // Create a VM through jclouds + JcloudsSshMachineLocation machine = obtainMachine(ImmutableMap.of("imageId", EUWEST_IMAGE_ID, "imageOwner", IMAGE_OWNER)); + assertTrue(machine.isSshable()); + LOG.info("obtained "+machine); + + String id = checkNotNull(machine.getJcloudsId(), "id"); + InetAddress address = checkNotNull(machine.getAddress(), "address"); + String hostname = checkNotNull(address.getHostName(), "hostname"); + String user = checkNotNull(machine.getUser(), "user"); + + // Create a new jclouds location, and re-bind the existing VM to that + JcloudsLocation loc2 = (JcloudsLocation) managementContext.getLocationRegistry().resolve(AWS_EC2_PROVIDER+":"+AWS_EC2_EUWEST_REGION_NAME); + SshMachineLocation machine2 = loc2.rebindMachine(ImmutableMap.of("id", id, "hostname", hostname, "user", user)); + + LOG.info("rebinded to "+machine2); + + // Confirm the re-bound machine is wired up + assertTrue(machine2.isSshable()); + assertEquals(ImmutableSet.copyOf(loc2.getChildren()), ImmutableSet.of(machine2)); + + // Confirm can release the re-bound machine via the new jclouds location + loc2.release(machine2); + assertFalse(machine.isSshable()); + assertEquals(ImmutableSet.copyOf(loc2.getChildren()), Collections.emptySet()); + } + + @Test(groups = { "Live" }) + public void testRebindVmDeprecated() throws Exception { + // FIXME See comments in testRebindVm + + // Create a VM through jclouds + JcloudsSshMachineLocation machine = obtainMachine(ImmutableMap.of("imageId", EUWEST_IMAGE_ID, "imageOwner", IMAGE_OWNER)); + assertTrue(machine.isSshable()); + + String id = machine.getJcloudsId(); + InetAddress address = machine.getAddress(); + String hostname = address.getHostName(); + String username = machine.getUser(); + + // Create a new jclouds location, and re-bind the existing VM to that + JcloudsLocation loc2 = (JcloudsLocation) managementContext.getLocationRegistry().resolve(AWS_EC2_PROVIDER+":"+AWS_EC2_EUWEST_REGION_NAME); + // pass deprecated userName + SshMachineLocation machine2 = loc2.rebindMachine(ImmutableMap.of("id", id, "hostname", hostname, "userName", username)); + + // Confirm the re-bound machine is wired up + assertTrue(machine2.isSshable()); + assertEquals(ImmutableSet.copyOf(loc2.getChildren()), ImmutableSet.of(machine2)); + + // Confirm can release the re-bound machine via the new jclouds location + loc2.release(machine2); + assertFalse(machine.isSshable()); + assertEquals(ImmutableSet.copyOf(loc2.getChildren()), Collections.emptySet()); + } + + // Useful for debugging; accesss a hard-coded existing instance so don't need to wait for provisioning a new one + @Test(enabled=false, groups = { "Live" }) + public void testRebindVmToHardcodedInstance() throws Exception { + String id = "eu-west-1/i-5504f21d"; + InetAddress address = InetAddress.getByName("ec2-176-34-93-58.eu-west-1.compute.amazonaws.com"); + String hostname = address.getHostName(); + String username = "root"; + + SshMachineLocation machine = jcloudsLocation.rebindMachine(ImmutableMap.of("id", id, "hostname", hostname, "userName", username)); + + // Confirm the re-bound machine is wired up + assertTrue(machine.isSshable()); + assertEquals(ImmutableSet.copyOf(jcloudsLocation.getChildren()), ImmutableSet.of(machine)); + } +}
