You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/08/19 23:21:13 UTC

[39/62] [abbrv] incubator-brooklyn git commit: rename core’s o.a.b.location to o.a.b.core.location

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
new file mode 100644
index 0000000..c10f376
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
@@ -0,0 +1,141 @@
+/*
+ * 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.core.location;
+
+import java.net.InetAddress;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.location.HardwareDetails;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.location.MachineDetails;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.api.location.PortSupplier;
+import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.BasicHardwareDetails;
+import org.apache.brooklyn.core.location.BasicMachineDetails;
+import org.apache.brooklyn.core.location.BasicOsDetails;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.net.Networking;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+
+/** Location for use in dev/test, defining custom start/stop support, and/or tweaking the ports which are permitted to be available
+ * (using setPermittedPorts(Iterable))
+ */
+public class SimulatedLocation extends AbstractLocation implements MachineProvisioningLocation<MachineLocation>, MachineLocation, PortSupplier {
+
+    private static final long serialVersionUID = 1L;
+    
+    private static final InetAddress address;
+    static {
+        address = Networking.getLocalHost();
+    }
+
+    Iterable<Integer> permittedPorts = PortRanges.fromString("1+");
+    Set<Integer> usedPorts = Sets.newLinkedHashSet();
+
+    public SimulatedLocation() {
+        this(MutableMap.<String,Object>of());
+    }
+    public SimulatedLocation(Map<String,? extends Object> flags) {
+        super(flags);
+    }
+    
+    @Override
+    public SimulatedLocation newSubLocation(Map<?,?> newFlags) {
+        // TODO shouldn't have to copy config bag as it should be inherited (but currently it is not used inherited everywhere; just most places)
+        return getManagementContext().getLocationManager().createLocation(LocationSpec.create(getClass())
+                .parent(this)
+                .configure(config().getLocalBag().getAllConfig())  // FIXME Should this just be inherited?
+                .configure(newFlags));
+    }
+
+    public MachineLocation obtain(Map<?,?> flags) {
+        return this;
+    }
+
+    public void release(MachineLocation machine) {
+    }
+
+    public Map<String,Object> getProvisioningFlags(Collection<String> tags) {
+        return MutableMap.<String,Object>of();
+    }
+    
+    public InetAddress getAddress() {
+        return address;
+    }
+
+    @Override
+    public String getHostname() {
+        String hostname = address.getHostName();
+        return (hostname == null || hostname.equals(address.getHostAddress())) ? null : hostname;
+    }
+    
+    @Override
+    public Set<String> getPublicAddresses() {
+        return ImmutableSet.of(address.getHostAddress());
+    }
+    
+    @Override
+    public Set<String> getPrivateAddresses() {
+        return ImmutableSet.of();
+    }
+
+    public synchronized boolean obtainSpecificPort(int portNumber) {
+        if (!Iterables.contains(permittedPorts, portNumber)) return false;
+        if (usedPorts.contains(portNumber)) return false;
+        usedPorts.add(portNumber);
+        return true;
+    }
+
+    public synchronized int obtainPort(PortRange range) {
+        for (int p: range)
+            if (obtainSpecificPort(p)) return p;
+        return -1;
+    }
+
+    public synchronized void releasePort(int portNumber) {
+        usedPorts.remove(portNumber);
+    }
+    
+    public synchronized void setPermittedPorts(Iterable<Integer> ports) {
+        permittedPorts  = ports;
+    }
+
+    @Override
+    public OsDetails getOsDetails() {
+        return getMachineDetails().getOsDetails();
+    }
+
+    @Override
+    public MachineDetails getMachineDetails() {
+        HardwareDetails hardwareDetails = new BasicHardwareDetails(null, null);
+        OsDetails osDetails = BasicOsDetails.Factory.ANONYMOUS_LINUX;
+        return new BasicMachineDetails(hardwareDetails, osDetails);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/TestPortSupplierLocation.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/TestPortSupplierLocation.java b/core/src/test/java/org/apache/brooklyn/core/location/TestPortSupplierLocation.java
new file mode 100644
index 0000000..6b64cc1
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/TestPortSupplierLocation.java
@@ -0,0 +1,90 @@
+/*
+ * 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.core.location;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.sensor.core.PortAttributeSensorAndConfigKey;
+import org.apache.brooklyn.sensor.feed.ConfigToAttributes;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestPortSupplierLocation extends BrooklynAppUnitTestSupport {
+
+    SimulatedLocation loc;
+    PortAttributeSensorAndConfigKey ps;
+    TestEntity entity;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        loc = app.newSimulatedLocation();
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        app.start(ImmutableList.of(loc));
+        
+        ps = new PortAttributeSensorAndConfigKey("some.port", "for testing", "1234+");
+    }
+
+    @Test
+    public void testObtainsPort() throws Exception {
+        ConfigToAttributes.apply(entity, ps);
+        
+        int p = entity.getAttribute(ps);
+        assertEquals(p, 1234);
+        
+        //sensor access should keep the same value
+        p = entity.getAttribute(ps);
+        assertEquals(p, 1234);
+    }
+    
+    @Test
+    public void testRepeatedConvertAccessIncrements() throws Exception {
+        int p = ps.getAsSensorValue(entity);
+        assertEquals(p, 1234);
+
+        //but direct access should see it as being reserved (not required behaviour, but it is the current behaviour)
+        int p2 = ps.getAsSensorValue(entity);
+        assertEquals(p2, 1235);
+    }
+
+    @Test
+    public void testNullBeforeSetting() throws Exception {
+        // currently getting the attribute before explicitly setting return null; i.e. no "auto-set" -- 
+        // but this behaviour may be changed
+        Integer p = entity.getAttribute(ps);
+        assertEquals(p, null);
+    }
+
+    @Test
+    public void testSimulatedRestrictedPermitted() throws Exception {
+        loc.setPermittedPorts(PortRanges.fromString("1240+"));
+        
+        ConfigToAttributes.apply(entity, ps);
+        int p = entity.getAttribute(ps);
+        assertEquals((int)p, 1240);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtilsTest.java b/core/src/test/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtilsTest.java
new file mode 100644
index 0000000..17a24b0
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtilsTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.core.location.access;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.location.SupportsPortForwarding;
+import org.apache.brooklyn.core.location.access.BrooklynAccessUtils;
+import org.apache.brooklyn.core.location.access.PortForwardManager;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.net.Cidr;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.net.HostAndPort;
+
+public class BrooklynAccessUtilsTest extends BrooklynAppUnitTestSupport {
+
+    protected PortForwardManager pfm;
+    private TestEntity entity;
+
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        pfm = (PortForwardManager) mgmt.getLocationRegistry().resolve("portForwardManager(scope=global)");
+    }
+    
+    @Test
+    public void testBrooklynAccessibleAddressFindsPreexistingMapping() throws Exception {
+        final int privatePort = 8080;
+        final String publicNatIp = "1.2.3.4";
+        final int publicNatPort = 12000;
+        
+        SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure(SshMachineLocation.TCP_PORT_MAPPINGS, ImmutableMap.of(privatePort, publicNatIp+":"+publicNatPort)));
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm)
+                .location(machine));
+
+        assertEquals(BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort), HostAndPort.fromParts(publicNatIp, publicNatPort));
+    }
+    
+    @Test
+    public void testBrooklynAccessibleAddressUsesPrivateHostPortIfNoMapping() throws Exception {
+        final String privateIp = "127.1.2.3";
+        final int privatePort = 8080;
+        
+        SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class));
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm)
+                .location(machine));
+        entity.setAttribute(Attributes.HOSTNAME, privateIp);
+
+        assertEquals(BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort), HostAndPort.fromParts(privateIp, privatePort));
+    }
+    
+    @Test
+    public void testBrooklynAccessibleAddressFailsIfNoMappingAndNoHostname() throws Exception {
+        final int privatePort = 8080;
+        
+        SshMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class));
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm)
+                .location(machine));
+
+        try {
+            BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort);
+            fail();
+        } catch (IllegalStateException e) {
+            if (!e.toString().contains("no host.name")) throw e;
+            // success
+        }
+    }
+    
+    @Test
+    public void testBrooklynAccessibleAddressRequestsNewPortForwarding() throws Exception {
+        final int privatePort = 8080;
+        
+        RecordingSupportsPortForwarding machine = mgmt.getLocationManager().createLocation(LocationSpec.create(RecordingSupportsPortForwarding.class));
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .configure(BrooklynAccessUtils.PORT_FORWARDING_MANAGER, pfm)
+                .configure(BrooklynAccessUtils.MANAGEMENT_ACCESS_CIDR, Cidr.UNIVERSAL)
+                .location(machine));
+
+        HostAndPort result = BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, privatePort);
+        HostAndPort portForwarded = machine.mappings.get(privatePort);
+        assertNotNull(portForwarded);
+        assertEquals(result, portForwarded);
+    }
+    
+    @SuppressWarnings("serial") // TODO location should not be serializable; will be changed in future release
+    public static class RecordingSupportsPortForwarding extends SshMachineLocation implements SupportsPortForwarding {
+        protected final String publicIp = "1.2.3.4";
+        protected final Map<Integer, HostAndPort> mappings = Maps.newConcurrentMap();
+        private final AtomicInteger nextPort = new AtomicInteger(12000);
+        
+        
+        @Override
+        public HostAndPort getSocketEndpointFor(Cidr accessor, int privatePort) {
+            HostAndPort result = mappings.get(privatePort);
+            if (result == null) {
+                int publicPort = nextPort.getAndIncrement();
+                result = HostAndPort.fromParts(publicIp, publicPort);
+                mappings.put(privatePort, result);
+            }
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerLocationResolverTest.java
new file mode 100644
index 0000000..c911236
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerLocationResolverTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.core.location.access;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.location.access.PortForwardManager;
+import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class PortForwardManagerLocationResolverTest {
+
+    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 testReturnsSameInstanceBasedOnScope() {
+        Location global1 = resolve("portForwardManager()"); // defaults to global
+        Location global2 = resolve("portForwardManager()");
+        Location global3 = resolve("portForwardManager(scope=global)");
+        assertSame(global1, global2);
+        assertSame(global1, global3);
+        
+        Location a1 = resolve("portForwardManager(scope=a)");
+        Location a2 = resolve("portForwardManager(scope=a)");
+        assertSame(a1, a2);
+        assertNotSame(global1, a1);
+        
+        Location b1 = resolve("portForwardManager(scope=b)");
+        assertNotSame(global1, b1);
+        assertNotSame(a1, b1);
+    }
+
+    private Location resolve(String val) {
+        Location l = managementContext.getLocationRegistry().resolve(val);
+        Assert.assertNotNull(l);
+        return l;
+    }
+    
+    private void assertSame(Location loc1, Location loc2) {
+        Assert.assertNotNull(loc1);
+        Assert.assertTrue(loc1 instanceof PortForwardManager, "loc1="+loc1);
+        Assert.assertSame(loc1, loc2);
+    }
+    
+    private void assertNotSame(Location loc1, Location loc2) {
+        Assert.assertNotNull(loc1);
+        Assert.assertNotNull(loc2);
+        Assert.assertTrue(loc1 instanceof PortForwardManager, "loc1="+loc1);
+        Assert.assertTrue(loc2 instanceof PortForwardManager, "loc2="+loc2);
+        Assert.assertNotSame(loc1, loc2);
+        Assert.assertNotEquals(((PortForwardManager)loc1).getId(), ((PortForwardManager)loc2).getId());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerRebindTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerRebindTest.java b/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerRebindTest.java
new file mode 100644
index 0000000..f123342
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerRebindTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.core.location.access;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+
+import java.io.File;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.ha.MementoCopyMode;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.location.access.PortForwardManager;
+import org.apache.brooklyn.core.mgmt.persist.BrooklynPersistenceUtils;
+import org.apache.brooklyn.core.mgmt.persist.FileBasedObjectStore;
+import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore;
+import org.apache.brooklyn.core.mgmt.rebind.RebindOptions;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestUtils;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
+import org.apache.brooklyn.sensor.core.Sensors;
+import org.apache.brooklyn.util.net.Networking;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.text.Identifiers;
+import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
+
+public class PortForwardManagerRebindTest extends RebindTestFixtureWithApp {
+
+    private static final Logger log = LoggerFactory.getLogger(PortForwardManagerRebindTest.class);
+
+    private String machineAddress = "1.2.3.4";
+    private SshMachineLocation origSimulatedMachine;
+
+    @Override
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        super.setUp();
+
+        origSimulatedMachine = origManagementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure("address", Networking.getInetAddressWithFixedName(machineAddress))
+                .configure("port", 1234)
+                .configure("user", "myuser"));
+    }
+    
+    @Test
+    public void testAssociationPreservedOnRebind() throws Exception {
+        String publicIpId = "5.6.7.8";
+        String publicAddress = "5.6.7.8";
+
+        TestEntity origEntity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntity.class));
+        PortForwardManager origPortForwardManager = origEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+
+        // We first wait for persisted, to ensure that it is the PortForwardManager.onChanged that is causing persistence.
+        RebindTestUtils.waitForPersisted(origApp);
+        origPortForwardManager.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40080), origSimulatedMachine, 80);
+     
+        newApp = rebind();
+        
+        // After rebind, confirm that lookups still work
+        TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+        Location newSimulatedMachine = newApp.getManagementContext().getLocationManager().getLocation(origSimulatedMachine.getId());
+        PortForwardManager newPortForwardManager = newEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+        
+        assertEquals(newPortForwardManager.lookup(newSimulatedMachine, 80), HostAndPort.fromParts(publicAddress, 40080));
+        assertEquals(newPortForwardManager.lookup(publicIpId, 80), HostAndPort.fromParts(publicAddress, 40080));
+    }
+    
+    @Test
+    public void testAssociationPreservedOnStateExport() throws Exception {
+        String publicIpId = "5.6.7.8";
+        String publicAddress = "5.6.7.8";
+
+        TestEntity origEntity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntity.class));
+        PortForwardManager origPortForwardManager = origEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+
+        origPortForwardManager.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40080), origSimulatedMachine, 80);
+
+        String label = origManagementContext.getManagementNodeId()+"-"+Time.makeDateSimpleStampString();
+        PersistenceObjectStore targetStore = BrooklynPersistenceUtils.newPersistenceObjectStore(origManagementContext, null, 
+            "tmp/web-persistence-"+label+"-"+Identifiers.makeRandomId(4));
+        File dir = ((FileBasedObjectStore)targetStore).getBaseDir();
+        // only register the parent dir because that will prevent leaks for the random ID
+        Os.deleteOnExitEmptyParentsUpTo(dir.getParentFile(), dir.getParentFile());
+        BrooklynPersistenceUtils.writeMemento(origManagementContext, targetStore, MementoCopyMode.LOCAL);            
+
+        RebindTestUtils.waitForPersisted(origApp);
+        log.info("Using manual export dir "+dir+" for rebind instead of "+mementoDir);
+        newApp = rebind(RebindOptions.create().mementoDir(dir));
+        
+        // After rebind, confirm that lookups still work
+        TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+        Location newSimulatedMachine = newApp.getManagementContext().getLocationManager().getLocation(origSimulatedMachine.getId());
+        PortForwardManager newPortForwardManager = newEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+        
+        assertEquals(newPortForwardManager.lookup(newSimulatedMachine, 80), HostAndPort.fromParts(publicAddress, 40080));
+        assertEquals(newPortForwardManager.lookup(publicIpId, 80), HostAndPort.fromParts(publicAddress, 40080));
+        
+        // delete the dir here, to be more likely not to leak it on failure
+        newManagementContext.getRebindManager().stop();
+        Os.deleteRecursively(dir);
+    }
+    
+    @Test
+    public void testAssociationPreservedOnRebindLegacy() throws Exception {
+        String publicIpId = "5.6.7.8";
+        String publicAddress = "5.6.7.8";
+
+        TestEntity origEntity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntity.class));
+        PortForwardManager origPortForwardManager = origEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+
+        // We first wait for persisted, to ensure that it is the PortForwardManager.onChanged that is causing persistence.
+        RebindTestUtils.waitForPersisted(origApp);
+        origPortForwardManager.recordPublicIpHostname(publicIpId, publicAddress);
+        origPortForwardManager.acquirePublicPortExplicit(publicIpId, 40080);
+        origPortForwardManager.associate(publicIpId, 40080, origSimulatedMachine, 80);
+     
+        newApp = rebind();
+        
+        // After rebind, confirm that lookups still work
+        TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+        Location newSimulatedMachine = newApp.getManagementContext().getLocationManager().getLocation(origSimulatedMachine.getId());
+        PortForwardManager newPortForwardManager = newEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+        
+        assertEquals(newPortForwardManager.getPublicIpHostname(publicIpId), publicAddress);
+        assertEquals(newPortForwardManager.lookup(newSimulatedMachine, 80), HostAndPort.fromParts(publicAddress, 40080));
+        assertEquals(newPortForwardManager.lookup(publicIpId, 80), HostAndPort.fromParts(publicAddress, 40080));
+    }
+    
+    @Test
+    public void testAcquirePortCounterPreservedOnRebindLegacy() throws Exception {
+        String publicIpId = "5.6.7.8";
+
+        TestEntity origEntity = origApp.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntity.class));
+        PortForwardManager origPortForwardManager = origEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+
+        // We first wait for persisted, to ensure that it is the PortForwardManager.onChanged that is causing persistence.
+        RebindTestUtils.waitForPersisted(origApp);
+        int acquiredPort = origPortForwardManager.acquirePublicPort(publicIpId);
+     
+        newApp = rebind();
+        
+        // After rebind, confirm that lookups still work
+        TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));
+        PortForwardManager newPortForwardManager = newEntity.getConfig(MyEntity.PORT_FORWARD_MANAGER);
+        
+        int acquiredPort2 = newPortForwardManager.acquirePublicPort(publicIpId);
+        assertNotEquals(acquiredPort, acquiredPort2);
+    }
+    
+    public static class MyEntity extends TestEntityImpl {
+        public static final ConfigKey<PortForwardManager> PORT_FORWARD_MANAGER = ConfigKeys.newConfigKey(PortForwardManager.class, "myentity.portForwardManager");
+        public static final AttributeSensor<PortForwardManager> PORT_FORWARD_MANAGER_LIVE = Sensors.newSensor(PortForwardManager.class, "myentity.portForwardManager.live");
+
+        @Override
+        public void init() {
+            super.init();
+            
+            if (getConfig(PORT_FORWARD_MANAGER) == null) {
+                PortForwardManager pfm = (PortForwardManager) getManagementContext().getLocationRegistry().resolve("portForwardManager(scope=global)");
+                setAttribute(PORT_FORWARD_MANAGER_LIVE, pfm);
+                setConfig(PORT_FORWARD_MANAGER, pfm);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerTest.java
new file mode 100644
index 0000000..f3a8693
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/access/PortForwardManagerTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.core.location.access;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNull;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.util.net.Networking;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.location.access.PortForwardManager;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+
+import com.google.common.base.Predicate;
+import com.google.common.net.HostAndPort;
+
+public class PortForwardManagerTest extends BrooklynAppUnitTestSupport {
+
+    private static final Logger log = LoggerFactory.getLogger(PortForwardManagerTest.class);
+
+    private Map<HostAndPort, HostAndPort> portMapping;
+    private SshMachineLocation machine1;
+    private SshMachineLocation machine2;
+    private PortForwardManager pfm;
+    
+    @Override
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        super.setUp();
+
+        pfm = (PortForwardManager) mgmt.getLocationRegistry().resolve("portForwardManager(scope=global)");
+
+        machine1 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure("address", Networking.getInetAddressWithFixedName("1.2.3.4"))
+                .configure("port", 1234)
+                .configure("user", "myuser"));
+        machine2 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure("address", Networking.getInetAddressWithFixedName("1.2.3.5"))
+                .configure("port", 1234)
+                .configure("user", "myuser"));
+    }
+    
+    @Test
+    public void testAssociateWithLocation() throws Exception {
+        String publicIpId = "myipid";
+        String publicAddress = "5.6.7.8";
+
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40080), machine1, 80);
+     
+        assertEquals(pfm.lookup(machine1, 80), HostAndPort.fromParts(publicAddress, 40080));
+        assertEquals(pfm.lookup(publicIpId, 80), HostAndPort.fromParts(publicAddress, 40080));
+    }
+    
+    @Test
+    public void testAssociateWithoutLocation() throws Exception {
+        String publicIpId = "myipid";
+        String publicAddress = "5.6.7.8";
+
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40080), 80);
+     
+        assertEquals(pfm.lookup(publicIpId, 80), HostAndPort.fromParts(publicAddress, 40080));
+        assertNull(pfm.lookup(machine1, 80));
+    }
+    
+    @Test
+    public void testAcquirePortDoesNotReturnDuplicate() throws Exception {
+        String publicIpId = "myipid";
+
+        int port1 = pfm.acquirePublicPort(publicIpId);
+        int port2 = pfm.acquirePublicPort(publicIpId);
+        assertNotEquals(port1, port2);
+    }
+    
+    @Test
+    public void testAcquirePortRespectsStartingPortNumber() throws Exception {
+        BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+        props.put(PortForwardManager.PORT_FORWARD_MANAGER_STARTING_PORT, 1234);
+        LocalManagementContextForTests mgmt2 = new LocalManagementContextForTests(props);
+        try {
+            PortForwardManager pfm2 = (PortForwardManager) mgmt2.getLocationRegistry().resolve("portForwardManager(scope=global)");
+            int port = pfm2.acquirePublicPort("myipid");
+            assertEquals(port, 1234);
+        } finally {
+            Entities.destroyAll(mgmt2);
+        }
+    }
+    
+    @Test
+    public void testForgetPortMapping() throws Exception {
+        String publicIpId = "myipid";
+        String publicAddress = "5.6.7.8";
+
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40080), machine1, 80);
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40081), machine1, 81);
+        pfm.forgetPortMapping(publicIpId, 40080);
+        
+        assertNull(pfm.lookup(publicIpId, 80));
+        assertNull(pfm.lookup(machine1, 80));
+        assertEquals(pfm.lookup(publicIpId, 81), HostAndPort.fromParts(publicAddress, 40081));
+        assertEquals(pfm.lookup(publicIpId, 81), HostAndPort.fromParts(publicAddress, 40081));
+    }
+    
+    @Test
+    public void testForgetPortMappingsOfMachine() throws Exception {
+        String publicIpId = "myipid";
+        String publicIpId2 = "myipid2";
+        String publicAddress = "5.6.7.8";
+
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40080), machine1, 80);
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicAddress, 40081), machine1, 81);
+        pfm.associate(publicIpId2, HostAndPort.fromParts(publicAddress, 40082), machine2, 80);
+        pfm.forgetPortMappings(machine1);
+        
+        assertNull(pfm.lookup(machine1, 80));
+        assertNull(pfm.lookup(machine1, 81));
+        assertNull(pfm.lookup(publicIpId, 80));
+        assertEquals(pfm.lookup(machine2, 80), HostAndPort.fromParts(publicAddress, 40082));
+    }
+    
+    @Test
+    public void testAssociateLegacy() throws Exception {
+        String publicIpId = "myipid";
+        String publicAddress = "5.6.7.8";
+
+        pfm.acquirePublicPortExplicit(publicIpId, 40080);
+        pfm.recordPublicIpHostname(publicIpId, publicAddress);
+        pfm.associate(publicIpId, 40080, machine1, 80);
+        
+        assertEquals(pfm.lookup(publicIpId, 80), HostAndPort.fromParts(publicAddress, 40080));
+        assertEquals(pfm.lookup(machine1, 80), HostAndPort.fromParts(publicAddress, 40080));
+    }
+
+    @Test
+    public void testAssociationListeners() throws Exception {
+        final AtomicInteger associationCreatedCount = new AtomicInteger(0);
+        final AtomicInteger associationDeletedCount = new AtomicInteger(0);
+
+        final String publicIpId = "myipid";
+        final String anotherIpId = "anotherIpId";
+
+        pfm.addAssociationListener(new PortForwardManager.AssociationListener() {
+            @Override
+            public void onAssociationCreated(PortForwardManager.AssociationMetadata metadata) {
+                associationCreatedCount.incrementAndGet();
+            }
+
+            @Override
+            public void onAssociationDeleted(PortForwardManager.AssociationMetadata metadata) {
+                associationDeletedCount.incrementAndGet();
+            }
+        }, new Predicate<PortForwardManager.AssociationMetadata>() {
+            @Override
+            public boolean apply(PortForwardManager.AssociationMetadata metadata) {
+                return publicIpId.equals(metadata.getPublicIpId());
+            }
+        });
+
+        pfm.associate(publicIpId, HostAndPort.fromParts(publicIpId, 40080), machine1, 80);
+        pfm.associate(anotherIpId, HostAndPort.fromParts(anotherIpId, 40081), machine1, 80);
+        pfm.forgetPortMapping(publicIpId, 40080);
+        pfm.forgetPortMapping(anotherIpId, 40081);
+
+        assertEquals(associationCreatedCount.get(), 1);
+        assertEquals(associationDeletedCount.get(), 1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/cloud/CloudMachineNamerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/cloud/CloudMachineNamerTest.java b/core/src/test/java/org/apache/brooklyn/core/location/cloud/CloudMachineNamerTest.java
new file mode 100644
index 0000000..4ebaaec
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/cloud/CloudMachineNamerTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.core.location.cloud;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.core.location.cloud.names.AbstractCloudMachineNamer;
+import org.apache.brooklyn.core.location.cloud.names.BasicCloudMachineNamer;
+import org.apache.brooklyn.core.location.cloud.names.CloudMachineNamer;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+public class CloudMachineNamerTest {
+
+    private static final Logger log = LoggerFactory.getLogger(CloudMachineNamerTest.class);
+    
+    private TestApplication app;
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+
+    @Test
+    public void testGenerateGroupIdWithEntity() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TistApp"), LocalManagementContextForTests.newInstance());
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt"));
+
+        ConfigBag cfg = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+
+        String result = new BasicCloudMachineNamer().generateNewGroupId(cfg);
+
+        log.info("test entity child group id gives: "+result);
+        // e.g. brooklyn-alex-tistapp-uube-testent-xisg-rwad
+        Assert.assertTrue(result.length() <= 60);
+
+        String user = Strings.maxlen(System.getProperty("user.name"), 4).toLowerCase();
+        Assert.assertTrue(result.indexOf(user) >= 0);
+        Assert.assertTrue(result.indexOf("-tistapp-") >= 0);
+        Assert.assertTrue(result.indexOf("-testent-") >= 0);
+        Assert.assertTrue(result.indexOf("-"+Strings.maxlen(app.getId(), 4).toLowerCase()) >= 0);
+        Assert.assertTrue(result.indexOf("-"+Strings.maxlen(child.getId(), 4).toLowerCase()) >= 0);
+    }
+    
+    @Test
+    public void testGenerateNewMachineName() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TistApp"), LocalManagementContextForTests.newInstance());
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt"));
+
+        ConfigBag cfg = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+        BasicCloudMachineNamer namer = new BasicCloudMachineNamer();
+        
+        String result = namer.generateNewMachineUniqueName(cfg);
+        Assert.assertTrue(result.length() <= namer.getMaxNameLength(cfg));
+        String user = Strings.maxlen(System.getProperty("user.name"), 4).toLowerCase();
+        Assert.assertTrue(result.indexOf(user) >= 0);
+        Assert.assertTrue(result.indexOf("-tistapp-") >= 0);
+        Assert.assertTrue(result.indexOf("-testent-") >= 0);
+        Assert.assertTrue(result.indexOf("-"+Strings.maxlen(app.getId(), 4).toLowerCase()) >= 0);
+        Assert.assertTrue(result.indexOf("-"+Strings.maxlen(child.getId(), 4).toLowerCase()) >= 0);
+    }
+    
+    @Test
+    public void testGenerateNewMachineUniqueNameFromGroupId() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TistApp"), LocalManagementContextForTests.newInstance());
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt"));
+
+        ConfigBag cfg = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+        CloudMachineNamer namer = new BasicCloudMachineNamer();
+        
+        String groupId = namer.generateNewGroupId(cfg);
+        String result = namer.generateNewMachineUniqueNameFromGroupId(cfg, groupId);
+        Assert.assertTrue(result.startsWith(groupId));
+        Assert.assertTrue(result.length() == groupId.length() + 5);
+    }
+    
+    @Test
+    public void testLengthMaxPermittedForMachineName() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TistApp"), LocalManagementContextForTests.newInstance());
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt"));
+        
+        ConfigBag cfg = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+        BasicCloudMachineNamer namer = new BasicCloudMachineNamer();
+        namer.setDefaultMachineNameMaxLength(10);
+        String result = namer.generateNewMachineUniqueName(cfg);
+        Assert.assertEquals(result.length(), 10);
+    }
+    
+    @Test
+    public void testLengthReservedForNameInGroup() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TistApp"), LocalManagementContextForTests.newInstance());
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt"));
+        
+        ConfigBag cfg = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+        BasicCloudMachineNamer namer = new BasicCloudMachineNamer();
+        namer.setDefaultMachineNameMaxLength(20);
+        namer.setDefaultMachineNameSeparatorAndSaltLength(":I", 5);
+        String groupId = namer.generateNewGroupId(cfg);
+        Assert.assertEquals(13, groupId.length(), "groupId="+groupId);
+        String machineId = namer.generateNewMachineUniqueNameFromGroupId(cfg, groupId);
+        Assert.assertEquals(20, machineId.length(), "machineId="+machineId);
+        // separator is not sanitized -- caller should know what they are doing there!
+        Assert.assertTrue(machineId.startsWith(groupId+"-i"), "machineId="+machineId);
+    }
+
+    @Test
+    public void testSanitizesNewMachineName() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("T_%$()\r\n\t[]*.!App"), LocalManagementContextForTests.newInstance());
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("ent"));
+
+        ConfigBag cfg = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+        CloudMachineNamer namer = new BasicCloudMachineNamer();
+        
+        String result = namer.generateNewMachineUniqueName(cfg);
+        assertTrue(result.indexOf("t-ap") >= 0, "result="+result);
+        for (int c : "_%$()\r\n\t[]*.!".getBytes()) {
+            assertFalse(result.contains(new String(new char [] {(char)c})), "result="+result);
+        }
+    }
+    
+    @Test
+    public void testSanitize() {
+        Assert.assertEquals(AbstractCloudMachineNamer.sanitize(
+                        "me & you like alphanumeric but not _ or !!! or dots...dots...dots %$()\r\n\t[]*etc"),
+                "me-you-like-alphanumeric-but-not-or-or-dots-dots-dots-etc");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/cloud/CustomMachineNamerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/cloud/CustomMachineNamerTest.java b/core/src/test/java/org/apache/brooklyn/core/location/cloud/CustomMachineNamerTest.java
new file mode 100644
index 0000000..7503ff2
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/cloud/CustomMachineNamerTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.location.cloud;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.core.location.cloud.names.CustomMachineNamer;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+public class CustomMachineNamerTest {
+    
+    private TestApplication app;
+    private TestEntity child;
+    private ConfigBag config;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() {
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TestApp"), LocalManagementContextForTests.newInstance());
+        child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt"));
+        config = new ConfigBag()
+            .configure(CloudLocationConfig.CALLER_CONTEXT, child);
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+
+    @Test
+    public void testMachineNameNoConfig() {
+        config.configure(CloudLocationConfig.CALLER_CONTEXT, child);
+        Assert.assertEquals(new CustomMachineNamer().generateNewMachineUniqueName(config), "TestEnt");
+    }
+    
+    @Test
+    public void testMachineNameWithConfig() {
+        child.setSequenceValue(999);
+        config.configure(CustomMachineNamer.MACHINE_NAME_TEMPLATE, "number${entity.sequenceValue}");
+        Assert.assertEquals(new CustomMachineNamer().generateNewMachineUniqueName(config), "number999");
+    }
+    
+    @Test
+    public void testMachineNameWithExtraSubstitutions() {
+        config.configure(CustomMachineNamer.MACHINE_NAME_TEMPLATE, "foo-${fooName}-bar-${barName}-baz-${bazName.substitution}")
+            .configure(CustomMachineNamer.EXTRA_SUBSTITUTIONS, ImmutableMap.of("fooName", "foo", "barName", "bar", "bazName", this));
+        Assert.assertEquals(new CustomMachineNamer().generateNewMachineUniqueName(config), "foo-foo-bar-bar-baz-baz");
+    }
+    
+    public String getSubstitution() {
+        return "baz";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoInfoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoInfoTest.java b/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoInfoTest.java
new file mode 100644
index 0000000..06e1de1
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoInfoTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.geo;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.location.SimulatedLocation;
+import org.apache.brooklyn.core.location.geo.HostGeoInfo;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.testng.annotations.Test;
+
+public class HostGeoInfoTest {
+    private static final String IP = "192.168.0.1";
+    
+    private static final Location CUSTOM_LOCATION = new SimulatedLocation(MutableMap.of("name", "custom", "latitude", 50d, "longitude", 0d));
+    private static final Location CUSTOM_LOCATION_CHILD = new SimulatedLocation(MutableMap.of("name", "custom-child", "address", IP, "parentLocation", CUSTOM_LOCATION));
+        
+    @Test
+    public void testCustomLocationCoordinates() {
+        HostGeoInfo hgi = HostGeoInfo.fromLocation(CUSTOM_LOCATION);
+        assertNotNull(hgi);
+        assertEquals(50.0d, hgi.latitude);
+        assertEquals(0.0d, hgi.longitude);
+    }
+    
+    @Test
+    public void testCustomLocationChildCoordinates() {
+        HostGeoInfo hgi = HostGeoInfo.fromLocation(CUSTOM_LOCATION_CHILD);
+        assertNotNull(hgi);
+        assertEquals(50.0d, hgi.latitude);
+        assertEquals(0.0d, hgi.longitude);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoLookupIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoLookupIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoLookupIntegrationTest.java
new file mode 100644
index 0000000..dd1e2cd
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/geo/HostGeoLookupIntegrationTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.core.location.geo;
+
+import java.net.InetAddress;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.core.location.geo.GeoBytesHostGeoLookup;
+import org.apache.brooklyn.core.location.geo.HostGeoInfo;
+import org.apache.brooklyn.core.location.geo.MaxMind2HostGeoLookup;
+import org.apache.brooklyn.core.location.geo.UtraceHostGeoLookup;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.base.Objects;
+
+public class HostGeoLookupIntegrationTest {
+
+    public static final Logger log = LoggerFactory.getLogger(HostGeoLookupIntegrationTest.class);
+    
+    // Needs fast network connectivity to figure out the external IP. If response not returned in 2s fails.
+    @Test(groups = "Integration")
+    public void testLocalhostGetsLocation() throws Exception {
+        LocalhostMachineProvisioningLocation ll = new LocalhostMachineProvisioningLocation();
+        SshMachineLocation l = ll.obtain();
+        HostGeoInfo geo = HostGeoInfo.fromLocation(l);
+        Assert.assertNotNull(geo, "host lookup unavailable - is the maxmind database installed? or else network unavailable or too slow?");
+        log.info("localhost is in "+geo);
+        Assert.assertNotNull(geo, "couldn't load data; must have a valid HostGeoLookup impl (e.g. MaxMind installed, or online and with Utrace credit)");
+        Assert.assertTrue(-90 <= geo.latitude && geo.latitude <= 90); 
+        ll.close();
+    }
+
+    @Deprecated // see GeoBytesHostGeoLookup - their API changed
+    @Test(groups = "Integration", enabled=false)
+    public void testGeobytesLookup() throws Exception {
+        HostGeoInfo geo = new GeoBytesHostGeoLookup().getHostGeoInfo(InetAddress.getByName("geobytes.com"));
+        Assert.assertNotNull(geo, "host lookup unavailable");
+        Assert.assertEquals(geo.displayName, "Baltimore (US)");
+        Assert.assertEquals(geo.latitude, 39.2894, 0.1);
+        Assert.assertEquals(geo.longitude, -76.6384, 0.1);
+    }
+
+    @Test(groups = "Integration")
+    public void testUtraceLookup() throws Exception {
+        // The test times out in a VM - VirtualBox + Ubuntu Vivid, possibly due to proxy usage?
+        // Increase the timeout so we can actually test it's working correctly, regardless of test environment.
+        HostGeoInfo geo = new UtraceHostGeoLookup().getHostGeoInfo(InetAddress.getByName("utrace.de"), Duration.THIRTY_SECONDS);
+        Assert.assertNotNull(geo, "host lookup unavailable - maybe network not available ");
+        Assert.assertTrue(geo.displayName.contains("(DE)"));
+        Assert.assertEquals(geo.latitude, 51, 2);
+        Assert.assertEquals(geo.longitude, 9, 5);
+    }
+
+    @Test(groups = "Integration")  // only works if maxmind database is installed to ~/.brooklyn/
+    public void testMaxmindLookup() throws Exception {
+        HostGeoInfo geo = new MaxMind2HostGeoLookup().getHostGeoInfo(InetAddress.getByName("maxmind.com"));
+        Assert.assertNotNull(geo, "host lookup unavailable - is the maxmind database installed?");
+        log.info("maxmind.com at "+geo);
+        
+        // used to be Washington; now Dallas - in case this changes again, we will accept either!
+        // also have seen variation in lat/lon reported, so happy to within one degree now
+        Assert.assertTrue(Objects.equal(geo.displayName, "Washington, DC (US)") || Objects.equal(geo.displayName, "Dallas, TX (US)"), "name="+geo.displayName);
+        Assert.assertTrue(Math.abs(geo.latitude - 38.90) <= 1 || Math.abs(geo.latitude - 32.78) <= 1, "lat="+geo.latitude);
+        Assert.assertTrue(Math.abs(geo.longitude - -77.02) <= 1 || Math.abs(geo.longitude - -96.82) <= 1, "lon="+geo.longitude);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/location/geo/LocalhostExternalIpLoaderIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/geo/LocalhostExternalIpLoaderIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/location/geo/LocalhostExternalIpLoaderIntegrationTest.java
new file mode 100644
index 0000000..a5ff105
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/geo/LocalhostExternalIpLoaderIntegrationTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.core.location.geo;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+
+import org.apache.brooklyn.core.location.geo.LocalhostExternalIpLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Sets;
+
+public class LocalhostExternalIpLoaderIntegrationTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LocalhostExternalIpLoaderIntegrationTest.class);
+
+    @Test(groups = "Integration")
+    public void testHostsAgreeOnExternalIp() {
+        Set<String> ips = Sets.newHashSet();
+        for (String url : LocalhostExternalIpLoader.getIpAddressWebsites()) {
+            String ip = LocalhostExternalIpLoader.getIpAddressFrom(url);
+            LOG.debug("IP from {}: {}", url, ip);
+            ips.add(ip);
+        }
+        assertEquals(ips.size(), 1, "Expected all IP suppliers to agree on the external IP address of Brooklyn. " +
+                "Check logs for source responses. ips=" + ips);
+    }
+
+    @Test(groups = "Integration")
+    public void testLoadExternalIp() {
+        assertNotNull(LocalhostExternalIpLoader.getLocalhostIpWaiting());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/AccessManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/AccessManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/AccessManagerTest.java
index 2698dcf..d3ade7b 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/AccessManagerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/AccessManagerTest.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -36,7 +37,6 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.collect.ImmutableSet;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
index 30fe628..4132750 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
@@ -30,7 +30,6 @@ import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
-import org.apache.brooklyn.location.core.SimulatedLocation;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.test.TestResourceUnavailableException;
@@ -55,6 +54,7 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
 import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
 import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiTestResources;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
 import org.apache.brooklyn.core.mgmt.persist.XmlMementoSerializer;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
index b0e5b7b..4afb361 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEnricherTest.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.entity.EntityPredicates;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.core.test.entity.TestEntityImpl;
@@ -54,7 +55,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
index ea02b23..a427995 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
@@ -59,6 +59,7 @@ import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.EntityPredicates;
 import org.apache.brooklyn.core.entity.trait.Resizable;
 import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.LocationConfigTest.MyLocation;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.mgmt.rebind.BasicEntityRebindSupport;
 import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -78,7 +79,6 @@ import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException;
 import org.apache.brooklyn.util.time.Durations;
 import org.testng.Assert;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.LocationConfigTest.MyLocation;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Predicates;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindLocationTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindLocationTest.java
index fe60599..6b2d8c5 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindLocationTest.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.LocationMemento;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.location.AbstractLocation;
 import org.apache.brooklyn.core.mgmt.rebind.BasicLocationRebindSupport;
 import org.apache.brooklyn.core.mgmt.rebind.RebindEntityTest.MyEntity;
 import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -44,7 +45,6 @@ import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.AbstractLocation;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
index 70003a0..d410474 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyTest.java
@@ -36,6 +36,7 @@ import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.location.Locations;
 import org.apache.brooklyn.core.mgmt.rebind.RebindEnricherTest.MyEnricher;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
@@ -47,7 +48,6 @@ import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.Locations;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableSet;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
index e08d32b..c2cb02c 100644
--- a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
@@ -23,9 +23,9 @@ import static org.testng.Assert.assertEquals;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
 import org.apache.brooklyn.core.entity.RecordingSensorEventListener;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 import org.apache.brooklyn.policy.core.AbstractPolicy;
 import org.apache.brooklyn.sensor.core.BasicSensorEvent;
 import org.apache.brooklyn.test.Asserts;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/server/entity/BrooklynMetricsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/server/entity/BrooklynMetricsTest.java b/core/src/test/java/org/apache/brooklyn/core/server/entity/BrooklynMetricsTest.java
index c0b864d..49cab1e 100644
--- a/core/src/test/java/org/apache/brooklyn/core/server/entity/BrooklynMetricsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/server/entity/BrooklynMetricsTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.server.entity.BrooklynMetrics;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -39,7 +40,6 @@ import org.apache.brooklyn.util.time.Duration;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.collect.ImmutableList;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplication.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplication.java b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplication.java
index 63d9dd5..2521b1f 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplication.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplication.java
@@ -28,7 +28,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.entity.StartableApplication;
 import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
-import org.apache.brooklyn.location.core.SimulatedLocation;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 import org.apache.brooklyn.sensor.core.Sensors;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
index 2a76f03..47faafd 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
@@ -28,9 +28,9 @@ import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.core.entity.AbstractApplication;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 import org.apache.brooklyn.util.logging.LoggingSetup;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/location/TestPaasLocation.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/location/TestPaasLocation.java b/core/src/test/java/org/apache/brooklyn/core/test/location/TestPaasLocation.java
deleted file mode 100644
index d79476c..0000000
--- a/core/src/test/java/org/apache/brooklyn/core/test/location/TestPaasLocation.java
+++ /dev/null
@@ -1,32 +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.core.test.location;
-
-import org.apache.brooklyn.location.core.AbstractLocation;
-import org.apache.brooklyn.location.paas.PaasLocation;
-
-/**
- * Mock {@link PaasLocation} for test purposes
- */
-public class TestPaasLocation extends AbstractLocation implements PaasLocation {
-    @Override
-    public String getPaasProviderName() {
-        return "TestPaas";
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java
index 1e6a185..9258011 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java
@@ -20,7 +20,7 @@ package org.apache.brooklyn.core.test.qa.longevity;
 
 import org.testng.annotations.Test;
 import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.location.core.SimulatedLocation;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java
index 6c2b334..8fad0ae 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
 import org.apache.brooklyn.core.internal.storage.BrooklynStorage;
 import org.apache.brooklyn.core.internal.storage.DataGrid;
 import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.mgmt.internal.AbstractManagementContext;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
@@ -46,7 +47,6 @@ import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupTest.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupTest.java
index b9fb501..11ef3d0 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupTest.java
@@ -20,7 +20,7 @@ package org.apache.brooklyn.core.test.qa.longevity;
 
 import org.testng.annotations.Test;
 import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.location.core.SimulatedLocation;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
 
 public class EntityCleanupTest extends EntityCleanupLongevityTestFixture {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/AbstractPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/AbstractPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/AbstractPerformanceTest.java
index 8c2b5e2..a5a3568 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/AbstractPerformanceTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/AbstractPerformanceTest.java
@@ -25,13 +25,13 @@ import java.util.concurrent.TimeUnit;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.util.internal.DoubleSystemProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Stopwatch;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/EntityPersistencePerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/EntityPersistencePerformanceTest.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/EntityPersistencePerformanceTest.java
index 70737f6..11a965e 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/EntityPersistencePerformanceTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/performance/EntityPersistencePerformanceTest.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
 import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.core.test.policy.TestPolicy;
@@ -33,7 +34,6 @@ import org.apache.brooklyn.test.PerformanceTestUtils;
 import org.apache.brooklyn.util.repeat.Repeater;
 import org.apache.brooklyn.util.time.Duration;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
index 98c788f..786fe69 100644
--- a/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
+++ b/core/src/test/java/org/apache/brooklyn/effector/core/EffectorBasicTest.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.trait.FailingEntity;
 import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.core.test.entity.TestEntity;
@@ -40,7 +41,6 @@ import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.collect.ImmutableList;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/538324e1/core/src/test/java/org/apache/brooklyn/entity/group/DynamicClusterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/entity/group/DynamicClusterTest.java b/core/src/test/java/org/apache/brooklyn/entity/group/DynamicClusterTest.java
index 5097a45..0e2f73f 100644
--- a/core/src/test/java/org/apache/brooklyn/entity/group/DynamicClusterTest.java
+++ b/core/src/test/java/org/apache/brooklyn/entity/group/DynamicClusterTest.java
@@ -55,6 +55,7 @@ import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
 import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
 import org.apache.brooklyn.core.entity.trait.Changeable;
 import org.apache.brooklyn.core.entity.trait.FailingEntity;
+import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.core.test.entity.TestEntity;
@@ -70,7 +71,6 @@ import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.time.Time;
-import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;