http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
 
b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
new file mode 100644
index 0000000..b2d0eb9
--- /dev/null
+++ 
b/core/src/test/java/org/apache/brooklyn/location/ssh/SshMachineLocationTest.java
@@ -0,0 +1,345 @@
+/*
+ * 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.ssh;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.effector.Effector;
+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.Location;
+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.PortRange;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.effector.core.EffectorBody;
+import org.apache.brooklyn.effector.core.EffectorTaskTest;
+import org.apache.brooklyn.effector.core.Effectors;
+import org.apache.brooklyn.entity.core.BrooklynConfigKeys;
+import org.apache.brooklyn.entity.core.Entities;
+import org.apache.brooklyn.entity.core.EntityInternal;
+import org.apache.brooklyn.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.location.core.BasicHardwareDetails;
+import org.apache.brooklyn.location.core.BasicMachineDetails;
+import org.apache.brooklyn.location.core.BasicOsDetails;
+import org.apache.brooklyn.location.core.Machines;
+import org.apache.brooklyn.location.core.PortRanges;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.file.ArchiveUtils;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.util.core.internal.ssh.SshException;
+import org.apache.brooklyn.util.core.internal.ssh.SshTool;
+import org.apache.brooklyn.util.core.task.BasicExecutionContext;
+import org.apache.brooklyn.util.core.task.BasicExecutionManager;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.net.Networking;
+import org.apache.brooklyn.util.net.Urls;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.Files;
+
+/**
+ * Test the {@link SshMachineLocation} implementation of the {@link Location} 
interface.
+ */
+public class SshMachineLocationTest {
+
+    private SshMachineLocation host;
+    private ManagementContext mgmt;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        mgmt = LocalManagementContextForTests.newInstance();
+        host = new SshMachineLocation(MutableMap.of("address", 
Networking.getLocalHost()));
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (host != null) Streams.closeQuietly(host);
+        if (mgmt != null) Entities.destroyAll(mgmt);
+    }
+    
+    @Test(groups = "Integration")
+    public void testGetMachineDetails() throws Exception {
+        BasicExecutionManager execManager = new 
BasicExecutionManager("mycontextid");
+        BasicExecutionContext execContext = new 
BasicExecutionContext(execManager);
+        try {
+            MachineDetails details = execContext.submit(new 
Callable<MachineDetails>() {
+                public MachineDetails call() {
+                    return host.getMachineDetails();
+                }}).get();
+            assertNotNull(details);
+        } finally {
+            execManager.shutdownNow();
+        }
+    }
+    
+    @Test
+    public void testSupplyingMachineDetails() throws Exception {
+        MachineDetails machineDetails = new BasicMachineDetails(new 
BasicHardwareDetails(1, 1024), new BasicOsDetails("myname", "myarch", 
"myversion"));
+        SshMachineLocation host2 = 
mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure(SshMachineLocation.MACHINE_DETAILS, 
machineDetails));
+        
+        assertSame(host2.getMachineDetails(), machineDetails);
+    }
+    
+    @Test
+    public void testConfigurePrivateAddresses() throws Exception {
+        SshMachineLocation host2 = 
mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure("address", Networking.getLocalHost())
+                .configure(SshMachineLocation.PRIVATE_ADDRESSES, 
ImmutableList.of("1.2.3.4"))
+                .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, 
true));
+
+        assertEquals(host2.getPrivateAddresses(), ImmutableSet.of("1.2.3.4"));
+    }
+    
+    // Wow, this is hard to test (until I accepted creating the entity + 
effector)! Code smell?
+    // Need to call getMachineDetails in a DynamicSequentialTask so that the 
"innessential" takes effect,
+    // to not fail its caller. But to get one of those outside of an effector 
is non-obvious.
+    @Test(groups = "Integration")
+    public void testGetMachineIsInessentialOnFailure() throws Exception {
+        SshMachineLocation host2 = 
mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+                .configure("address", Networking.getLocalHost())
+                .configure(SshTool.PROP_TOOL_CLASS, 
FailingSshTool.class.getName()));
+
+        final Effector<MachineDetails> GET_MACHINE_DETAILS = 
Effectors.effector(MachineDetails.class, "getMachineDetails")
+                .impl(new EffectorBody<MachineDetails>() {
+                    public MachineDetails call(ConfigBag parameters) {
+                        Maybe<MachineLocation> machine = 
Machines.findUniqueMachineLocation(entity().getLocations());
+                        try {
+                            machine.get().getMachineDetails();
+                            throw new IllegalStateException("Expected failure 
in ssh");
+                        } catch (RuntimeException e) {
+                            return null;
+                        }
+                    }})
+                .build();
+
+        EntitySpec<TestApplication> appSpec = 
EntitySpec.create(TestApplication.class)
+                .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, 
true)
+                .addInitializer(new EntityInitializer() {
+                        public void apply(EntityLocal entity) {
+                            
((EntityInternal)entity).getMutableEntityType().addEffector(EffectorTaskTest.DOUBLE_1);
+                        }});
+
+        TestApplication app = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+
+        app.start(ImmutableList.of(host2));
+        
+        MachineDetails details = app.invoke(GET_MACHINE_DETAILS, 
ImmutableMap.<String, Object>of()).get();
+        assertNull(details);
+    }
+    public static class FailingSshTool extends RecordingSshTool {
+        public FailingSshTool(Map<?, ?> props) {
+            super(props);
+        }
+        @Override public int execScript(Map<String, ?> props, List<String> 
commands, Map<String, ?> env) {
+            throw new RuntimeException("Simulating failure of ssh: 
cmds="+commands);
+        }
+        @Override public int execCommands(Map<String, ?> props, List<String> 
commands, Map<String, ?> env) {
+            throw new RuntimeException("Simulating failure of ssh: 
cmds="+commands);
+        }
+    }
+    
+    // Note: requires `ssh localhost` to be setup such that no password is 
required    
+    @Test(groups = "Integration")
+    public void testSshExecScript() throws Exception {
+        OutputStream outStream = new ByteArrayOutputStream();
+        String expectedName = Os.user();
+        host.execScript(MutableMap.of("out", outStream), "mysummary", 
ImmutableList.of("whoami; exit"));
+        String outString = outStream.toString();
+        
+        assertTrue(outString.contains(expectedName), outString);
+    }
+    
+    // Note: requires `ssh localhost` to be setup such that no password is 
required    
+    @Test(groups = "Integration")
+    public void testSshExecCommands() throws Exception {
+        OutputStream outStream = new ByteArrayOutputStream();
+        String expectedName = Os.user();
+        host.execCommands(MutableMap.of("out", outStream), "mysummary", 
ImmutableList.of("whoami; exit"));
+        String outString = outStream.toString();
+        
+        assertTrue(outString.contains(expectedName), outString);
+    }
+    
+    // For issue #230
+    @Test(groups = "Integration")
+    public void testOverridingPropertyOnExec() throws Exception {
+        SshMachineLocation host = new 
SshMachineLocation(MutableMap.of("address", Networking.getLocalHost(), 
"sshPrivateKeyData", "wrongdata"));
+        
+        OutputStream outStream = new ByteArrayOutputStream();
+        String expectedName = Os.user();
+        host.execCommands(MutableMap.of("sshPrivateKeyData", null, "out", 
outStream), "my summary", ImmutableList.of("whoami"));
+        String outString = outStream.toString();
+        
+        assertTrue(outString.contains(expectedName), "outString="+outString);
+    }
+
+    @Test(groups = "Integration", 
expectedExceptions={IllegalStateException.class, SshException.class})
+    public void testSshRunWithInvalidUserFails() throws Exception {
+        SshMachineLocation badHost = new 
SshMachineLocation(MutableMap.of("user", "doesnotexist", "address", 
Networking.getLocalHost()));
+        badHost.execScript("mysummary", ImmutableList.of("whoami; exit"));
+    }
+    
+    // Note: requires `ssh localhost` to be setup such that no password is 
required    
+    @Test(groups = "Integration")
+    public void testCopyFileTo() throws Exception {
+        File dest = Os.newTempFile(getClass(), ".dest.tmp");
+        File src = Os.newTempFile(getClass(), ".src.tmp");
+        try {
+            Files.write("abc", src, Charsets.UTF_8);
+            host.copyTo(src, dest);
+            assertEquals("abc", Files.readFirstLine(dest, Charsets.UTF_8));
+        } finally {
+            src.delete();
+            dest.delete();
+        }
+    }
+
+    // Note: requires `ssh localhost` to be setup such that no password is 
required    
+    @Test(groups = "Integration")
+    public void testCopyStreamTo() throws Exception {
+        String contents = "abc";
+        File dest = new File(Os.tmp(), "sssMachineLocationTest_dest.tmp");
+        try {
+            host.copyTo(Streams.newInputStreamWithContents(contents), 
dest.getAbsolutePath());
+            assertEquals("abc", Files.readFirstLine(dest, Charsets.UTF_8));
+        } finally {
+            dest.delete();
+        }
+    }
+
+    @Test(groups = "Integration")
+    public void testInstallUrlTo() throws Exception {
+        File dest = new File(Os.tmp(), "sssMachineLocationTest_dir/");
+        dest.mkdir();
+        try {
+            int result = 
host.installTo("https://raw.github.com/brooklyncentral/brooklyn/master/README.md";,
 Urls.mergePaths(dest.getAbsolutePath(), "README.md"));
+            assertEquals(result, 0);
+            String contents = ArchiveUtils.readFullyString(new File(dest, 
"README.md"));
+            assertTrue(contents.contains("http://brooklyncentral.github.com";), 
"contents missing expected phrase; contains:\n"+contents);
+        } finally {
+            dest.delete();
+        }
+    }
+    
+    @Test(groups = "Integration")
+    public void testInstallClasspathCopyTo() throws Exception {
+        File dest = new File(Os.tmp(), "sssMachineLocationTest_dir/");
+        dest.mkdir();
+        try {
+            int result = 
host.installTo("classpath://brooklyn/config/sample.properties", 
Urls.mergePaths(dest.getAbsolutePath(), "sample.properties"));
+            assertEquals(result, 0);
+            String contents = ArchiveUtils.readFullyString(new File(dest, 
"sample.properties"));
+            assertTrue(contents.contains("Property 1"), "contents missing 
expected phrase; contains:\n"+contents);
+        } finally {
+            dest.delete();
+        }
+    }
+
+    // Note: requires `ssh localhost` to be setup such that no password is 
required    
+    @Test(groups = "Integration")
+    public void testIsSshableWhenTrue() throws Exception {
+        assertTrue(host.isSshable());
+    }
+    
+    // Note: on some (home/airport) networks, `ssh 123.123.123.123` hangs 
seemingly forever.
+    // Make sure we fail, waiting for longer than the 70 second TCP timeout.
+    //
+    // Times out in 2m7s on Ubuntu Vivid (syn retries set to 6)
+    @Test(groups = "Integration")
+    public void testIsSshableWhenFalse() throws Exception {
+        byte[] unreachableIp = new byte[] {123,123,123,123};
+        final SshMachineLocation unreachableHost = new 
SshMachineLocation(MutableMap.of("address", 
InetAddress.getByAddress("unreachablename", unreachableIp)));
+        Asserts.assertReturnsEventually(new Runnable() {
+            public void run() {
+                assertFalse(unreachableHost.isSshable());
+            }},
+            Duration.minutes(3));
+    }
+    
+    @Test
+    public void obtainSpecificPortGivesOutPortOnlyOnce() {
+        int port = 2345;
+        assertTrue(host.obtainSpecificPort(port));
+        assertFalse(host.obtainSpecificPort(port));
+        host.releasePort(port);
+        assertTrue(host.obtainSpecificPort(port));
+    }
+    
+    @Test
+    public void obtainPortInRangeGivesBackRequiredPortOnlyIfAvailable() {
+        int port = 2345;
+        assertEquals(host.obtainPort(new PortRanges.LinearPortRange(port, 
port)), port);
+        assertEquals(host.obtainPort(new PortRanges.LinearPortRange(port, 
port)), -1);
+        host.releasePort(port);
+        assertEquals(host.obtainPort(new PortRanges.LinearPortRange(port, 
port)), port);
+    }
+    
+    @Test
+    public void obtainPortInWideRange() {
+        int lowerPort = 2345;
+        int upperPort = 2350;
+        PortRange range = new PortRanges.LinearPortRange(lowerPort, upperPort);
+        for (int i = lowerPort; i <= upperPort; i++) {
+            assertEquals(host.obtainPort(range), i);
+        }
+        assertEquals(host.obtainPort(range), -1);
+        
+        host.releasePort(lowerPort);
+        assertEquals(host.obtainPort(range), lowerPort);
+        assertEquals(host.obtainPort(range), -1);
+    }
+    
+    @Test
+    public void testObtainPortDoesNotUsePreReservedPorts() {
+        host = new SshMachineLocation(MutableMap.of("address", 
Networking.getLocalHost(), "usedPorts", ImmutableSet.of(8000)));
+        assertEquals(host.obtainPort(PortRanges.fromString("8000")), -1);
+        assertEquals(host.obtainPort(PortRanges.fromString("8000+")), 8001);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java
 
b/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java
new file mode 100644
index 0000000..65ac92e
--- /dev/null
+++ 
b/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.winrm;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.winrm.AdvertiseWinrmLoginPolicy;
+import org.apache.brooklyn.location.winrm.WinRmMachineLocation;
+
+import com.google.common.collect.ImmutableList;
+
+public class AdvertiseWinrmLoginPolicyTest extends BrooklynAppUnitTestSupport {
+
+    @Test
+    public void testAdvertisesMachineLoginDetails() throws Exception {
+        TestEntity entity = 
app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .policy(PolicySpec.create(AdvertiseWinrmLoginPolicy.class)));
+        
+        WinRmMachineLocation machine = 
mgmt.getLocationManager().createLocation(LocationSpec.create(WinRmMachineLocation.class)
+                .configure("address", "1.2.3.4")
+                .configure("user", "myuser")
+                .configure("port", 5678)
+                .configure("password", "mypassword"));
+        app.start(ImmutableList.of(machine));
+        
+        String expected = "myuser : mypassword @ 1.2.3.4:5678";
+
+        EntityTestUtils.assertAttributeEqualsEventually(entity, 
AdvertiseWinrmLoginPolicy.VM_USER_CREDENTIALS, expected);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
 
b/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java
new file mode 100644
index 0000000..4dd4727
--- /dev/null
+++ 
b/core/src/test/java/org/apache/brooklyn/location/winrm/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.location.winrm;
+
+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.winrm.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/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherDeprecatedTest.groovy
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherDeprecatedTest.groovy
 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherDeprecatedTest.groovy
index 5656aa6..a2416ef 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherDeprecatedTest.groovy
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherDeprecatedTest.groovy
@@ -18,13 +18,15 @@
  */
 package org.apache.brooklyn.sensor.enricher
 
+import static org.testng.Assert.assertEquals
+
 import org.apache.brooklyn.api.entity.EntitySpec
 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.entity.core.Entities
 import org.apache.brooklyn.entity.group.BasicGroup
-import org.apache.brooklyn.location.basic.SimulatedLocation
+import org.apache.brooklyn.location.core.SimulatedLocation
 import org.apache.brooklyn.sensor.core.BasicAttributeSensor
 import org.apache.brooklyn.test.TestUtils
 import org.slf4j.Logger
@@ -32,7 +34,6 @@ import org.slf4j.LoggerFactory
 import org.testng.annotations.AfterMethod
 import org.testng.annotations.BeforeMethod
 import org.testng.annotations.Test
-import static org.testng.Assert.assertEquals
 
 import com.google.common.base.Function
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherTest.java
index 6aba673..0d9c2a7 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/CustomAggregatingEnricherTest.java
@@ -36,7 +36,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.basic.SimulatedLocation;
+import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherDeprecatedTest.groovy
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherDeprecatedTest.groovy
 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherDeprecatedTest.groovy
index 4251c2d..7b2a290 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherDeprecatedTest.groovy
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherDeprecatedTest.groovy
@@ -25,7 +25,7 @@ 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.entity.core.Entities
-import org.apache.brooklyn.location.basic.SimulatedLocation
+import org.apache.brooklyn.location.core.SimulatedLocation
 import org.apache.brooklyn.sensor.core.BasicAttributeSensor
 import org.apache.brooklyn.test.TestUtils
 import org.apache.brooklyn.util.collections.MutableMap

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherTest.java
index 4510c4a..d438933 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/enricher/TransformingEnricherTest.java
@@ -30,7 +30,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.basic.SimulatedLocation;
+import org.apache.brooklyn.location.core.SimulatedLocation;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/feed/function/FunctionFeedTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/function/FunctionFeedTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/function/FunctionFeedTest.java
index a8f1a1f..bd3e0da 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/function/FunctionFeedTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/function/FunctionFeedTest.java
@@ -52,7 +52,7 @@ 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.LocalhostMachineProvisioningLocation;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/feed/http/HttpFeedIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/http/HttpFeedIntegrationTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/http/HttpFeedIntegrationTest.java
index 9295b5a..ea01eb3 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/http/HttpFeedIntegrationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/http/HttpFeedIntegrationTest.java
@@ -39,8 +39,8 @@ import org.apache.brooklyn.test.EntityTestUtils;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 
 import com.google.common.base.Functions;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/feed/shell/ShellFeedIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/shell/ShellFeedIntegrationTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/shell/ShellFeedIntegrationTest.java
index 1a53f78..cab9610 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/shell/ShellFeedIntegrationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/shell/ShellFeedIntegrationTest.java
@@ -46,7 +46,7 @@ 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.LocalhostMachineProvisioningLocation;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/feed/ssh/SshFeedIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/ssh/SshFeedIntegrationTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/ssh/SshFeedIntegrationTest.java
index 02eeaac..c0708b7 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/ssh/SshFeedIntegrationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/ssh/SshFeedIntegrationTest.java
@@ -51,8 +51,8 @@ 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.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeedTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeedTest.java
 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeedTest.java
index 499f549..0c6cbc1 100644
--- 
a/core/src/test/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeedTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeedTest.java
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
-import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 
 import io.cloudsoft.winrm4j.winrm.WinRmToolResponse;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/util/core/file/ArchiveUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/util/core/file/ArchiveUtilsTest.java 
b/core/src/test/java/org/apache/brooklyn/util/core/file/ArchiveUtilsTest.java
index d44199c..4224d8d 100644
--- 
a/core/src/test/java/org/apache/brooklyn/util/core/file/ArchiveUtilsTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/util/core/file/ArchiveUtilsTest.java
@@ -31,7 +31,7 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.file.ArchiveBuilder;
 import org.apache.brooklyn.util.core.file.ArchiveUtils;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/util/core/http/HttpToolIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/util/core/http/HttpToolIntegrationTest.java
 
b/core/src/test/java/org/apache/brooklyn/util/core/http/HttpToolIntegrationTest.java
index 788b3c6..fc830a6 100644
--- 
a/core/src/test/java/org/apache/brooklyn/util/core/http/HttpToolIntegrationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/util/core/http/HttpToolIntegrationTest.java
@@ -27,7 +27,7 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 import org.apache.brooklyn.core.test.HttpService;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
 import org.apache.brooklyn.util.core.http.HttpTool;
 import org.apache.brooklyn.util.core.http.HttpToolResponse;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/util/core/ssh/BashCommandsIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/util/core/ssh/BashCommandsIntegrationTest.java
 
b/core/src/test/java/org/apache/brooklyn/util/core/ssh/BashCommandsIntegrationTest.java
index a2d3480..10bbf67 100644
--- 
a/core/src/test/java/org/apache/brooklyn/util/core/ssh/BashCommandsIntegrationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/util/core/ssh/BashCommandsIntegrationTest.java
@@ -53,8 +53,8 @@ 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.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
 
 import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/util/core/task/ssh/SshTasksTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/util/core/task/ssh/SshTasksTest.java 
b/core/src/test/java/org/apache/brooklyn/util/core/task/ssh/SshTasksTest.java
index 96f38c4..7c734ff 100644
--- 
a/core/src/test/java/org/apache/brooklyn/util/core/task/ssh/SshTasksTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/util/core/task/ssh/SshTasksTest.java
@@ -33,8 +33,8 @@ 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.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.core.ssh.BashCommandsIntegrationTest;
 import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskFactory;
 import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskWrapper;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
----------------------------------------------------------------------
diff --git 
a/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
 
b/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
index ff2627d..5bb8426 100644
--- 
a/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
+++ 
b/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
@@ -40,7 +40,7 @@ import org.apache.brooklyn.entity.proxy.AbstractController;
 import org.apache.brooklyn.entity.webapp.ElasticJavaWebAppService;
 import org.apache.brooklyn.entity.webapp.JavaWebAppService;
 import org.apache.brooklyn.launcher.BrooklynLauncher;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
 import org.apache.brooklyn.sensor.core.PortAttributeSensorAndConfigKey;
 import org.apache.brooklyn.util.CommandLineUtil;
 import org.apache.brooklyn.util.core.BrooklynMavenArtifacts;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
----------------------------------------------------------------------
diff --git 
a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
 
b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
index 26891d5..5f9d297 100644
--- 
a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
+++ 
b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
@@ -53,7 +53,7 @@ import org.apache.brooklyn.entity.trait.Startable;
 import org.apache.brooklyn.entity.webapp.JavaWebAppService;
 import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
 import org.apache.brooklyn.launcher.BrooklynLauncher;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
 import org.apache.brooklyn.policy.ha.ServiceFailureDetector;
 import org.apache.brooklyn.policy.ha.ServiceReplacer;
 import org.apache.brooklyn.policy.ha.ServiceRestarter;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
----------------------------------------------------------------------
diff --git 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
index 46be8bb..77adc18 100644
--- 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
+++ 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
@@ -30,7 +30,7 @@ import org.apache.brooklyn.entity.core.StartableApplication;
 import org.apache.brooklyn.entity.webapp.JavaWebAppService;
 import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server;
 import org.apache.brooklyn.launcher.BrooklynLauncher;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
 import org.apache.brooklyn.util.CommandLineUtil;
 
 import com.google.common.collect.Lists;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
----------------------------------------------------------------------
diff --git 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
index 8682335..1092262 100644
--- 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
+++ 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
@@ -39,7 +39,7 @@ import org.apache.brooklyn.entity.webapp.JavaWebAppService;
 import org.apache.brooklyn.entity.webapp.WebAppService;
 import org.apache.brooklyn.entity.webapp.WebAppServiceConstants;
 import org.apache.brooklyn.launcher.BrooklynLauncher;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
 import org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy;
 import org.apache.brooklyn.policy.enricher.HttpLatencyDetector;
 import org.apache.brooklyn.sensor.core.Sensors;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
----------------------------------------------------------------------
diff --git 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
index e13a632..2030200 100644
--- 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
+++ 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
@@ -44,7 +44,7 @@ import org.apache.brooklyn.entity.database.mysql.MySqlNode;
 import org.apache.brooklyn.entity.group.DynamicCluster;
 import org.apache.brooklyn.entity.java.JavaEntityMethods;
 import org.apache.brooklyn.launcher.BrooklynLauncher;
-import org.apache.brooklyn.location.basic.PortRanges;
+import org.apache.brooklyn.location.core.PortRanges;
 import org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy;
 import org.apache.brooklyn.policy.enricher.HttpLatencyDetector;
 import org.apache.brooklyn.sensor.core.Sensors;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleGroovy.groovy
----------------------------------------------------------------------
diff --git 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleGroovy.groovy
 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleGroovy.groovy
index dfd677d..9327db4 100644
--- 
a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleGroovy.groovy
+++ 
b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleGroovy.groovy
@@ -18,7 +18,7 @@
  */
 package org.apache.brooklyn.demo;
 
-import static brooklyn.entity.java.JavaEntityMethods.javaSysProp
+import static org.apache.brooklyn.entity.java.JavaEntityMethods.javaSysProp
 import static 
org.apache.brooklyn.sensor.core.DependentConfiguration.attributeWhenReady
 import static 
org.apache.brooklyn.sensor.core.DependentConfiguration.formatString
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStore.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStore.java
 
b/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStore.java
deleted file mode 100644
index 782f160..0000000
--- 
a/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStore.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.rebind.persister.jclouds;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode;
-import org.apache.brooklyn.core.mgmt.rebind.persister.PersistMode;
-import org.apache.brooklyn.core.mgmt.rebind.persister.PersistenceObjectStore;
-import org.apache.brooklyn.core.server.BrooklynServerConfig;
-import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.blobstore.domain.StorageMetadata;
-import org.jclouds.blobstore.options.ListContainerOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.location.basic.LocationConfigKeys;
-import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import org.apache.brooklyn.location.jclouds.JcloudsLocation;
-import org.apache.brooklyn.location.jclouds.JcloudsUtil;
-import org.apache.brooklyn.util.exceptions.FatalConfigurationRuntimeException;
-import org.apache.brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-
-/**
- * @author Andrea Turli
- */
-public class JcloudsBlobStoreBasedObjectStore implements 
PersistenceObjectStore {
-
-    private static final Logger log = 
LoggerFactory.getLogger(JcloudsBlobStoreBasedObjectStore.class);
-
-    private final String containerNameFirstPart;
-    private final String containerSubPath;
-    
-    private String locationSpec;
-    private JcloudsLocation location;
-    private BlobStoreContext context;
-
-    private ManagementContext mgmt;
-
-    public JcloudsBlobStoreBasedObjectStore(String locationSpec, String 
containerName) {
-        this.locationSpec = locationSpec;
-        String[] segments = splitOnce(containerName);
-        this.containerNameFirstPart = segments[0];
-        this.containerSubPath = segments[1];
-    }
-    
-    private String[] splitOnce(String path) {
-        String separator = subPathSeparator();
-        int index = path.indexOf(separator);
-        if (index<0) return new String[] { path, "" };
-        return new String[] { path.substring(0, index), 
path.substring(index+separator.length()) };
-    }
-
-    public JcloudsBlobStoreBasedObjectStore(JcloudsLocation location, String 
containerName) {
-        this.location = location;
-        String[] segments = splitOnce(containerName);
-        this.containerNameFirstPart = segments[0];
-        this.containerSubPath = segments[1];
-        getBlobStoreContext();
-    }
-
-    public String getSummaryName() {
-        return (locationSpec!=null ? locationSpec : 
location)+":"+getContainerNameFull();
-    }
-    
-    public synchronized BlobStoreContext getBlobStoreContext() {
-        if (context==null) {
-            if (location==null) {
-                Preconditions.checkNotNull(locationSpec, "locationSpec 
required for remote object store when location is null");
-                Preconditions.checkNotNull(mgmt, "mgmt not injected / object 
store not prepared");
-                location = (JcloudsLocation) 
mgmt.getLocationRegistry().resolve(locationSpec);
-            }
-            
-            String identity = 
checkNotNull(location.getConfig(LocationConfigKeys.ACCESS_IDENTITY), "identity 
must not be null");
-            String credential = 
checkNotNull(location.getConfig(LocationConfigKeys.ACCESS_CREDENTIAL), 
"credential must not be null");
-            String provider = 
checkNotNull(location.getConfig(LocationConfigKeys.CLOUD_PROVIDER), "provider 
must not be null");
-            String endpoint = 
location.getConfig(CloudLocationConfig.CLOUD_ENDPOINT);
-
-            context = JcloudsUtil.newBlobstoreContext(provider, endpoint, 
identity, credential);
-     
-            // TODO do we need to get location from region? can't see the 
jclouds API.
-            // doesn't matter in some places because it's already in the 
endpoint
-//            String region = 
location.getConfig(CloudLocationConfig.CLOUD_REGION_ID);
-            context.getBlobStore().createContainerInLocation(null, 
getContainerNameFirstPart());
-        }
-        return context;
-    }
-
-    @Override
-    public void prepareForMasterUse() {
-        // backups not supported here, that is all which is needed for master 
use
-        // that's now normally done *prior* to calling in to here for writes
-        // (and we have already thrown in prepareForSharedUse if legacy 
backups have been specified as required)
-    }
-    
-    public String getContainerName() {
-        return getContainerNameFull();
-    }
-    
-    protected String getContainerNameFull() {
-        return mergePaths(containerNameFirstPart, containerSubPath);
-    }
-
-    protected String getContainerNameFirstPart() {
-        return containerNameFirstPart;
-    }
-    
-    protected String getItemInContainerSubPath(String path) {
-        if (Strings.isBlank(containerSubPath)) return path;
-        return mergePaths(containerSubPath, path);
-    }
-
-    @Override
-    public void createSubPath(String subPath) {
-        // not needed - subpaths are created on demant
-        // (and buggy on softlayer w swift w jclouds 1.7.2:
-        // throws a "not found" if we're creating an empty directory from 
scratch)
-//        context.getBlobStore().createDirectory(getContainerName(), subPath);
-    }
-
-    protected void checkPrepared() {
-        if (context==null)
-            throw new IllegalStateException("object store not prepared");
-    }
-    
-    @Override
-    public StoreObjectAccessor newAccessor(String path) {
-        checkPrepared();
-        return new JcloudsStoreObjectAccessor(context.getBlobStore(), 
getContainerNameFirstPart(), getItemInContainerSubPath(path));
-    }
-
-    protected String mergePaths(String basePath, String ...subPaths) {
-        StringBuilder result = new StringBuilder(basePath);
-        for (String subPath: subPaths) {
-            if (result.length()>0 && subPath.length()>0) {
-                result.append(subPathSeparator());
-                result.append(subPath);
-            }
-        }
-        return result.toString();
-    }
-    
-    protected String subPathSeparator() {
-        // in case some object stores don't allow / for paths
-        return "/";
-    }
-
-    @Override
-    public List<String> listContentsWithSubPath(final String parentSubPath) {
-        checkPrepared();
-        return 
FluentIterable.from(context.getBlobStore().list(getContainerNameFirstPart(), 
-            
ListContainerOptions.Builder.inDirectory(getItemInContainerSubPath(parentSubPath))))
-                .transform(new Function<StorageMetadata, String>() {
-                    @Override
-                    public String apply(@javax.annotation.Nullable 
StorageMetadata input) {
-                        String result = input.getName();
-                        result = Strings.removeFromStart(result, 
containerSubPath);
-                        result = Strings.removeFromStart(result, "/");
-                        return result;
-                    }
-                }).toList();
-    }
-
-    @Override
-    public void close() {
-        if (context!=null)
-            context.close();
-    }
-
-    @Override
-    public String toString() {
-        return Objects.toStringHelper(this)
-                .add("blobStoreContext", context)
-                .add("basedir", containerNameFirstPart)
-                .toString();
-    }
-    
-    @Override
-    public void injectManagementContext(ManagementContext mgmt) {
-        if (this.mgmt!=null && !this.mgmt.equals(mgmt))
-            throw new IllegalStateException("Cannot change mgmt context of 
"+this);
-        this.mgmt = mgmt;
-    }
-    
-    @SuppressWarnings("deprecation")
-    @Override
-    public void prepareForSharedUse(@Nullable PersistMode persistMode, 
HighAvailabilityMode haMode) {
-        if (mgmt==null) throw new NullPointerException("Must inject 
ManagementContext before preparing "+this);
-        
-        getBlobStoreContext();
-        
-        if (persistMode==null || persistMode==PersistMode.DISABLED) {
-            log.warn("Should not be using "+this+" when persistMode is 
"+persistMode);
-            return;
-        }
-        
-        Boolean backups = 
mgmt.getConfig().getConfig(BrooklynServerConfig.PERSISTENCE_BACKUPS_REQUIRED);
-        if (Boolean.TRUE.equals(backups)) {
-            log.warn("Using legacy backup for "+this+"; functionality will be 
removed in future versions, in favor of promotion/demotion-specific backups to 
a configurable backup location.");
-            throw new FatalConfigurationRuntimeException("Backups not 
supported for object store ("+this+")");
-        }
-    }
-
-    @Override
-    public void deleteCompletely() {
-        if (Strings.isBlank(containerSubPath))
-            
getBlobStoreContext().getBlobStore().deleteContainer(containerNameFirstPart);
-        else
-            newAccessor(containerSubPath).delete();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsStoreObjectAccessor.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsStoreObjectAccessor.java
 
b/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsStoreObjectAccessor.java
deleted file mode 100644
index a8f1c76..0000000
--- 
a/locations/jclouds/src/main/java/brooklyn/entity/rebind/persister/jclouds/JcloudsStoreObjectAccessor.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.rebind.persister.jclouds;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Date;
-
-import org.apache.brooklyn.core.mgmt.rebind.persister.PersistenceObjectStore;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.commons.io.Charsets;
-import org.jclouds.blobstore.BlobStore;
-import org.jclouds.blobstore.domain.Blob;
-import org.jclouds.util.Strings2;
-
-import com.google.common.base.Throwables;
-import com.google.common.io.ByteSource;
-import com.google.common.io.ByteStreams;
-
-/**
- * @author Andrea Turli
- */
-public class JcloudsStoreObjectAccessor implements 
PersistenceObjectStore.StoreObjectAccessor {
-
-    private final BlobStore blobStore;
-    private final String containerName;
-    private final String blobName;
-
-    public JcloudsStoreObjectAccessor(BlobStore blobStore, String 
containerName, String blobNameOptionallyWithPath) {
-        this.blobStore = blobStore;
-        this.containerName = containerName;
-        this.blobName = blobNameOptionallyWithPath;
-    }
-
-    @Override
-    public boolean exists() {
-        return blobStore.blobExists(containerName, blobName);
-    }
-
-    @Override
-    public void put(String val) {
-        if (val==null) val = "";
-        
-        blobStore.createContainerInLocation(null, containerName);
-        // seems not needed, at least not w SoftLayer
-//        blobStore.createDirectory(containerName, directoryName);
-        ByteSource payload = ByteSource.wrap(val.getBytes(Charsets.UTF_8));
-        Blob blob;
-        try {
-            blob = blobStore.blobBuilder(blobName).payload(payload)
-                    .contentLength(payload.size())
-                    .build();
-        } catch (IOException e) {
-            throw Throwables.propagate(e);
-        }
-        blobStore.putBlob(containerName, blob);
-    }
-
-    @Override
-    public void append(String val) {
-        String val0 = get();
-        if (val0==null) val0="";
-        if (val==null) val="";
-        put(val0+val);
-    }
-
-    @Override
-    public void delete() {
-        blobStore.removeBlob(containerName, blobName);
-    }
-
-    @Override
-    public String get() {
-        try {
-            Blob blob = blobStore.getBlob(containerName, blobName);
-            if (blob==null) return null;
-            return Strings2.toStringAndClose(blob.getPayload().openStream());
-        } catch (IOException e) {
-            Exceptions.propagateIfFatal(e);
-            throw new IllegalStateException("Error reading blobstore 
"+containerName+" "+blobName+": "+e, e);
-        }
-    }
-
-    @Override
-    public byte[] getBytes() {
-        try {
-            Blob blob = blobStore.getBlob(containerName, blobName);
-            if (blob==null) return null;
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            InputStream in = blob.getPayload().openStream();
-            try {
-                ByteStreams.copy(in, out);
-                return out.toByteArray();
-            } finally {
-                out.close();
-            }
-        } catch (IOException e) {
-            Exceptions.propagateIfFatal(e);
-            throw new IllegalStateException("Error reading blobstore 
"+containerName+" "+blobName+": "+e, e);
-        }
-    }
-
-    @Override
-    public Date getLastModifiedDate() {
-        Blob blob = blobStore.getBlob(containerName, blobName);
-        if (blob==null) return null;
-        return blob.getMetadata().getLastModified();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
 
b/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
deleted file mode 100644
index a08429d..0000000
--- 
a/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.policy.os;
-
-import org.apache.brooklyn.api.entity.Entity;
-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.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.apache.brooklyn.entity.core.AbstractEntity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.location.basic.WinRmMachineLocation;
-import org.apache.brooklyn.policy.core.AbstractPolicy;
-import org.apache.brooklyn.sensor.core.Sensors;
-
-import com.google.common.annotations.Beta;
-
-/**
- * When attached to an entity, this will monitor for when an {@link 
WinRmMachineLocation} is added to that entity
- * (e.g. when a VM has been provisioned for it).
- * 
- * The policy will then add a sensor that advertises the Administrator login 
details.
- * 
- * A preferred mechanism would be for an external key-management tool to 
provide access to the credentials.
- */
-@Beta
-public class AdvertiseWinrmLoginPolicy extends AbstractPolicy implements 
SensorEventListener<Location> {
-
-    // TODO Would like support user-creation over WinRM
-    
-    private static final Logger LOG = 
LoggerFactory.getLogger(AdvertiseWinrmLoginPolicy.class);
-
-    public static final AttributeSensor<String> VM_USER_CREDENTIALS = 
Sensors.newStringSensor(
-            "vm.user.credentials",
-            "The \"<user> : <password> @ <hostname>:<port>\"");
-
-    public void setEntity(EntityLocal entity) {
-        super.setEntity(entity);
-        subscribe(entity, AbstractEntity.LOCATION_ADDED, this);
-    }
-
-    @Override
-    public void onEvent(SensorEvent<Location> event) {
-        final Entity entity = event.getSource();
-        final Location loc = event.getValue();
-        if (loc instanceof WinRmMachineLocation) {
-            advertiseUserAsync(entity, (WinRmMachineLocation)loc);
-        }
-    }
-
-    protected void advertiseUserAsync(final Entity entity, final 
WinRmMachineLocation machine) {
-        String user = machine.getUser();
-        String hostname = machine.getHostname();
-        int port = machine.config().get(WinRmMachineLocation.WINRM_PORT);
-        String password = machine.config().get(WinRmMachineLocation.PASSWORD);
-        
-        String creds = user + " : " + password + " @ " +hostname + ":" + port;
-        
-        LOG.info("Advertising user "+user+" @ "+hostname+":"+port);
-        
-        ((EntityLocal)entity).setAttribute(VM_USER_CREDENTIALS, creds);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java 
b/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
deleted file mode 100644
index f47a318..0000000
--- a/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.policy.os;
-
-import java.util.List;
-
-import org.apache.brooklyn.api.entity.Entity;
-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.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.entity.core.AbstractEntity;
-import org.apache.brooklyn.entity.core.EntityInternal;
-import org.jclouds.compute.config.AdminAccessConfiguration;
-import org.jclouds.scriptbuilder.functions.InitAdminAccess;
-import org.jclouds.scriptbuilder.statements.login.AdminAccess;
-import org.jclouds.scriptbuilder.statements.ssh.SshdConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import org.apache.brooklyn.policy.core.AbstractPolicy;
-import org.apache.brooklyn.sensor.core.Sensors;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-import org.apache.brooklyn.util.core.internal.ssh.SshTool;
-import org.apache.brooklyn.util.text.Identifiers;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * When attached to an entity, this will monitor for when an {@link 
SshMachineLocation} is added to that entity
- * (e.g. when a VM has been provisioned for it).
- * 
- * The policy will then (asynchronously) add a new user to the VM, with a 
randomly generated password.
- * The ssh details will be set as a sensor on the entity.
- * 
- * If this is used, it is strongly encouraged to tell users to change the 
password on first login.
- * 
- * A preferred mechanism would be for an external key-management tool to 
generate ssh key-pairs for
- * the user, and for the public key to be passed to Brooklyn. However, there 
is not a customer 
- * requirement for that yet, so focusing on the password-approach.
- */
-@Beta
-public class CreateUserPolicy extends AbstractPolicy implements 
SensorEventListener<Location> {
-
-    // TODO Should add support for authorizing ssh keys as well
-    
-    // TODO Should review duplication with:
-    //  - JcloudsLocationConfig.GRANT_USER_SUDO
-    //    (but config default/description and context of use are different)
-    //  - AdminAccess in JcloudsLocation.createUserStatements
-    
-    // TODO Could make the password explicitly configurable, or auto-generate 
if not set?
-    
-    private static final Logger LOG = 
LoggerFactory.getLogger(CreateUserPolicy.class);
-
-    @SetFromFlag("user")
-    public static final ConfigKey<String> VM_USERNAME = 
ConfigKeys.newStringConfigKey("createuser.vm.user.name");
-
-    @SetFromFlag("grantSudo")
-    public static final ConfigKey<Boolean> GRANT_SUDO = 
ConfigKeys.newBooleanConfigKey(
-            "createuser.vm.user.grantSudo",
-            "Whether to give the new user sudo rights",
-            false);
-
-    public static final AttributeSensor<String> VM_USER_CREDENTIALS = 
Sensors.newStringSensor(
-            "createuser.vm.user.credentials",
-            "The \"<user> : <password> @ <hostname>:<port>\"");
-
-    public void setEntity(EntityLocal entity) {
-        super.setEntity(entity);
-        subscribe(entity, AbstractEntity.LOCATION_ADDED, this);
-    }
-
-    @Override
-    public void onEvent(SensorEvent<Location> event) {
-        final Entity entity = event.getSource();
-        final Location loc = event.getValue();
-        if (loc instanceof SshMachineLocation) {
-            addUserAsync(entity, (SshMachineLocation)loc);
-        }
-    }
-
-    protected void addUserAsync(final Entity entity, final SshMachineLocation 
machine) {
-        ((EntityInternal)entity).getExecutionContext().execute(new Runnable() {
-            public void run() {
-                addUser(entity, machine);
-            }});
-    }
-    
-    protected void addUser(Entity entity, SshMachineLocation machine) {
-        boolean grantSudo = getRequiredConfig(GRANT_SUDO);
-        String user = getRequiredConfig(VM_USERNAME);
-        String password = Identifiers.makeRandomId(12);
-        String hostname = machine.getAddress().getHostName();
-        int port = machine.getPort();
-        String creds = user + " : " + password + " @ " +hostname + ":" + port;
-        
-        LOG.info("Adding auto-generated user "+user+" @ "+hostname+":"+port);
-        
-        // Build the command to create the user
-        // Note AdminAccess requires _all_ fields set, due to 
http://code.google.com/p/jclouds/issues/detail?id=1095
-        // If jclouds grants Sudo rights, it overwrites the /etc/sudoers, 
which makes integration tests very dangerous! Not using it.
-        AdminAccess adminAccess = AdminAccess.builder()
-                .adminUsername(user)
-                .adminPassword(password)
-                .grantSudoToAdminUser(false)
-                .resetLoginPassword(true)
-                .loginPassword(password)
-                .authorizeAdminPublicKey(false)
-                .adminPublicKey("ignored")
-                .installAdminPrivateKey(false)
-                .adminPrivateKey("ignore")
-                .lockSsh(false)
-                .build();
-        
-        org.jclouds.scriptbuilder.domain.OsFamily scriptOsFamily = 
(machine.getMachineDetails().getOsDetails().isWindows()) 
-                ? org.jclouds.scriptbuilder.domain.OsFamily.WINDOWS
-                : org.jclouds.scriptbuilder.domain.OsFamily.UNIX;
-        
-        InitAdminAccess initAdminAccess = new InitAdminAccess(new 
AdminAccessConfiguration.Default());
-        initAdminAccess.visit(adminAccess);
-        String cmd = adminAccess.render(scriptOsFamily);
-
-        // Exec command to create the user
-        int result = 
machine.execScript(ImmutableMap.of(SshTool.PROP_RUN_AS_ROOT.getName(), true), 
"create-user-"+user, ImmutableList.of(cmd));
-        if (result != 0) {
-            throw new IllegalStateException("Failed to auto-generate user, 
using command "+cmd);
-        }
-
-        // Exec command to grant password-access to sshd (which may have been 
disabled earlier).
-        cmd = new SshdConfig(ImmutableMap.of("PasswordAuthentication", 
"yes")).render(scriptOsFamily);
-        result = 
machine.execScript(ImmutableMap.of(SshTool.PROP_RUN_AS_ROOT.getName(), true), 
"create-user-"+user, ImmutableList.of(cmd));
-        if (result != 0) {
-            throw new IllegalStateException("Failed to enable 
ssh-login-with-password, using command "+cmd);
-        }
-
-        // Exec command to grant sudo rights.
-        if (grantSudo) {
-            List<String> cmds = ImmutableList.of(
-                    "cat >> /etc/sudoers <<-'END_OF_JCLOUDS_FILE'\n"+
-                            user+" ALL = (ALL) NOPASSWD:ALL\n"+
-                            "END_OF_JCLOUDS_FILE\n",
-                    "chmod 0440 /etc/sudoers");
-            result = 
machine.execScript(ImmutableMap.of(SshTool.PROP_RUN_AS_ROOT.getName(), true), 
"add-user-to-sudoers-"+user, cmds);
-            if (result != 0) {
-                throw new IllegalStateException("Failed to auto-generate user, 
using command "+cmd);
-            }
-        }
-        
-        ((EntityLocal)entity).setAttribute(VM_USER_CREDENTIALS, creds);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsBlobStoreBasedObjectStore.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsBlobStoreBasedObjectStore.java
 
b/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsBlobStoreBasedObjectStore.java
new file mode 100644
index 0000000..182e8cd
--- /dev/null
+++ 
b/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsBlobStoreBasedObjectStore.java
@@ -0,0 +1,237 @@
+/*
+ * 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.mgmt.persist.jclouds;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.mgmt.persist.PersistMode;
+import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore;
+import org.apache.brooklyn.core.server.BrooklynServerConfig;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.domain.StorageMetadata;
+import org.jclouds.blobstore.options.ListContainerOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.location.core.LocationConfigKeys;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.jclouds.JcloudsUtil;
+import org.apache.brooklyn.util.exceptions.FatalConfigurationRuntimeException;
+import org.apache.brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.FluentIterable;
+
+/**
+ * @author Andrea Turli
+ */
+public class JcloudsBlobStoreBasedObjectStore implements 
PersistenceObjectStore {
+
+    private static final Logger log = 
LoggerFactory.getLogger(JcloudsBlobStoreBasedObjectStore.class);
+
+    private final String containerNameFirstPart;
+    private final String containerSubPath;
+    
+    private String locationSpec;
+    private JcloudsLocation location;
+    private BlobStoreContext context;
+
+    private ManagementContext mgmt;
+
+    public JcloudsBlobStoreBasedObjectStore(String locationSpec, String 
containerName) {
+        this.locationSpec = locationSpec;
+        String[] segments = splitOnce(containerName);
+        this.containerNameFirstPart = segments[0];
+        this.containerSubPath = segments[1];
+    }
+    
+    private String[] splitOnce(String path) {
+        String separator = subPathSeparator();
+        int index = path.indexOf(separator);
+        if (index<0) return new String[] { path, "" };
+        return new String[] { path.substring(0, index), 
path.substring(index+separator.length()) };
+    }
+
+    public JcloudsBlobStoreBasedObjectStore(JcloudsLocation location, String 
containerName) {
+        this.location = location;
+        String[] segments = splitOnce(containerName);
+        this.containerNameFirstPart = segments[0];
+        this.containerSubPath = segments[1];
+        getBlobStoreContext();
+    }
+
+    public String getSummaryName() {
+        return (locationSpec!=null ? locationSpec : 
location)+":"+getContainerNameFull();
+    }
+    
+    public synchronized BlobStoreContext getBlobStoreContext() {
+        if (context==null) {
+            if (location==null) {
+                Preconditions.checkNotNull(locationSpec, "locationSpec 
required for remote object store when location is null");
+                Preconditions.checkNotNull(mgmt, "mgmt not injected / object 
store not prepared");
+                location = (JcloudsLocation) 
mgmt.getLocationRegistry().resolve(locationSpec);
+            }
+            
+            String identity = 
checkNotNull(location.getConfig(LocationConfigKeys.ACCESS_IDENTITY), "identity 
must not be null");
+            String credential = 
checkNotNull(location.getConfig(LocationConfigKeys.ACCESS_CREDENTIAL), 
"credential must not be null");
+            String provider = 
checkNotNull(location.getConfig(LocationConfigKeys.CLOUD_PROVIDER), "provider 
must not be null");
+            String endpoint = 
location.getConfig(CloudLocationConfig.CLOUD_ENDPOINT);
+
+            context = JcloudsUtil.newBlobstoreContext(provider, endpoint, 
identity, credential);
+     
+            // TODO do we need to get location from region? can't see the 
jclouds API.
+            // doesn't matter in some places because it's already in the 
endpoint
+//            String region = 
location.getConfig(CloudLocationConfig.CLOUD_REGION_ID);
+            context.getBlobStore().createContainerInLocation(null, 
getContainerNameFirstPart());
+        }
+        return context;
+    }
+
+    @Override
+    public void prepareForMasterUse() {
+        // backups not supported here, that is all which is needed for master 
use
+        // that's now normally done *prior* to calling in to here for writes
+        // (and we have already thrown in prepareForSharedUse if legacy 
backups have been specified as required)
+    }
+    
+    public String getContainerName() {
+        return getContainerNameFull();
+    }
+    
+    protected String getContainerNameFull() {
+        return mergePaths(containerNameFirstPart, containerSubPath);
+    }
+
+    protected String getContainerNameFirstPart() {
+        return containerNameFirstPart;
+    }
+    
+    protected String getItemInContainerSubPath(String path) {
+        if (Strings.isBlank(containerSubPath)) return path;
+        return mergePaths(containerSubPath, path);
+    }
+
+    @Override
+    public void createSubPath(String subPath) {
+        // not needed - subpaths are created on demant
+        // (and buggy on softlayer w swift w jclouds 1.7.2:
+        // throws a "not found" if we're creating an empty directory from 
scratch)
+//        context.getBlobStore().createDirectory(getContainerName(), subPath);
+    }
+
+    protected void checkPrepared() {
+        if (context==null)
+            throw new IllegalStateException("object store not prepared");
+    }
+    
+    @Override
+    public StoreObjectAccessor newAccessor(String path) {
+        checkPrepared();
+        return new JcloudsStoreObjectAccessor(context.getBlobStore(), 
getContainerNameFirstPart(), getItemInContainerSubPath(path));
+    }
+
+    protected String mergePaths(String basePath, String ...subPaths) {
+        StringBuilder result = new StringBuilder(basePath);
+        for (String subPath: subPaths) {
+            if (result.length()>0 && subPath.length()>0) {
+                result.append(subPathSeparator());
+                result.append(subPath);
+            }
+        }
+        return result.toString();
+    }
+    
+    protected String subPathSeparator() {
+        // in case some object stores don't allow / for paths
+        return "/";
+    }
+
+    @Override
+    public List<String> listContentsWithSubPath(final String parentSubPath) {
+        checkPrepared();
+        return 
FluentIterable.from(context.getBlobStore().list(getContainerNameFirstPart(), 
+            
ListContainerOptions.Builder.inDirectory(getItemInContainerSubPath(parentSubPath))))
+                .transform(new Function<StorageMetadata, String>() {
+                    @Override
+                    public String apply(@javax.annotation.Nullable 
StorageMetadata input) {
+                        String result = input.getName();
+                        result = Strings.removeFromStart(result, 
containerSubPath);
+                        result = Strings.removeFromStart(result, "/");
+                        return result;
+                    }
+                }).toList();
+    }
+
+    @Override
+    public void close() {
+        if (context!=null)
+            context.close();
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this)
+                .add("blobStoreContext", context)
+                .add("basedir", containerNameFirstPart)
+                .toString();
+    }
+    
+    @Override
+    public void injectManagementContext(ManagementContext mgmt) {
+        if (this.mgmt!=null && !this.mgmt.equals(mgmt))
+            throw new IllegalStateException("Cannot change mgmt context of 
"+this);
+        this.mgmt = mgmt;
+    }
+    
+    @SuppressWarnings("deprecation")
+    @Override
+    public void prepareForSharedUse(@Nullable PersistMode persistMode, 
HighAvailabilityMode haMode) {
+        if (mgmt==null) throw new NullPointerException("Must inject 
ManagementContext before preparing "+this);
+        
+        getBlobStoreContext();
+        
+        if (persistMode==null || persistMode==PersistMode.DISABLED) {
+            log.warn("Should not be using "+this+" when persistMode is 
"+persistMode);
+            return;
+        }
+        
+        Boolean backups = 
mgmt.getConfig().getConfig(BrooklynServerConfig.PERSISTENCE_BACKUPS_REQUIRED);
+        if (Boolean.TRUE.equals(backups)) {
+            log.warn("Using legacy backup for "+this+"; functionality will be 
removed in future versions, in favor of promotion/demotion-specific backups to 
a configurable backup location.");
+            throw new FatalConfigurationRuntimeException("Backups not 
supported for object store ("+this+")");
+        }
+    }
+
+    @Override
+    public void deleteCompletely() {
+        if (Strings.isBlank(containerSubPath))
+            
getBlobStoreContext().getBlobStore().deleteContainer(containerNameFirstPart);
+        else
+            newAccessor(containerSubPath).delete();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsStoreObjectAccessor.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsStoreObjectAccessor.java
 
b/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsStoreObjectAccessor.java
new file mode 100644
index 0000000..be6a56e
--- /dev/null
+++ 
b/locations/jclouds/src/main/java/org/apache/brooklyn/core/mgmt/persist/jclouds/JcloudsStoreObjectAccessor.java
@@ -0,0 +1,127 @@
+/*
+ * 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.mgmt.persist.jclouds;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+
+import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.commons.io.Charsets;
+import org.jclouds.blobstore.BlobStore;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.util.Strings2;
+
+import com.google.common.base.Throwables;
+import com.google.common.io.ByteSource;
+import com.google.common.io.ByteStreams;
+
+/**
+ * @author Andrea Turli
+ */
+public class JcloudsStoreObjectAccessor implements 
PersistenceObjectStore.StoreObjectAccessor {
+
+    private final BlobStore blobStore;
+    private final String containerName;
+    private final String blobName;
+
+    public JcloudsStoreObjectAccessor(BlobStore blobStore, String 
containerName, String blobNameOptionallyWithPath) {
+        this.blobStore = blobStore;
+        this.containerName = containerName;
+        this.blobName = blobNameOptionallyWithPath;
+    }
+
+    @Override
+    public boolean exists() {
+        return blobStore.blobExists(containerName, blobName);
+    }
+
+    @Override
+    public void put(String val) {
+        if (val==null) val = "";
+        
+        blobStore.createContainerInLocation(null, containerName);
+        // seems not needed, at least not w SoftLayer
+//        blobStore.createDirectory(containerName, directoryName);
+        ByteSource payload = ByteSource.wrap(val.getBytes(Charsets.UTF_8));
+        Blob blob;
+        try {
+            blob = blobStore.blobBuilder(blobName).payload(payload)
+                    .contentLength(payload.size())
+                    .build();
+        } catch (IOException e) {
+            throw Throwables.propagate(e);
+        }
+        blobStore.putBlob(containerName, blob);
+    }
+
+    @Override
+    public void append(String val) {
+        String val0 = get();
+        if (val0==null) val0="";
+        if (val==null) val="";
+        put(val0+val);
+    }
+
+    @Override
+    public void delete() {
+        blobStore.removeBlob(containerName, blobName);
+    }
+
+    @Override
+    public String get() {
+        try {
+            Blob blob = blobStore.getBlob(containerName, blobName);
+            if (blob==null) return null;
+            return Strings2.toStringAndClose(blob.getPayload().openStream());
+        } catch (IOException e) {
+            Exceptions.propagateIfFatal(e);
+            throw new IllegalStateException("Error reading blobstore 
"+containerName+" "+blobName+": "+e, e);
+        }
+    }
+
+    @Override
+    public byte[] getBytes() {
+        try {
+            Blob blob = blobStore.getBlob(containerName, blobName);
+            if (blob==null) return null;
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            InputStream in = blob.getPayload().openStream();
+            try {
+                ByteStreams.copy(in, out);
+                return out.toByteArray();
+            } finally {
+                out.close();
+            }
+        } catch (IOException e) {
+            Exceptions.propagateIfFatal(e);
+            throw new IllegalStateException("Error reading blobstore 
"+containerName+" "+blobName+": "+e, e);
+        }
+    }
+
+    @Override
+    public Date getLastModifiedDate() {
+        Blob blob = blobStore.getBlob(containerName, blobName);
+        if (blob==null) return null;
+        return blob.getMetadata().getLastModified();
+    }
+    
+}


Reply via email to