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(); + } + +}
