http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/group/DynamicClusterWithAvailabilityZonesMultiLocationTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/group/DynamicClusterWithAvailabilityZonesMultiLocationTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/group/DynamicClusterWithAvailabilityZonesMultiLocationTest.java new file mode 100644 index 0000000..474ce0f --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/group/DynamicClusterWithAvailabilityZonesMultiLocationTest.java @@ -0,0 +1,115 @@ +/* + * 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.entity.software.base.test.group; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; + +import java.util.List; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.internal.EntityLocal; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.location.MachineLocation; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.entity.core.EntityPredicates; +import org.apache.brooklyn.entity.group.DynamicCluster; +import org.apache.brooklyn.entity.group.DynamicClusterWithAvailabilityZonesTest; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; +import org.apache.brooklyn.entity.software.base.SoftwareProcess; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.basic.MultiLocation; +import org.apache.brooklyn.test.Asserts; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +/** + * Uses {@link SoftwareProcess}, so test can't be in core project. + * + * Different from {@link DynamicClusterWithAvailabilityZonesTest} in the use of {@link MultiLocation}. + * However, the difference is important: the {@link SoftwareProcess} entity has two locations + * (the {@link MachineProvisioningLocation} and the {@link MachineLocation}, which was previously + * causing a failure - now fixed and tested here. + */ +public class DynamicClusterWithAvailabilityZonesMultiLocationTest extends BrooklynAppUnitTestSupport { + + private DynamicCluster cluster; + + private LocalhostMachineProvisioningLocation subLoc1; + private LocalhostMachineProvisioningLocation subLoc2; + private MultiLocation<?> multiLoc; + + @BeforeMethod(alwaysRun=true) + @Override + public void setUp() throws Exception { + super.setUp(); + cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) + .configure(DynamicCluster.ENABLE_AVAILABILITY_ZONES, true) + .configure(DynamicCluster.INITIAL_SIZE, 0) + .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(EmptySoftwareProcess.class))); + + subLoc1 = app.newLocalhostProvisioningLocation(ImmutableMap.of("displayName", "loc1")); + subLoc2 = app.newLocalhostProvisioningLocation(ImmutableMap.of("displayName", "loc2")); + multiLoc = mgmt.getLocationManager().createLocation(LocationSpec.create(MultiLocation.class) + .configure(MultiLocation.SUB_LOCATIONS, ImmutableList.<MachineProvisioningLocation<?>>of(subLoc1, subLoc2))); + } + + @Test + public void testReplacesEntityInSameZone() throws Exception { + ((EntityLocal)cluster).config().set(DynamicCluster.ENABLE_AVAILABILITY_ZONES, true); + cluster.start(ImmutableList.of(multiLoc)); + + cluster.resize(4); + List<String> locsUsed = getLocationNames(getLocationsOf(cluster.getMembers(), Predicates.instanceOf(MachineProvisioningLocation.class))); + Asserts.assertEqualsIgnoringOrder(locsUsed, ImmutableList.of("loc1", "loc1", "loc2", "loc2")); + + String idToRemove = Iterables.getFirst(cluster.getMembers(), null).getId(); + String idAdded = cluster.replaceMember(idToRemove); + locsUsed = getLocationNames(getLocationsOf(cluster.getMembers(), Predicates.instanceOf(MachineProvisioningLocation.class))); + Asserts.assertEqualsIgnoringOrder(locsUsed, ImmutableList.of("loc1", "loc1", "loc2", "loc2")); + assertNull(Iterables.find(cluster.getMembers(), EntityPredicates.idEqualTo(idToRemove), null)); + assertNotNull(Iterables.find(cluster.getMembers(), EntityPredicates.idEqualTo(idAdded), null)); + } + + protected List<Location> getLocationsOf(Iterable<? extends Entity> entities, Predicate<? super Location> filter) { + List<Location> result = Lists.newArrayList(); + for (Entity entity : entities) { + Iterables.addAll(result, Iterables.filter(entity.getLocations(), filter)); + } + return result; + } + + protected List<String> getLocationNames(Iterable<? extends Location> locs) { + List<String> result = Lists.newArrayList(); + for (Location subLoc : locs) { + result.add(subLoc.getDisplayName()); + } + return result; + } +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/GeneralisedDynamicMBean.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/GeneralisedDynamicMBean.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/GeneralisedDynamicMBean.java new file mode 100644 index 0000000..9c6c551 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/GeneralisedDynamicMBean.java @@ -0,0 +1,146 @@ +/* + * 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.entity.software.base.test.jmx; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.DynamicMBean; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; + +/** + * A quick-and-simple general-purpose implementation of DynamicMBean. + * + * This class provides an implementation of {@link DynamicMBean}. Its initial set of attribute names and values are + * provided to the constructor; from this it figures an {@link MBeanInfo}. + * <p> + * It presently assumes that all attributes are read-only; operations and notifications are not currently supported. + * Choosing the descriptions is not supported - they are set to be the same as the name. + * <p> + * Getting a valid dynamic MBean (in Groovy) is as simple as: + * <pre> + * new GeneralisedDynamicMBean(meaning: 42, advice: "Don't panic") + * </pre> + */ +public class GeneralisedDynamicMBean implements DynamicMBean { + private final MBeanInfo mBeanInfo; + private final Map<String,Object> attributes = Maps.newLinkedHashMap(); + private final Map<String,Function> operations = Maps.newLinkedHashMap(); + + public GeneralisedDynamicMBean(Map<String,?> initialAttributes, Map<?,?> initialOperations) { + attributes.putAll(initialAttributes); + + for (Entry<?,?> entry : initialOperations.entrySet()) { + checkArgument(entry.getKey() instanceof String || entry.getKey() instanceof MBeanOperationInfo, "entry.key=%s", entry.getKey()); + String opName = (entry.getKey() instanceof String) ? (String)entry.getKey() : ((MBeanOperationInfo)entry.getKey()).getName(); + operations.put(opName, (Function) entry.getValue()); + } + + Iterable<MBeanAttributeInfo> attrInfo = Iterables.transform(initialAttributes.entrySet(), new Function<Map.Entry<String,?>, MBeanAttributeInfo>() { + @Override public MBeanAttributeInfo apply(Map.Entry<String,?> entry) { + return new MBeanAttributeInfo(entry.getKey(), entry.getValue().getClass().getName(), entry.getKey(), true, false, false); + } + }); + + Iterable<MBeanOperationInfo> opInfo = Iterables.transform(initialOperations.keySet(), new Function<Object, MBeanOperationInfo>() { + public MBeanOperationInfo apply(Object it) { + if (it instanceof MBeanOperationInfo) { + return (MBeanOperationInfo) it; + } else if (it instanceof CharSequence) { + return new MBeanOperationInfo( + it.toString(), + "my descr", + new MBeanParameterInfo[0], + "void", + MBeanOperationInfo.ACTION_INFO); + } else { + throw new IllegalArgumentException("Cannot convert "+it+" to MBeanOperationInfo"); + } + }}); + + mBeanInfo = new MBeanInfo( + GeneralisedDynamicMBean.class.getName(), + GeneralisedDynamicMBean.class.getName(), + Iterables.toArray(attrInfo, MBeanAttributeInfo.class), + new MBeanConstructorInfo[0], + Iterables.toArray(opInfo, MBeanOperationInfo.class), + new MBeanNotificationInfo[0]); + } + + public void updateAttributeValue(String name, Object value) { + attributes.put(name, value); + } + + @Override + public Object getAttribute(String s) { + return attributes.get(s); + } + + @Override + public void setAttribute(Attribute attribute) { + attributes.put(attribute.getName(), attribute.getValue()); + } + + @Override + public AttributeList getAttributes(String[] strings) { + AttributeList result = new AttributeList(); + for (Object obj : mBeanInfo.getAttributes()) { + Attribute attrib = (Attribute) obj; + result.add(new Attribute(attrib.getName(), attributes.get(attrib.getName()))); + } + return result; + } + + @Override + public AttributeList setAttributes(AttributeList attributeList) { + for (Object element : attributeList) { + Attribute attrib = (Attribute) element; + attributes.put(attrib.getName(), attrib.getValue()); + } + return attributeList; + } + + @Override + public Object invoke(String s, Object[] objects, String[] strings) { + Function op = operations.get(s); + if (op != null) { + return op.apply(objects); + } else { + throw new RuntimeException("Unknown operation "+s); + } + } + + @Override + public MBeanInfo getMBeanInfo() { + return mBeanInfo; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/JmxService.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/JmxService.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/JmxService.java new file mode 100644 index 0000000..bb7b2a5 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/jmx/JmxService.java @@ -0,0 +1,172 @@ +/* + * 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.entity.software.base.test.jmx; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.MBeanServerInvocationHandler; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.management.Notification; +import javax.management.NotificationBroadcasterSupport; +import javax.management.NotificationEmitter; +import javax.management.ObjectName; +import javax.management.StandardEmitterMBean; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +import mx4j.tools.naming.NamingService; +import mx4j.tools.naming.NamingServiceMBean; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.entity.core.Attributes; +import org.apache.brooklyn.entity.java.UsesJmx; +import org.apache.brooklyn.sensor.feed.jmx.JmxHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; + +/** + * Set up a JMX service ready for clients to connect. This consists of an MBean server, a connector server and a naming + * service. + */ +public class JmxService { + private static final Logger logger = LoggerFactory.getLogger(JmxService.class); + + private MBeanServer server; + private NamingServiceMBean namingServiceMBean; + private JMXConnectorServer connectorServer; + private String jmxHost; + private int jmxPort; + private String url; + + public JmxService() throws Exception { + this("localhost", 28000 + (int)Math.floor(new Random().nextDouble() * 1000)); + logger.warn("use of deprecated default host and port in JmxService"); + } + + /** + * @deprecated since 0.6.0; either needs abandoning, or updating to support JmxSupport (and JmxmpAgent, etc) */ + public JmxService(Entity e) throws Exception { + this(e.getAttribute(Attributes.HOSTNAME) != null ? e.getAttribute(Attributes.HOSTNAME) : "localhost", + e.getAttribute(UsesJmx.JMX_PORT) != null ? e.getAttribute(UsesJmx.JMX_PORT) : null); + } + + public JmxService(String jmxHost, Integer jmxPort) throws Exception { + this.jmxHost = jmxHost; + Preconditions.checkNotNull(jmxPort, "JMX_PORT must be set when starting JmxService"); + this.jmxPort = jmxPort; + url = JmxHelper.toRmiJmxUrl(jmxHost, jmxPort, jmxPort, "jmxrmi"); + + try { + JMXServiceURL address = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + jmxHost + ":" + jmxPort + "/jmxrmi"); + connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, null, null); + server = MBeanServerFactory.createMBeanServer(); + ObjectName cntorServerName = ObjectName.getInstance("connectors:protocol=rmi"); + server.registerMBean(connectorServer, cntorServerName); + + ObjectName naming = new ObjectName("Naming:type=registry"); + server.registerMBean(new NamingService(jmxPort), naming); + Object proxy = MBeanServerInvocationHandler.newProxyInstance(server, naming, NamingServiceMBean.class, false); + namingServiceMBean = (NamingServiceMBean) proxy; + try { + namingServiceMBean.start(); + } catch (Exception e) { + // may take a bit of time for port to be available, if it had just been used + logger.warn("JmxService couldn't start test mbean ("+e+"); will delay then retry once"); + Thread.sleep(1000); + namingServiceMBean.start(); + } + + connectorServer.start(); + logger.info("JMX tester service started at URL {}", address); + } catch (Exception e) { + try { + shutdown(); + } catch (Exception e2) { + logger.warn("Error shutting down JmxService, after error during startup; rethrowing original error", e2); + } + throw e; + } + } + + public int getJmxPort() { + return jmxPort; + } + + public void shutdown() throws IOException { + if (connectorServer != null) connectorServer.stop(); + if (namingServiceMBean != null) namingServiceMBean.stop(); + if (server != null) MBeanServerFactory.releaseMBeanServer(server); + connectorServer = null; + namingServiceMBean = null; + server = null; + logger.info("JMX tester service stopped ({}:{})", jmxHost, jmxPort); + } + + public String getUrl() { + return url; + } + + public GeneralisedDynamicMBean registerMBean(String name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, NullPointerException { + return registerMBean(ImmutableMap.of(), ImmutableMap.of(), name); + } + + /** + * Construct a {@link GeneralisedDynamicMBean} and register it with this MBean server. + * + * @param initialAttributes a {@link Map} of attributes that make up the MBean's initial set of attributes and their * values + * @param name the name of the MBean + * @return the newly created and registered MBean + * @throws NullPointerException + * @throws MalformedObjectNameException + * @throws NotCompliantMBeanException + * @throws MBeanRegistrationException + * @throws InstanceAlreadyExistsException + */ + public GeneralisedDynamicMBean registerMBean(Map initialAttributes, String name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, NullPointerException { + return registerMBean(initialAttributes, ImmutableMap.of(), name); + } + + public GeneralisedDynamicMBean registerMBean(Map initialAttributes, Map operations, String name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, NullPointerException { + GeneralisedDynamicMBean mbean = new GeneralisedDynamicMBean(initialAttributes, operations); + server.registerMBean(mbean, new ObjectName(name)); + return mbean; + } + + public StandardEmitterMBean registerMBean(List<String> notifications, String name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, NullPointerException { + String[] types = (String[]) notifications.toArray(new String[0]); + MBeanNotificationInfo info = new MBeanNotificationInfo(types, Notification.class.getName(), "Notification"); + NotificationEmitter emitter = new NotificationBroadcasterSupport(info); + StandardEmitterMBean mbean = new StandardEmitterMBean(emitter, NotificationEmitter.class, emitter); + server.registerMBean(mbean, new ObjectName(name)); + return mbean; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsEc2LiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsEc2LiveTest.java new file mode 100644 index 0000000..b9e3d68 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsEc2LiveTest.java @@ -0,0 +1,70 @@ +/* + * 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.entity.software.base.test.location; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.MachineDetails; +import org.apache.brooklyn.api.location.OsDetails; +import org.apache.brooklyn.entity.AbstractEc2LiveTest; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; +import org.apache.brooklyn.entity.trait.Startable; +import org.apache.brooklyn.location.basic.BasicMachineDetails; +import org.apache.brooklyn.location.basic.Locations; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.test.EntityTestUtils; +import org.apache.brooklyn.util.collections.MutableMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; + +// This test really belongs in brooklyn-location but depends on AbstractEc2LiveTest in brooklyn-software-base +public class MachineDetailsEc2LiveTest extends AbstractEc2LiveTest { + + private static final Logger LOG = LoggerFactory.getLogger(MachineDetailsEc2LiveTest.class); + private static final int TIMEOUT_MS = 1000 * 60 * 10; // ten minutes + + @Override + protected void doTest(Location loc) throws Exception { + Entity testEntity = app.createAndManageChild(EntitySpec.create(EmptySoftwareProcess.class)); + app.start(ImmutableList.of(loc)); + EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), + testEntity, Startable.SERVICE_UP, true); + + SshMachineLocation sshLoc = Locations.findUniqueSshMachineLocation(testEntity.getLocations()).get(); + MachineDetails machine = app.getExecutionContext() + .submit(BasicMachineDetails.taskForSshMachineLocation(sshLoc)) + .getUnchecked(); + LOG.info("Found the following at {}: {}", loc, machine); + assertNotNull(machine); + OsDetails details = machine.getOsDetails(); + assertNotNull(details); + assertNotNull(details.getArch()); + assertNotNull(details.getName()); + assertNotNull(details.getVersion()); + assertFalse(details.getArch().startsWith("architecture:")); + assertFalse(details.getName().startsWith("name:")); + assertFalse(details.getVersion().startsWith("version:")); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsGoogleComputeLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsGoogleComputeLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsGoogleComputeLiveTest.java new file mode 100644 index 0000000..1234f41 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/MachineDetailsGoogleComputeLiveTest.java @@ -0,0 +1,67 @@ +/* + * 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.entity.software.base.test.location; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.MachineDetails; +import org.apache.brooklyn.api.location.OsDetails; +import org.apache.brooklyn.entity.AbstractGoogleComputeLiveTest; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; +import org.apache.brooklyn.entity.trait.Startable; +import org.apache.brooklyn.location.basic.BasicMachineDetails; +import org.apache.brooklyn.location.basic.Locations; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.test.EntityTestUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; + +// This test really belongs in brooklyn-location but depends on AbstractGoogleComputeLiveTest in brooklyn-software-base +public class MachineDetailsGoogleComputeLiveTest extends AbstractGoogleComputeLiveTest { + + private static final Logger LOG = LoggerFactory.getLogger(MachineDetailsGoogleComputeLiveTest.class); + + @Override + protected void doTest(Location loc) throws Exception { + Entity testEntity = app.createAndManageChild(EntitySpec.create(EmptySoftwareProcess.class)); + app.start(ImmutableList.of(loc)); + EntityTestUtils.assertAttributeEqualsEventually(testEntity, Startable.SERVICE_UP, true); + + SshMachineLocation sshLoc = Locations.findUniqueSshMachineLocation(testEntity.getLocations()).get(); + MachineDetails machine = app.getExecutionContext() + .submit(BasicMachineDetails.taskForSshMachineLocation(sshLoc)) + .getUnchecked(); + LOG.info("Found the following at {}: {}", loc, machine); + assertNotNull(machine); + OsDetails details = machine.getOsDetails(); + assertNotNull(details); + assertNotNull(details.getArch()); + assertNotNull(details.getName()); + assertNotNull(details.getVersion()); + assertFalse(details.getArch().startsWith("architecture:")); + assertFalse(details.getName().startsWith("name:")); + assertFalse(details.getVersion().startsWith("version:")); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java new file mode 100644 index 0000000..12727fa --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java @@ -0,0 +1,92 @@ +/* + * 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.entity.software.base.test.location; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.core.internal.BrooklynProperties; +import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; + +import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.apache.brooklyn.location.jclouds.JcloudsWinRmMachineLocation; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class WinRmMachineLocationLiveTest { + + // FIXME failing locally with: + // Caused by: Traceback (most recent call last): + // File "__pyclasspath__/winrm/__init__.py", line 40, in run_cmd + // File "__pyclasspath__/winrm/protocol.py", line 118, in open_shell + // File "__pyclasspath__/winrm/protocol.py", line 190, in send_message + // File "__pyclasspath__/winrm/transport.py", line 112, in send_message + // winrm.exceptions.WinRMTransportError: 500 WinRMTransport. [Errno 20001] getaddrinfo failed + // at org.python.core.PyException.doRaise(PyException.java:226) + + private static final Logger LOG = LoggerFactory.getLogger(BrooklynAppLiveTestSupport.class); + + protected JcloudsLocation loc; + protected TestApplication app; + protected ManagementContextInternal mgmt; + + private JcloudsWinRmMachineLocation machine; + + @BeforeClass(alwaysRun=true) + public void setUpClass() throws Exception { + mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault()); + JcloudsLocation loc = (JcloudsLocation) mgmt.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-2", ImmutableMap.of( + "inboundPorts", ImmutableList.of(5985, 3389), + "displayName", "AWS Oregon (Windows)", + "imageId", "us-west-2/ami-8fd3f9bf", + "hardwareId", "m3.medium", + "useJcloudsSshInit", false)); + machine = (JcloudsWinRmMachineLocation) loc.obtain(); + } + + @AfterClass(alwaysRun=true) + public void tearDownClass() throws Exception { + try { + if (machine != null) loc.release(machine); + if (mgmt != null) Entities.destroyAll(mgmt); + } catch (Throwable t) { + LOG.error("Caught exception in tearDown method", t); + } finally { + mgmt = null; + } + } + + @Test(groups="Live") + public void testExecScript() throws Exception { + WinRmToolResponse response = machine.executeScript("echo true"); + assertEquals(response.getStatusCode(), 0); + assertEquals(response.getStdErr(), ""); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationTest.java new file mode 100644 index 0000000..8880d88 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationTest.java @@ -0,0 +1,44 @@ +/* + * 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.entity.software.base.test.location; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.entity.core.BrooklynConfigKeys; +import org.apache.brooklyn.location.basic.WinRmMachineLocation; +import org.apache.brooklyn.util.net.Networking; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +public class WinRmMachineLocationTest extends BrooklynAppUnitTestSupport { + + @Test + public void testConfigurePrivateAddresses() throws Exception { + WinRmMachineLocation host = mgmt.getLocationManager().createLocation(LocationSpec.create(WinRmMachineLocation.class) + .configure("address", Networking.getLocalHost()) + .configure(WinRmMachineLocation.PRIVATE_ADDRESSES, ImmutableList.of("1.2.3.4")) + .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)); + + assertEquals(host.getPrivateAddresses(), ImmutableSet.of("1.2.3.4")); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/AbstractToyMySqlEntityTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/AbstractToyMySqlEntityTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/AbstractToyMySqlEntityTest.java new file mode 100644 index 0000000..e7bc7d8 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/AbstractToyMySqlEntityTest.java @@ -0,0 +1,107 @@ +/* + * 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.entity.software.base.test.mysql; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; +import org.apache.brooklyn.entity.core.Attributes; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.sensor.ssh.SshEffectorTasks; +import org.apache.brooklyn.test.EntityTestUtils; +import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; +import org.apache.brooklyn.util.time.Duration; +import org.apache.brooklyn.util.time.Time; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.basic.SshMachineLocation; + +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; + + +public abstract class AbstractToyMySqlEntityTest extends BrooklynAppLiveTestSupport { + + private static final Logger log = LoggerFactory.getLogger(AbstractToyMySqlEntityTest.class); + + protected MachineProvisioningLocation<? extends SshMachineLocation> targetLocation; + + @Override + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + + targetLocation = createLocation(); + } + + protected MachineProvisioningLocation<? extends SshMachineLocation> createLocation() { + return mgmt.getLocationManager().createLocation(LocationSpec.create( + LocalhostMachineProvisioningLocation.class)); + } + + protected abstract Entity createMysql(); + + // deliberately not marked as a test here so that subclasses mark it correctly (Live v Integration) + public void testMySqlOnProvisioningLocation() throws Exception { + Entity mysql = createMysql(); + app.start(MutableList.of(targetLocation)); + checkStartsRunning(mysql); + checkIsRunningAndStops(mysql, (SshMachineLocation) Iterables.getOnlyElement( mysql.getLocations() )); + } + + protected Integer getPid(Entity mysql) { + return mysql.getAttribute(Attributes.PID); + } + + protected void checkStartsRunning(Entity mysql) { + // should be starting within a few seconds (and almost certainly won't complete in that time) + EntityTestUtils.assertAttributeEventually( + mysql, + Attributes.SERVICE_STATE_ACTUAL, + Predicates.or(Predicates.equalTo(Lifecycle.STARTING), Predicates.equalTo(Lifecycle.RUNNING))); + // should be up and running within 5m + EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", Duration.FIVE_MINUTES), + mysql, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + } + + protected void checkIsRunningAndStops(Entity mysql, SshMachineLocation lh) { + Integer pid = getPid(mysql); + Assert.assertNotNull(pid, "PID should be set as an attribute (or getPid() overridden to supply)"); + Entities.submit(app, SshEffectorTasks.requirePidRunning(pid).machine(lh).newTask() ).get(); + + app.stop(); + + // let the kill -1 take effect + Time.sleep(Duration.ONE_SECOND); + + // and assert it has died + log.info("mysql in pid "+pid+" should be dead now"); + // (app has stopped, so submit on mgmt context) + ProcessTaskWrapper<Integer> t = SshEffectorTasks.codePidRunning(pid).machine(lh).newTask(); + mgmt.getExecutionManager().submit(t); + Assert.assertNotEquals(t.block().getExitCode(), (Integer)0); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityBuilder.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityBuilder.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityBuilder.java new file mode 100644 index 0000000..650c28c --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityBuilder.java @@ -0,0 +1,189 @@ +/* + * 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.entity.software.base.test.mysql; + +import java.io.File; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntityInitializer; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.internal.EntityLocal; +import org.apache.brooklyn.api.location.MachineLocation; +import org.apache.brooklyn.api.location.OsDetails; +import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; +import org.apache.brooklyn.entity.core.Attributes; +import org.apache.brooklyn.entity.software.base.lifecycle.MachineLifecycleEffectorTasks; +import org.apache.brooklyn.entity.stock.BasicStartable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.brooklyn.location.basic.BasicOsDetails.OsVersions; +import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.sensor.ssh.SshEffectorTasks; +import org.apache.brooklyn.util.core.task.DynamicTasks; +import org.apache.brooklyn.util.core.task.Tasks; +import org.apache.brooklyn.util.core.task.ssh.SshTasks; +import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; +import org.apache.brooklyn.util.ssh.BashCommands; +import org.apache.brooklyn.util.text.ComparableVersion; +import org.apache.brooklyn.util.time.Duration; +import org.apache.brooklyn.util.time.Time; + +import com.google.common.base.Predicates; +import com.google.common.base.Splitter; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.Iterables; + +public class DynamicToyMySqlEntityBuilder { + + private static final Logger log = LoggerFactory.getLogger(DynamicToyMySqlEntityBuilder.class); + + public static EntitySpec<? extends Entity> spec() { + return EntitySpec.create(BasicStartable.class).addInitializer(MySqlEntityInitializer.class); + } + + public static final String downloadUrl(Entity e, boolean isLocalhost) { + if (isLocalhost) { + for (int i=50; i>20; i--) { + String f = System.getProperty("user.home")+"/.brooklyn/repository/MySqlNode/5.5."+i+"/mysql-5.5."+i+"-osx10.6-x86_64.tar.gz"; + if (new File(f).exists()) + return "file://"+f; + } + } + // download + String version = "5.5.37"; + String osTag = getOsTag(e); + String mirrorUrl = "http://www.mirrorservice.org/sites/ftp.mysql.com/"; + return "http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-"+version+"-"+osTag+".tar.gz/from/"+mirrorUrl; + } + + public static final String installDir(Entity e, boolean isLocalhost) { + String url = downloadUrl(e, isLocalhost); + String archive = Iterables.find(Splitter.on('/').omitEmptyStrings().split(url), Predicates.containsPattern(".tar.gz")); + return archive.replace(".tar.gz", ""); + } + + public static final String dir(Entity e) { + return "/tmp/brooklyn-mysql-"+e.getId(); + } + + // copied from MySqlSshDriver + public static String getOsTag(Entity e) { + // e.g. "osx10.6-x86_64"; see http://www.mysql.com/downloads/mysql/#downloads + OsDetails os = ((SshMachineLocation)Iterables.getOnlyElement(e.getLocations())).getOsDetails(); + if (os == null) return "linux-glibc2.5-x86_64"; + if (os.isMac()) { + String osp1 = os.getVersion()==null ? "osx10.8" //lowest common denominator + : new ComparableVersion(os.getVersion()).isGreaterThanOrEqualTo(OsVersions.MAC_10_9) ? "osx10.9" + : "osx10.8"; //lowest common denominator + if (!os.is64bit()) { + throw new IllegalStateException("Only 64 bit MySQL build is available for OS X"); + } + return osp1+"-x86_64"; + } + //assume generic linux + String osp1 = "linux-glibc2.5"; + String osp2 = os.is64bit() ? "x86_64" : "i686"; + return osp1+"-"+osp2; + } + + public static class MySqlEntityInitializer implements EntityInitializer { + public void apply(final EntityLocal entity) { + new MachineLifecycleEffectorTasks() { + @Override + protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) { + DynamicTasks.queue( + SshEffectorTasks.ssh( + "mkdir "+dir(entity), + "cd "+dir(entity), + BashCommands.downloadToStdout(downloadUrl(entity, isLocalhost(machineS)))+" | tar xvz" + ).summary("download mysql").returning(SshTasks.returningStdoutLoggingInfo(log, true))); + if (isLinux(machineS)) { + DynamicTasks.queue(SshEffectorTasks.ssh(BashCommands.installPackage("libaio1"))); + } + DynamicTasks.queue( + SshEffectorTasks.put(".my.cnf") + .contents(String.format("[mysqld]\nbasedir=%s/%s\n", dir(entity), installDir(entity, isLocalhost(machineS)))), + SshEffectorTasks.ssh( + "cd "+dir(entity)+"/*", + "./scripts/mysql_install_db", + "./support-files/mysql.server start > out.log 2> err.log < /dev/null" + ).summary("setup and run mysql").returning(SshTasks.returningStdoutLoggingInfo(log, true))); + return "submitted start"; + } + protected void postStartCustom() { + // if it's still up after 5s assume we are good + Time.sleep(Duration.FIVE_SECONDS); + if (!DynamicTasks.queue(SshEffectorTasks.isPidFromFileRunning(dir(entity)+"/*/data/*.pid")).get()) { + // but if it's not up add a bunch of other info + log.warn("MySQL did not start: "+dir(entity)); + ProcessTaskWrapper<Integer> info = DynamicTasks.queue(SshEffectorTasks.ssh( + "cd "+dir(entity)+"/*", + "cat out.log", + "cat err.log > /dev/stderr")).block(); + log.info("STDOUT:\n"+info.getStdout()); + log.info("STDERR:\n"+info.getStderr()); + BrooklynTaskTags.addTagsDynamically(Tasks.current(), + BrooklynTaskTags.tagForStream("console (nohup stdout)", Suppliers.ofInstance(info.getStdout()), null), + BrooklynTaskTags.tagForStream("console (nohup stderr)", Suppliers.ofInstance(info.getStderr()), null)); + throw new IllegalStateException("MySQL appears not to be running"); + } + + // and set the PID + entity().setAttribute(Attributes.PID, + Integer.parseInt(DynamicTasks.queue(SshEffectorTasks.ssh("cat "+dir(entity)+"/*/data/*.pid")).block().getStdout().trim())); + + // TODO Without this, tests fail because nothing else sets serviceUp! + // Really should set this with a Feed that checks pid periodically. + // Should this instead be using SERVICE_NOT_UP_INDICATORS? + entity().setAttribute(Attributes.SERVICE_UP, true); + } + + @Override + protected String stopProcessesAtMachine() { + // TODO Where is best place to set? + // Really should set this with a Feed that checks pid periodically. + entity().setAttribute(Attributes.SERVICE_UP, false); + + Integer pid = entity().getAttribute(Attributes.PID); + if (pid==null) { + log.info("mysql not running"); + return "No pid -- is it running?"; + } + + DynamicTasks.queue(SshEffectorTasks.ssh( + "cd "+dir(entity)+"/*", + "./support-files/mysql.server stop" + ).summary("stop mysql")); + return "submitted stop"; + } + }.attachLifecycleEffectors(entity); + } + } + + private static boolean isLocalhost(Supplier<MachineLocation> machineS) { + return machineS.get() instanceof LocalhostMachine; + } + + private static boolean isLinux(Supplier<MachineLocation> machineS) { + return machineS.get().getMachineDetails().getOsDetails().isLinux(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityTest.java new file mode 100644 index 0000000..d676c00 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/mysql/DynamicToyMySqlEntityTest.java @@ -0,0 +1,58 @@ +/* + * 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.entity.software.base.test.mysql; + +import java.util.Arrays; + +import org.apache.brooklyn.api.entity.Entity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.util.collections.MutableMap; + + +public class DynamicToyMySqlEntityTest extends AbstractToyMySqlEntityTest { + + private static final Logger log = LoggerFactory.getLogger(DynamicToyMySqlEntityTest.class); + + protected Entity createMysql() { + Entity mysql = app.createAndManageChild(DynamicToyMySqlEntityBuilder.spec()); + log.debug("created "+mysql); + return mysql; + } + + // put right group on test (also help Eclipse IDE pick it up) + @Override + @Test(groups = "Integration") + public void testMySqlOnProvisioningLocation() throws Exception { + super.testMySqlOnProvisioningLocation(); + } + + @Test(groups="Integration") + public void testMySqlOnMachineLocation() throws Exception { + Entity mysql = createMysql(); + SshMachineLocation lh = targetLocation.obtain(MutableMap.of()); + + app.start(Arrays.asList(lh)); + checkStartsRunning(mysql); + checkIsRunningAndStops(mysql, lh); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/sensor/core/PortAttributeSensorAndConfigKeyTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/sensor/core/PortAttributeSensorAndConfigKeyTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/sensor/core/PortAttributeSensorAndConfigKeyTest.java new file mode 100644 index 0000000..66049b5 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/sensor/core/PortAttributeSensorAndConfigKeyTest.java @@ -0,0 +1,86 @@ +/* + * 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.entity.software.base.test.sensor.core; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; +import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl; +import org.testng.annotations.Test; +import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.sensor.core.PortAttributeSensorAndConfigKey; + +import com.google.common.collect.ImmutableList; + +public class PortAttributeSensorAndConfigKeyTest extends BrooklynAppUnitTestSupport { + + /* + * FIXME Fails because port is never released. Nothing calls PortSupplier.releasePort(int). + * The stacktrace below shows where it is obtained: + * + Daemon Thread [brooklyn-execmanager-XwLLLdS4-5] (Suspended (breakpoint at line 244 in LocalhostMachineProvisioningLocation$LocalhostMachine)) + LocalhostMachineProvisioningLocation$LocalhostMachine.obtainPort(PortRange) line: 244 + PortAttributeSensorAndConfigKey.convertConfigToSensor(PortRange, Entity) line: 78 + PortAttributeSensorAndConfigKey.convertConfigToSensor(Object, Entity) line: 1 + PortAttributeSensorAndConfigKey(AttributeSensorAndConfigKey<ConfigType,SensorType>).getAsSensorValue(Entity) line: 93 + ConfigToAttributes.apply(EntityLocal, AttributeSensorAndConfigKey<?,T>) line: 28 + ConfigToAttributes.apply(EntityLocal) line: 17 + SoftwareProcessDriverLifecycleEffectorTasks(MachineLifecycleEffectorTasks).preStartCustom(MachineLocation) line: 343 + SoftwareProcessDriverLifecycleEffectorTasks.preStartCustom(MachineLocation) line: 69 + MachineLifecycleEffectorTasks$6.run() line: 283 + */ + @Test(enabled=false, groups="Integration") // test is slow (for some reason - why?) + public void testStoppingEntityReleasesPortFromMachineForReuse() throws Exception { + LocalhostMachineProvisioningLocation loc = (LocalhostMachineProvisioningLocation) mgmt.getLocationRegistry().resolve("localhost"); + SshMachineLocation machine = loc.obtain(); + runStoppingEntityReleasesPortFromLocalhostForReuse(machine); + } + + @Test(groups="Integration") // test is slow (for some reason - why?) + public void testStoppingEntityReleasesPortFromLocalhostProvisioningLocationForReuse() throws Exception { + LocalhostMachineProvisioningLocation loc = (LocalhostMachineProvisioningLocation) mgmt.getLocationRegistry().resolve("localhost"); + runStoppingEntityReleasesPortFromLocalhostForReuse(loc); + } + + protected void runStoppingEntityReleasesPortFromLocalhostForReuse(Location loc) throws Exception { + MyEntity e1 = app.createAndManageChild(EntitySpec.create(MyEntity.class)); + e1.start(ImmutableList.of(loc)); + assertEquals(e1.getAttribute(MyEntity.MY_PORT), (Integer)47653); + + e1.stop(); + Entities.unmanage(e1); + MyEntity e2 = app.createAndManageChild(EntitySpec.create(MyEntity.class)); + e2.start(ImmutableList.of(loc)); + assertEquals(e2.getAttribute(MyEntity.MY_PORT), (Integer)47653); + } + + @ImplementedBy(MyEntityImpl.class) + public interface MyEntity extends EmptySoftwareProcess { + PortAttributeSensorAndConfigKey MY_PORT = new PortAttributeSensorAndConfigKey("myport", "", "47653"); + } + + public static class MyEntityImpl extends EmptySoftwareProcessImpl implements MyEntity { + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/ssh/SshCommandIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/ssh/SshCommandIntegrationTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/ssh/SshCommandIntegrationTest.java new file mode 100644 index 0000000..c51725c --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/ssh/SshCommandIntegrationTest.java @@ -0,0 +1,126 @@ +/* + * 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.entity.software.base.test.ssh; + +import static org.testng.Assert.assertTrue; + +import java.io.File; + +import org.apache.brooklyn.api.effector.Effector; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.internal.EntityLocal; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.sensor.AttributeSensor; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.effector.core.Effectors; +import org.apache.brooklyn.entity.core.Attributes; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.sensor.core.Sensors; +import org.apache.brooklyn.sensor.ssh.SshCommandEffector; +import org.apache.brooklyn.sensor.ssh.SshCommandSensor; +import org.apache.brooklyn.test.EntityTestUtils; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.time.Duration; +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 com.google.common.collect.ImmutableList; + +public class SshCommandIntegrationTest { + + final static AttributeSensor<String> SENSOR_STRING = Sensors.newStringSensor("aString", ""); + final static AttributeSensor<Integer> SENSOR_INT = Sensors.newIntegerSensor("aLong", ""); + final static Effector<String> EFFECTOR_SAY_HI = Effectors.effector(String.class, "sayHi").buildAbstract(); + + private TestApplication app; + private SshMachineLocation machine; + private EntityLocal entity; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + app = TestApplication.Factory.newManagedInstanceForTests(); + machine = app.newLocalhostProvisioningLocation().obtain(); + entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(machine)); + app.start(ImmutableList.<Location>of()); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + @Test(groups="Integration") + public void testSshSensor() throws Exception { + File tempFile = File.createTempFile("testSshCommand", "txt"); + tempFile.deleteOnExit(); + new SshCommandSensor<String>(ConfigBag.newInstance() + .configure(SshCommandSensor.SENSOR_PERIOD, Duration.millis(100)) + .configure(SshCommandSensor.SENSOR_NAME, SENSOR_STRING.getName()) + .configure(SshCommandSensor.SENSOR_COMMAND, "echo foo > "+tempFile.getAbsolutePath()+"\n" + + "wc "+tempFile.getAbsolutePath())) + .apply(entity); + entity.setAttribute(Attributes.SERVICE_UP, true); + + String val = EntityTestUtils.assertAttributeEventuallyNonNull(entity, SENSOR_STRING); + assertTrue(val.contains("1"), "val="+val); + String[] counts = val.trim().split("\\s+"); + Assert.assertEquals(counts.length, 4, "val="+val); + Assert.assertEquals(counts[0], "1", "val="+val); + } + + @Test(groups="Integration") + public void testSshEffector() throws Exception { + File tempFile = File.createTempFile("testSshCommand", "txt"); + tempFile.deleteOnExit(); + new SshCommandEffector(ConfigBag.newInstance() + .configure(SshCommandEffector.EFFECTOR_NAME, "sayHi") + .configure(SshCommandEffector.EFFECTOR_COMMAND, "echo hi")) + .apply(entity); + + String val = entity.invoke(EFFECTOR_SAY_HI, MutableMap.<String,String>of()).get(); + Assert.assertEquals(val.trim(), "hi", "val="+val); + } + + @Test(groups="Integration") + public void testSshEffectorWithParameters() throws Exception { + File tempFile = File.createTempFile("testSshCommand", "txt"); + tempFile.deleteOnExit(); + new SshCommandEffector(ConfigBag.newInstance() + .configure(SshCommandEffector.EFFECTOR_NAME, "sayHi") + .configure(SshCommandEffector.EFFECTOR_COMMAND, "echo $foo") + .configure(SshCommandEffector.EFFECTOR_PARAMETER_DEFS, + MutableMap.<String,Object>of("foo", MutableMap.of("defaultValue", "hi")))) + .apply(entity); + + String val; + // explicit value + val = entity.invoke(EFFECTOR_SAY_HI, MutableMap.<String,String>of("foo", "bar")).get(); + Assert.assertEquals(val.trim(), "bar", "val="+val); + + // default value + val = entity.invoke(EFFECTOR_SAY_HI, MutableMap.<String,String>of()).get(); + Assert.assertEquals(val.trim(), "hi", "val="+val); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/entity/system_service/SystemServiceEnricherTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/system_service/SystemServiceEnricherTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/system_service/SystemServiceEnricherTest.java new file mode 100644 index 0000000..87ad639 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/system_service/SystemServiceEnricherTest.java @@ -0,0 +1,95 @@ +/* + * 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.entity.system_service; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.sensor.EnricherSpec; +import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; +import org.apache.brooklyn.effector.core.EffectorTasks; +import org.apache.brooklyn.entity.core.Attributes; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.entity.core.EntityPredicates; +import org.apache.brooklyn.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess; +import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcessImpl; +import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcessSshDriver; +import org.apache.brooklyn.entity.system_service.SystemServiceEnricher; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.apache.brooklyn.location.basic.SshMachineLocation; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.ssh.BashCommands; +import org.apache.brooklyn.util.time.Duration; + +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class SystemServiceEnricherTest extends BrooklynAppLiveTestSupport { + //requires /etc/init.d OS, for example CentOS 6.5 + private static final String LOCATION_SPEC = "named:service-live-test-location"; + private JcloudsLocation location; + + @Override + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + location = (JcloudsLocation) mgmt.getLocationRegistry().resolve(LOCATION_SPEC); + } + + @Test(groups = "Live") + public void testRestartLaunchesService() { + String launchCmd = "nohup bash -c \"echo \\$\\$ > $PID_FILE; while true; do sleep 1000; done\" &"; + EntitySpec<VanillaSoftwareProcess> procSpec = EntitySpec.create(VanillaSoftwareProcess.class) + .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, launchCmd) + .enricher(EnricherSpec.create(SystemServiceEnricher.class)); + VanillaSoftwareProcess proc = app.createAndManageChild(procSpec); + app.start(ImmutableList.of(location)); + + waitHealthy(proc); + + SshMachineLocation machine = EffectorTasks.getSshMachine(proc); + String pidFile = getPidFile(proc); + String killCmd = "kill -9 `cat " + pidFile + "`"; + machine.execCommands("kill process", ImmutableList.of(killCmd)); + + waitFailed(proc); + + int restartCode = machine.execCommands("restart machine", ImmutableList.of(BashCommands.sudo("/sbin/shutdown -r now"))); + assertEquals(restartCode, 0); + + waitHealthy(proc); + } + + private String getPidFile(VanillaSoftwareProcess proc) { + VanillaSoftwareProcessImpl impl = (VanillaSoftwareProcessImpl)Entities.deproxy(proc); + return ((VanillaSoftwareProcessSshDriver)impl.getDriver()).getPidFile(); + } + + private void waitFailed(VanillaSoftwareProcess proc) { + Asserts.eventually(ImmutableMap.of("timeout", Duration.FIVE_MINUTES), Suppliers.ofInstance(proc), EntityPredicates.attributeEqualTo(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE)); + } + + private void waitHealthy(VanillaSoftwareProcess proc) { + Asserts.eventually(ImmutableMap.of("timeout", Duration.FIVE_MINUTES), Suppliers.ofInstance(proc), EntityPredicates.attributeEqualTo(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsEc2LiveTest.java b/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsEc2LiveTest.java deleted file mode 100644 index 39f787f..0000000 --- a/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsEc2LiveTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.location.basic; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.location.MachineDetails; -import org.apache.brooklyn.api.location.OsDetails; -import org.apache.brooklyn.entity.trait.Startable; -import org.apache.brooklyn.test.EntityTestUtils; -import org.apache.brooklyn.util.collections.MutableMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableList; - -import brooklyn.entity.AbstractEc2LiveTest; -import brooklyn.entity.basic.EmptySoftwareProcess; - -// This test really belongs in brooklyn-location but depends on AbstractEc2LiveTest in brooklyn-software-base -public class MachineDetailsEc2LiveTest extends AbstractEc2LiveTest { - - private static final Logger LOG = LoggerFactory.getLogger(MachineDetailsEc2LiveTest.class); - private static final int TIMEOUT_MS = 1000 * 60 * 10; // ten minutes - - @Override - protected void doTest(Location loc) throws Exception { - Entity testEntity = app.createAndManageChild(EntitySpec.create(EmptySoftwareProcess.class)); - app.start(ImmutableList.of(loc)); - EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), - testEntity, Startable.SERVICE_UP, true); - - SshMachineLocation sshLoc = Locations.findUniqueSshMachineLocation(testEntity.getLocations()).get(); - MachineDetails machine = app.getExecutionContext() - .submit(BasicMachineDetails.taskForSshMachineLocation(sshLoc)) - .getUnchecked(); - LOG.info("Found the following at {}: {}", loc, machine); - assertNotNull(machine); - OsDetails details = machine.getOsDetails(); - assertNotNull(details); - assertNotNull(details.getArch()); - assertNotNull(details.getName()); - assertNotNull(details.getVersion()); - assertFalse(details.getArch().startsWith("architecture:")); - assertFalse(details.getName().startsWith("name:")); - assertFalse(details.getVersion().startsWith("version:")); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsGoogleComputeLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsGoogleComputeLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsGoogleComputeLiveTest.java deleted file mode 100644 index 6f2a06a..0000000 --- a/software/base/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsGoogleComputeLiveTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.location.basic; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.location.MachineDetails; -import org.apache.brooklyn.api.location.OsDetails; -import org.apache.brooklyn.entity.trait.Startable; -import org.apache.brooklyn.test.EntityTestUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableList; - -import brooklyn.entity.AbstractGoogleComputeLiveTest; -import brooklyn.entity.basic.EmptySoftwareProcess; - -// This test really belongs in brooklyn-location but depends on AbstractGoogleComputeLiveTest in brooklyn-software-base -public class MachineDetailsGoogleComputeLiveTest extends AbstractGoogleComputeLiveTest { - - private static final Logger LOG = LoggerFactory.getLogger(MachineDetailsGoogleComputeLiveTest.class); - - @Override - protected void doTest(Location loc) throws Exception { - Entity testEntity = app.createAndManageChild(EntitySpec.create(EmptySoftwareProcess.class)); - app.start(ImmutableList.of(loc)); - EntityTestUtils.assertAttributeEqualsEventually(testEntity, Startable.SERVICE_UP, true); - - SshMachineLocation sshLoc = Locations.findUniqueSshMachineLocation(testEntity.getLocations()).get(); - MachineDetails machine = app.getExecutionContext() - .submit(BasicMachineDetails.taskForSshMachineLocation(sshLoc)) - .getUnchecked(); - LOG.info("Found the following at {}: {}", loc, machine); - assertNotNull(machine); - OsDetails details = machine.getOsDetails(); - assertNotNull(details); - assertNotNull(details.getArch()); - assertNotNull(details.getName()); - assertNotNull(details.getVersion()); - assertFalse(details.getArch().startsWith("architecture:")); - assertFalse(details.getName().startsWith("name:")); - assertFalse(details.getVersion().startsWith("version:")); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java deleted file mode 100644 index 1651f15..0000000 --- a/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.location.basic; - -import static org.testng.Assert.assertEquals; - -import org.apache.brooklyn.core.internal.BrooklynProperties; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; -import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; -import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; -import org.apache.brooklyn.core.test.entity.TestApplication; -import org.apache.brooklyn.entity.core.Entities; -import org.apache.brooklyn.location.jclouds.JcloudsLocation; - -import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.apache.brooklyn.location.jclouds.JcloudsWinRmMachineLocation; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -public class WinRmMachineLocationLiveTest { - - // FIXME failing locally with: - // Caused by: Traceback (most recent call last): - // File "__pyclasspath__/winrm/__init__.py", line 40, in run_cmd - // File "__pyclasspath__/winrm/protocol.py", line 118, in open_shell - // File "__pyclasspath__/winrm/protocol.py", line 190, in send_message - // File "__pyclasspath__/winrm/transport.py", line 112, in send_message - // winrm.exceptions.WinRMTransportError: 500 WinRMTransport. [Errno 20001] getaddrinfo failed - // at org.python.core.PyException.doRaise(PyException.java:226) - - private static final Logger LOG = LoggerFactory.getLogger(BrooklynAppLiveTestSupport.class); - - protected JcloudsLocation loc; - protected TestApplication app; - protected ManagementContextInternal mgmt; - - private JcloudsWinRmMachineLocation machine; - - @BeforeClass(alwaysRun=true) - public void setUpClass() throws Exception { - mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault()); - JcloudsLocation loc = (JcloudsLocation) mgmt.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-2", ImmutableMap.of( - "inboundPorts", ImmutableList.of(5985, 3389), - "displayName", "AWS Oregon (Windows)", - "imageId", "us-west-2/ami-8fd3f9bf", - "hardwareId", "m3.medium", - "useJcloudsSshInit", false)); - machine = (JcloudsWinRmMachineLocation) loc.obtain(); - } - - @AfterClass(alwaysRun=true) - public void tearDownClass() throws Exception { - try { - if (machine != null) loc.release(machine); - if (mgmt != null) Entities.destroyAll(mgmt); - } catch (Throwable t) { - LOG.error("Caught exception in tearDown method", t); - } finally { - mgmt = null; - } - } - - @Test(groups="Live") - public void testExecScript() throws Exception { - WinRmToolResponse response = machine.executeScript("echo true"); - assertEquals(response.getStatusCode(), 0); - assertEquals(response.getStdErr(), ""); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationTest.java b/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationTest.java deleted file mode 100644 index ea00d15..0000000 --- a/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.location.basic; - -import static org.testng.Assert.assertEquals; - -import org.apache.brooklyn.api.location.LocationSpec; -import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; -import org.apache.brooklyn.entity.core.BrooklynConfigKeys; -import org.apache.brooklyn.util.net.Networking; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public class WinRmMachineLocationTest extends BrooklynAppUnitTestSupport { - - @Test - public void testConfigurePrivateAddresses() throws Exception { - WinRmMachineLocation host = mgmt.getLocationManager().createLocation(LocationSpec.create(WinRmMachineLocation.class) - .configure("address", Networking.getLocalHost()) - .configure(WinRmMachineLocation.PRIVATE_ADDRESSES, ImmutableList.of("1.2.3.4")) - .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)); - - assertEquals(host.getPrivateAddresses(), ImmutableSet.of("1.2.3.4")); - } -}
