You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by gr...@apache.org on 2016/03/22 19:06:43 UTC
[01/10] brooklyn-server git commit: Test the Clocker pattern (of
LocationOwner and DynamicLocation)
Repository: brooklyn-server
Updated Branches:
refs/heads/master 1e5f3b608 -> b8211ed17
Test the Clocker pattern (of LocationOwner and DynamicLocation)
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/292b4cfb
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/292b4cfb
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/292b4cfb
Branch: refs/heads/master
Commit: 292b4cfb8d5b0bbff0f38eba5fc84a1fc9fe4eee
Parents: d059088
Author: Aled Sage <al...@gmail.com>
Authored: Fri Mar 11 19:37:13 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Mar 18 22:18:21 2016 +0000
----------------------------------------------------------------------
...ClockerDynamicLocationPatternRebindTest.java | 113 +++++++++
.../ClockerDynamicLocationPatternTest.java | 96 ++++++++
.../dynamic/clocker/StubAttributes.java | 34 +++
.../location/dynamic/clocker/StubContainer.java | 33 +++
.../dynamic/clocker/StubContainerImpl.java | 123 ++++++++++
.../dynamic/clocker/StubContainerLocation.java | 41 ++++
.../core/location/dynamic/clocker/StubHost.java | 38 +++
.../location/dynamic/clocker/StubHostImpl.java | 127 ++++++++++
.../dynamic/clocker/StubHostLocation.java | 109 ++++++++
.../dynamic/clocker/StubInfrastructure.java | 92 +++++++
.../dynamic/clocker/StubInfrastructureImpl.java | 246 +++++++++++++++++++
.../clocker/StubInfrastructureLocation.java | 83 +++++++
.../location/dynamic/clocker/StubResolver.java | 196 +++++++++++++++
.../location/dynamic/clocker/StubUtils.java | 95 +++++++
14 files changed, 1426 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
new file mode 100644
index 0000000..361ee95
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.location.BasicLocationRegistry;
+import org.apache.brooklyn.core.location.Locations;
+import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class ClockerDynamicLocationPatternRebindTest extends RebindTestFixtureWithApp {
+
+ @Override
+ protected LocalManagementContext createOrigManagementContext() {
+ LocalManagementContext result = super.createOrigManagementContext();
+ StubResolver stubResolver = new StubResolver();
+ ((BasicLocationRegistry)result.getLocationRegistry()).registerResolver(stubResolver);
+ return result;
+ }
+
+ @Override
+ protected LocalManagementContext createNewManagementContext(File mementoDir) {
+ LocalManagementContext result = super.createNewManagementContext(mementoDir);
+ StubResolver stubResolver = new StubResolver();
+ ((BasicLocationRegistry)result.getLocationRegistry()).registerResolver(stubResolver);
+ return result;
+ }
+
+ // To make this fail (with Clocker code as at 2016-03-11) requires several apps - there's a bug
+ // in rebind that only happens when there are several entities, so the order that they rebind
+ // is more interleaved.
+ @Test
+ public void testRebind() throws Exception {
+ final int NUM_INFRAS = 10;
+ final int HOST_CLUSTER_SIZE = 1;
+ Location loc = mgmt().getLocationRegistry().resolve("localhost");
+
+ // Maps from the infrastructure locSpec to the (potentially many) host locSpecs
+ Map<String, List<String>> locSpecs = Maps.newLinkedHashMap();
+
+ for (int i = 0; i < NUM_INFRAS; i++) {
+ StubInfrastructure infra = mgmt().getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class)
+ .configure(StubInfrastructure.LOCATION_NAME, "myname"+i));
+ infra.start(ImmutableList.of(loc));
+ infra.getStubHostCluster().resize(HOST_CLUSTER_SIZE);
+ assertEquals(infra.getStubHostCluster().getMembers().size(), HOST_CLUSTER_SIZE);
+
+ String infraLocSpec = infra.sensors().get(StubInfrastructure.LOCATION_SPEC);
+ List<String> hostLocSpecs = Lists.newArrayList();
+ for (Entity host : infra.getStubHostCluster().getMembers()) {
+ hostLocSpecs.add(host.sensors().get(StubInfrastructure.LOCATION_SPEC));
+ }
+
+ locSpecs.put(infraLocSpec, hostLocSpecs);
+ }
+ assertEquals(locSpecs.size(), NUM_INFRAS); // in case the infrastructures all used the same loc name!
+
+ rebind();
+
+ for (Map.Entry<String, List<String>> entry : locSpecs.entrySet()) {
+ String infraLocSpec = entry.getKey();
+ List<String> hostLocSpecs = entry.getValue();
+
+ StubInfrastructureLocation newInfraLoc = (StubInfrastructureLocation) mgmt().getLocationRegistry().resolve(infraLocSpec);
+ assertNotNull(newInfraLoc);
+ for (String hostLocSpec: hostLocSpecs) {
+ StubHostLocation newHostLoc = (StubHostLocation) mgmt().getLocationRegistry().resolve(hostLocSpec);
+ assertNotNull(newHostLoc);
+ }
+
+ // Confirm that it still functions
+ StubContainerLocation containerLoc = (StubContainerLocation) newInfraLoc.obtain(ImmutableMap.of());
+ StubContainer container = containerLoc.getOwner();
+
+ newInfraLoc.release(containerLoc);
+ assertFalse(Entities.isManaged(container));
+ assertFalse(Locations.isManaged(containerLoc));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
new file mode 100644
index 0000000..618c552
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.location.BasicLocationRegistry;
+import org.apache.brooklyn.core.location.Locations;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class ClockerDynamicLocationPatternTest extends BrooklynAppUnitTestSupport {
+
+ private LocalhostMachineProvisioningLocation loc;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+
+ StubResolver stubResolver = new StubResolver();
+ ((BasicLocationRegistry)mgmt.getLocationRegistry()).registerResolver(stubResolver);
+
+ loc = app.newLocalhostProvisioningLocation();
+ }
+
+ @Test
+ public void testCreateAndReleaseDirectly() throws Exception {
+ StubInfrastructure infra = mgmt.getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class));
+ infra.start(ImmutableList.of(loc));
+
+ StubInfrastructureLocation loc = infra.getDynamicLocation();
+ MachineLocation machine = loc.obtain(ImmutableMap.of());
+
+ StubHost host = (StubHost) Iterables.getOnlyElement(infra.getStubHostCluster().getMembers());
+ StubHostLocation hostLoc = host.getDynamicLocation();
+
+ StubContainer container = (StubContainer) Iterables.getOnlyElement(host.getDockerContainerCluster().getMembers());
+ StubContainerLocation containerLoc = container.getDynamicLocation();
+ assertEquals(containerLoc, machine);
+ assertEquals(Iterables.getOnlyElement(hostLoc.getChildren()), machine);
+
+ loc.release(machine);
+ assertFalse(Entities.isManaged(container));
+ assertFalse(Locations.isManaged(containerLoc));
+ }
+
+ @Test
+ public void testThroughLocationRegistry() throws Exception {
+ StubInfrastructure infra = mgmt.getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class));
+ infra.start(ImmutableList.of(loc));
+
+ String infraLocSpec = infra.sensors().get(StubInfrastructure.LOCATION_SPEC);
+ StubInfrastructureLocation infraLoc = (StubInfrastructureLocation) mgmt.getLocationRegistry().resolve(infraLocSpec);
+
+ MachineLocation machine = infraLoc.obtain(ImmutableMap.of());
+
+ StubHost host = (StubHost) Iterables.getOnlyElement(infra.getStubHostCluster().getMembers());
+ String hostLocSpec = host.sensors().get(StubInfrastructure.LOCATION_SPEC);
+ StubHostLocation hostLoc = (StubHostLocation) mgmt.getLocationRegistry().resolve(hostLocSpec);
+
+ StubContainer container = (StubContainer) Iterables.getOnlyElement(host.getDockerContainerCluster().getMembers());
+ StubContainerLocation containerLoc = container.getDynamicLocation();
+ assertEquals(containerLoc, machine);
+ assertEquals(Iterables.getOnlyElement(hostLoc.getChildren()), machine);
+
+ infraLoc.release(machine);
+ assertFalse(Entities.isManaged(container));
+ assertFalse(Locations.isManaged(containerLoc));
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubAttributes.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubAttributes.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubAttributes.java
new file mode 100644
index 0000000..e356801
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubAttributes.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
+
+public class StubAttributes {
+ public static final AttributeSensorAndConfigKey<StubInfrastructure, StubInfrastructure> DOCKER_INFRASTRUCTURE = ConfigKeys.newSensorAndConfigKey(
+ StubInfrastructure.class,
+ "docker.infrastructure",
+ "The Docker infrastructure");
+
+ public static final AttributeSensorAndConfigKey<StubHost, StubHost> DOCKER_HOST = ConfigKeys.newSensorAndConfigKey(
+ StubHost.class,
+ "docker.host",
+ "The Docker Host");
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainer.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainer.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainer.java
new file mode 100644
index 0000000..504159d
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainer.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
+import org.apache.brooklyn.entity.stock.BasicStartable;
+
+@ImplementedBy(StubContainerImpl.class)
+public interface StubContainer extends BasicStartable, LocationOwner<StubContainerLocation, StubContainer> {
+ AttributeSensorAndConfigKey<StubInfrastructure, StubInfrastructure> DOCKER_INFRASTRUCTURE = StubAttributes.DOCKER_INFRASTRUCTURE;
+ AttributeSensorAndConfigKey<StubHost, StubHost> DOCKER_HOST = StubAttributes.DOCKER_HOST;
+
+ StubInfrastructure getInfrastructure();
+ StubHost getDockerHost();
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
new file mode 100644
index 0000000..45cf9d0
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.LocationManager;
+import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
+import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
+import org.apache.brooklyn.core.feed.ConfigToAttributes;
+import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
+import org.apache.brooklyn.entity.stock.BasicStartableImpl;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StubContainerImpl extends BasicStartableImpl implements StubContainer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StubContainerImpl.class);
+
+ @Override
+ public void init() {
+ super.init();
+
+ ConfigToAttributes.apply(this);
+ }
+
+ @Override
+ public StubInfrastructure getInfrastructure() {
+ return config().get(DOCKER_INFRASTRUCTURE);
+ }
+
+ @Override
+ public StubHost getDockerHost() {
+ return (StubHost) config().get(DOCKER_HOST);
+ }
+
+ @Override
+ public StubContainerLocation getDynamicLocation() {
+ return (StubContainerLocation) sensors().get(DYNAMIC_LOCATION);
+ }
+
+ @Override
+ public void start(Collection<? extends Location> locations) {
+ ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
+
+ Map<String, ?> flags = MutableMap.copyOf(config().get(LOCATION_FLAGS));
+ createLocation(flags);
+
+ super.start(locations);
+
+ ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
+ }
+
+ @Override
+ public StubContainerLocation createLocation(Map<String, ?> flags) {
+ StubHost dockerHost = getDockerHost();
+ StubHostLocation host = dockerHost.getDynamicLocation();
+
+ SshMachineLocation containerMachine = getManagementContext().getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+ .configure("address", "1.2.3.4"));
+
+ // Create our wrapper location around the container
+ LocationSpec<StubContainerLocation> spec = LocationSpec.create(StubContainerLocation.class)
+ .parent(host)
+ .configure(flags)
+ .configure(DynamicLocation.OWNER, this)
+ .configure("machine", containerMachine)
+ .configure(containerMachine.config().getBag().getAllConfig());
+ StubContainerLocation location = getManagementContext().getLocationManager().createLocation(spec);
+
+ sensors().set(DYNAMIC_LOCATION, location);
+ sensors().set(LOCATION_NAME, location.getId());
+
+ return location;
+ }
+
+ @Override
+ public boolean isLocationAvailable() {
+ return getDynamicLocation() != null;
+ }
+
+ @Override
+ public void deleteLocation() {
+ StubContainerLocation location = getDynamicLocation();
+
+ if (location != null) {
+ try {
+ location.close();
+ } catch (IOException ioe) {
+ LOG.debug("Error closing container location", ioe);
+ }
+ LocationManager mgr = getManagementContext().getLocationManager();
+ if (mgr.isManaged(location)) {
+ mgr.unmanage(location);
+ }
+ }
+
+ sensors().set(DYNAMIC_LOCATION, null);
+ sensors().set(LOCATION_NAME, null);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
new file mode 100644
index 0000000..f4b0345
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+
+public class StubContainerLocation extends SshMachineLocation implements DynamicLocation<StubContainer, StubContainerLocation> {
+
+ @SetFromFlag("machine")
+ private SshMachineLocation machine;
+
+ @SetFromFlag("owner")
+ private StubContainer owner;
+
+ @Override
+ public StubContainer getOwner() {
+ return owner;
+ }
+
+ public SshMachineLocation getMachine() {
+ return machine;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
new file mode 100644
index 0000000..e5b4005
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.entity.machine.MachineEntity;
+
+@ImplementedBy(StubHostImpl.class)
+public interface StubHost extends MachineEntity, LocationOwner<StubHostLocation, StubHost> {
+ AttributeSensorAndConfigKey<StubInfrastructure, StubInfrastructure> DOCKER_INFRASTRUCTURE = StubAttributes.DOCKER_INFRASTRUCTURE;
+
+ AttributeSensor<DynamicCluster> DOCKER_CONTAINER_CLUSTER = Sensors.newSensor(DynamicCluster.class,
+ "docker.container.cluster", "The cluster of Docker containers");
+
+ StubInfrastructure getInfrastructure();
+ DynamicCluster getDockerContainerCluster();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
new file mode 100644
index 0000000..4c2ad36
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.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.location.dynamic.clocker;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.core.feed.ConfigToAttributes;
+import org.apache.brooklyn.core.location.BasicLocationDefinition;
+import org.apache.brooklyn.core.location.Locations;
+import org.apache.brooklyn.core.location.Machines;
+import org.apache.brooklyn.entity.group.Cluster;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.entity.machine.MachineEntityImpl;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StubHostImpl extends MachineEntityImpl implements StubHost {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StubHostImpl.class);
+
+ @Override
+ public void init() {
+ super.init();
+
+ ConfigToAttributes.apply(this);
+
+ EntitySpec<?> dockerContainerSpec = EntitySpec.create(StubContainer.class)
+ .configure(StubContainer.DOCKER_HOST, this)
+ .configure(StubContainer.DOCKER_INFRASTRUCTURE, getInfrastructure());
+
+ DynamicCluster containers = addChild(EntitySpec.create(DynamicCluster.class)
+ .configure(Cluster.INITIAL_SIZE, 0)
+ .configure(DynamicCluster.QUARANTINE_FAILED_ENTITIES, false)
+ .configure(DynamicCluster.MEMBER_SPEC, dockerContainerSpec)
+ .configure(DynamicCluster.RUNNING_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty())
+ .configure(DynamicCluster.UP_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty())
+ .displayName("Docker Containers"));
+ sensors().set(DOCKER_CONTAINER_CLUSTER, containers);
+ }
+
+ @Override
+ public StubInfrastructure getInfrastructure() {
+ return config().get(DOCKER_INFRASTRUCTURE);
+ }
+
+ @Override
+ public DynamicCluster getDockerContainerCluster() {
+ return sensors().get(DOCKER_CONTAINER_CLUSTER);
+ }
+
+ @Override
+ public StubHostLocation getDynamicLocation() {
+ return (StubHostLocation) sensors().get(DYNAMIC_LOCATION);
+ }
+
+ @Override
+ public void preStart() {
+ super.preStart();
+ ConfigToAttributes.apply(this);
+
+ Maybe<SshMachineLocation> found = Machines.findUniqueMachineLocation(getLocations(), SshMachineLocation.class);
+
+ Map<String, ?> flags = MutableMap.<String, Object>builder()
+ .putAll(config().get(LOCATION_FLAGS))
+ .put("machine", found.get())
+ .build();
+
+ createLocation(flags);
+ sensors().get(DOCKER_CONTAINER_CLUSTER).sensors().set(SERVICE_UP, Boolean.TRUE);
+ }
+
+ @Override
+ public StubHostLocation createLocation(Map<String, ?> flags) {
+ StubInfrastructure infrastructure = getInfrastructure();
+ StubInfrastructureLocation docker = infrastructure.getDynamicLocation();
+ String locationName = docker.getId() + "-" + getId();
+
+ String locationSpec = String.format(StubResolver.DOCKER_HOST_MACHINE_SPEC, infrastructure.getId(), getId()) + String.format(":(name=\"%s\")", locationName);
+ sensors().set(LOCATION_SPEC, locationSpec);
+
+ LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, flags);
+ Location location = getManagementContext().getLocationRegistry().resolve(definition);
+ sensors().set(DYNAMIC_LOCATION, location);
+ sensors().set(LOCATION_NAME, location.getId());
+
+ LOG.info("New Docker host location {} created", location);
+ return (StubHostLocation) location;
+ }
+
+ @Override
+ public boolean isLocationAvailable() {
+ return sensors().get(DYNAMIC_LOCATION) != null;
+ }
+
+ @Override
+ public void deleteLocation() {
+ StubHostLocation loc = (StubHostLocation) sensors().get(DYNAMIC_LOCATION);
+ if (loc != null) {
+ Locations.unmanage(loc);
+ }
+ sensors().set(DYNAMIC_LOCATION, null);
+ sensors().set(LOCATION_NAME, null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
new file mode 100644
index 0000000..a861220
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.LocationConfigKeys;
+import org.apache.brooklyn.core.location.Locations;
+import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class StubHostLocation extends AbstractLocation implements MachineProvisioningLocation<StubContainerLocation>, DynamicLocation<StubHost, StubHostLocation> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StubHostLocation.class);
+
+ @SetFromFlag("machine")
+ private SshMachineLocation machine;
+
+ @SetFromFlag("owner")
+ private StubHost dockerHost;
+
+ @Override
+ public StubHost getOwner() {
+ return (StubHost) getConfig(OWNER);
+ }
+
+ @Override
+ public StubContainerLocation obtain(Map<?, ?> flags) throws NoMachinesAvailableException {
+ Entity callerContext = (Entity) flags.get(LocationConfigKeys.CALLER_CONTEXT.getName());
+ if (callerContext == null) callerContext = getOwner();
+
+ DynamicCluster cluster = dockerHost.getDockerContainerCluster();
+ Entity added = cluster.addNode(machine, flags);
+ if (added == null) {
+ throw new NoMachinesAvailableException(String.format("Failed to create container at %s", dockerHost));
+ } else {
+ Entities.invokeEffector((EntityLocal) callerContext, added, Startable.START, MutableMap.of("locations", ImmutableList.of(machine))).getUnchecked();
+ }
+ StubContainer container = (StubContainer) added;
+
+ return container.getDynamicLocation();
+ }
+
+ @Override
+ public void release(StubContainerLocation machine) {
+ DynamicCluster cluster = dockerHost.getDockerContainerCluster();
+ StubContainer container = machine.getOwner();
+ if (cluster.removeMember(container)) {
+ LOG.info("Docker Host {}: member {} released", dockerHost, machine);
+ } else {
+ LOG.warn("Docker Host {}: member {} not found for release", dockerHost, machine);
+ }
+
+ // Now close and unmange the container
+ try {
+ container.stop();
+ machine.close();
+ } catch (Exception e) {
+ LOG.warn("Error stopping container: " + container, e);
+ Exceptions.propagateIfFatal(e);
+ } finally {
+ Entities.unmanage(container);
+ Locations.unmanage(machine);
+ }
+ }
+
+ @Override
+ public MachineProvisioningLocation<StubContainerLocation> newSubLocation(Map<?, ?> newFlags) {
+ return this;
+ }
+
+ @Override
+ public Map<String, Object> getProvisioningFlags(Collection<String> tags) {
+ return ImmutableMap.<String, Object>of();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
new file mode 100644
index 0000000..3170cf2
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.entity.group.DynamicGroup;
+import org.apache.brooklyn.entity.group.DynamicMultiGroup;
+
+/**
+ * These entities and locations mirror the structure used in Clocker v1 (prepend everything
+ * with "Docker" instead of "Stub"). The purpose of repeating it here is to ensure that the
+ * functionality Clocker is relying on will get regularly tested and kept working - or if it
+ * does change, then Clocker can be updated as appropriate.
+ *
+ * The Clocker hierarchy has the following structure:
+ *
+ * <pre>
+ * Infrastructure -----------> InfrastructureLocation
+ * | |
+ * Host -----------> HostLocation
+ * | |
+ * Container -----------> ContainerLocation
+ * <pre>
+ *
+ * The Infrastructure, Host and Container are all entities that implement {@link LocationOwner}.
+ * Whenever one of these is started, it creates the corresponding Location object (shown on the
+ * right).
+ *
+ * The Infrastructure has a cluster of Host instances. A host has a cluster of Container
+ * instances.
+ *
+ * When the {@code Infrastructure} is initially provisioned, it registers the newly create
+ * location in the {@link ManagementContext#getLocationRegistry()}. This makes it a named
+ * location, which can be used by other apps.
+ *
+ * When {@code InfrastructureLocation.obtain()) is called, it will create a container somewhere in
+ * the cluster. The following chain of events happens:
+ * <ol>
+ * <li>From the {@code Infrastructure} (i.e. the location's "owner"), get the set of
+ * {@code Host}s and thus the set of {@code HostLocation}s.
+ * <li>Choose a {@code HostLocation}
+ * (if there's not one, consider scaling up the {@code Infrastructure}'s cluster, if permitted)
+ * <li>Delegate to {@code DockerHostLocation.obtain()}, and return the result.
+ * <li>The {@code DockerHostLocation} first does some fiddly Docker stuff around images
+ * (not represented in this stub structure).
+ * <li>Get the {@code dockerHost.getDockerContainerCluster()}, and use that to create a new
+ * {@code Container} entity.
+ * <li>Invoke {@code start} effector on the {@code Container} entity
+ * <li>The {code Container.start} calls {@code Container.createLocation}, which instantiates
+ * the actual Docker container (by using the jclouds provider).
+ * <li>Return the {@code container.getDynamicLocation()} (i.e. the {@code ContainerLocation}).
+ * <ul>
+ */
+@ImplementedBy(StubInfrastructureImpl.class)
+public interface StubInfrastructure extends Application, Startable, LocationOwner<StubInfrastructureLocation, StubInfrastructure> {
+ ConfigKey<String> LOCATION_NAME = ConfigKeys.newConfigKeyWithDefault(LocationOwner.LOCATION_NAME.getConfigKey(), "my-stub-cloud");
+
+ AttributeSensor<DynamicCluster> DOCKER_HOST_CLUSTER = Sensors.newSensor(DynamicCluster.class, "docker.hosts", "Docker host cluster");
+ AttributeSensor<DynamicGroup> DOCKER_CONTAINER_FABRIC = Sensors.newSensor(DynamicGroup.class, "docker.fabric", "Docker container fabric");
+ AttributeSensor<DynamicMultiGroup> DOCKER_APPLICATIONS = Sensors.newSensor(DynamicMultiGroup.class, "docker.buckets", "Docker applications");
+
+ List<Entity> getStubHostList();
+ DynamicCluster getStubHostCluster();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
new file mode 100644
index 0000000..0d807fa
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.api.mgmt.LocationManager;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.entity.AbstractApplication;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityPredicates;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.feed.ConfigToAttributes;
+import org.apache.brooklyn.core.location.BasicLocationDefinition;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.entity.group.BasicGroup;
+import org.apache.brooklyn.entity.group.Cluster;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.entity.group.DynamicGroup;
+import org.apache.brooklyn.entity.group.DynamicMultiGroup;
+import org.apache.brooklyn.entity.software.base.SoftwareProcess;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
+import org.apache.brooklyn.util.time.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class StubInfrastructureImpl extends AbstractApplication implements StubInfrastructure {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StubInfrastructureImpl.class);
+
+ @Override
+ public void init() {
+ super.init();
+
+ ConfigToAttributes.apply(this);
+
+ EntitySpec<?> dockerHostSpec = EntitySpec.create(StubHost.class)
+ .configure(StubHost.DOCKER_INFRASTRUCTURE, this)
+ .configure(SoftwareProcess.CHILDREN_STARTABLE_MODE, SoftwareProcess.ChildStartableMode.BACKGROUND_LATE);
+
+ DynamicCluster hosts = addChild(EntitySpec.create(DynamicCluster.class)
+ .configure(Cluster.INITIAL_SIZE, 1)
+ .configure(DynamicCluster.QUARANTINE_FAILED_ENTITIES, true)
+ .configure(DynamicCluster.MEMBER_SPEC, dockerHostSpec)
+ .configure(DynamicCluster.RUNNING_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty())
+ .configure(DynamicCluster.UP_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty())
+ .displayName("Docker Hosts"));
+
+ DynamicGroup fabric = addChild(EntitySpec.create(DynamicGroup.class)
+ .configure(DynamicGroup.ENTITY_FILTER, Predicates.and(Predicates.instanceOf(StubContainer.class), EntityPredicates.attributeEqualTo(StubContainer.DOCKER_INFRASTRUCTURE, this)))
+ .configure(DynamicGroup.MEMBER_DELEGATE_CHILDREN, true)
+ .displayName("All Docker Containers"));
+
+ DynamicMultiGroup buckets = addChild(EntitySpec.create(DynamicMultiGroup.class)
+ .configure(DynamicMultiGroup.ENTITY_FILTER, StubUtils.sameInfrastructure(this))
+ .configure(DynamicMultiGroup.RESCAN_INTERVAL, 15L)
+ .configure(DynamicMultiGroup.BUCKET_FUNCTION, new Function<Entity, String>() {
+ @Override
+ public String apply(@Nullable Entity input) {
+ return input.getApplication().getDisplayName() + ":" + input.getApplicationId();
+ }
+ })
+ .configure(DynamicMultiGroup.BUCKET_SPEC, EntitySpec.create(BasicGroup.class)
+ .configure(BasicGroup.MEMBER_DELEGATE_CHILDREN, true))
+ .displayName("Docker Applications"));
+
+ sensors().set(DOCKER_HOST_CLUSTER, hosts);
+ sensors().set(DOCKER_CONTAINER_FABRIC, fabric);
+ sensors().set(DOCKER_APPLICATIONS, buckets);
+ }
+
+ @Override
+ public void rebind() {
+ super.rebind();
+
+ // Reload our location definition on rebind
+ ManagementContext.PropertiesReloadListener listener = sensors().get(Attributes.PROPERTIES_RELOAD_LISTENER);
+ if (listener != null) {
+ listener.reloaded();
+ }
+ }
+
+ @Override
+ public StubInfrastructureLocation getDynamicLocation() {
+ return (StubInfrastructureLocation) sensors().get(DYNAMIC_LOCATION);
+ }
+
+ @Override
+ public void doStart(Collection<? extends Location> locations) {
+ // TODO support multiple locations
+ sensors().set(SERVICE_UP, Boolean.FALSE);
+
+ Location provisioner = Iterables.getOnlyElement(locations);
+ LOG.info("Creating new DockerLocation wrapping {}", provisioner);
+
+ Map<String, ?> flags = MutableMap.<String, Object>builder()
+ .putAll(config().get(LOCATION_FLAGS))
+ .put("provisioner", provisioner)
+ .build();
+ createLocation(flags);
+
+ super.doStart(locations);
+
+ sensors().set(SERVICE_UP, Boolean.TRUE);
+ }
+
+ /**
+ * De-register our {@link DockerLocation} and its children.
+ */
+ @Override
+ public void stop() {
+ sensors().set(SERVICE_UP, Boolean.FALSE);
+
+ // Find all applications and stop, blocking for up to five minutes until ended
+ try {
+ Iterable<Entity> entities = Iterables.filter(getManagementContext().getEntityManager().getEntities(), StubUtils.sameInfrastructure(this));
+ Set<Application> applications = ImmutableSet.copyOf(Iterables.transform(entities, new Function<Entity, Application>() {
+ @Override
+ public Application apply(Entity input) {
+ return input.getApplication();
+ }
+ }));
+ LOG.debug("Stopping applications: {}", Iterables.toString(applications));
+ Entities.invokeEffectorList(this, applications, Startable.STOP).get(Duration.THIRTY_SECONDS);
+ } catch (Exception e) {
+ LOG.warn("Error stopping applications", e);
+ }
+
+ // Stop all Docker hosts in parallel
+ try {
+ DynamicCluster hosts = sensors().get(DOCKER_HOST_CLUSTER);
+ LOG.debug("Stopping hosts: {}", Iterables.toString(hosts.getMembers()));
+ Entities.invokeEffectorList(this, hosts.getMembers(), Startable.STOP).get(Duration.THIRTY_SECONDS);
+ } catch (Exception e) {
+ LOG.warn("Error stopping hosts", e);
+ }
+
+ // Stop anything else left over
+ super.stop();
+
+ deleteLocation();
+ }
+
+ @Override
+ public StubInfrastructureLocation createLocation(Map<String, ?> flags) {
+ String locationName = config().get(LOCATION_NAME);
+
+ LocationDefinition check = getManagementContext().getLocationRegistry().getDefinedLocationByName(locationName);
+ if (check != null) {
+ throw new IllegalStateException("Location " + locationName + " is already defined: " + check);
+ }
+
+ String locationSpec = String.format(StubResolver.DOCKER_INFRASTRUCTURE_SPEC, getId()) + String.format(":(name=\"%s\")", locationName);
+ sensors().set(LOCATION_SPEC, locationSpec);
+ LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, flags);
+ Location location = getManagementContext().getLocationRegistry().resolve(definition);
+ getManagementContext().getLocationRegistry().updateDefinedLocation(definition);
+
+ ManagementContext.PropertiesReloadListener listener = StubUtils.reloadLocationListener(getManagementContext(), definition);
+ getManagementContext().addPropertiesReloadListener(listener);
+ sensors().set(Attributes.PROPERTIES_RELOAD_LISTENER, listener);
+
+ sensors().set(LocationOwner.LOCATION_DEFINITION, definition);
+ sensors().set(LocationOwner.DYNAMIC_LOCATION, location);
+ sensors().set(LocationOwner.LOCATION_NAME, location.getId());
+
+ return (StubInfrastructureLocation) location;
+ }
+
+ @Override
+ public boolean isLocationAvailable() {
+ return getDynamicLocation() != null;
+ }
+
+ @Override
+ public void deleteLocation() {
+ StubInfrastructureLocation location = getDynamicLocation();
+
+ if (location != null) {
+ LocationManager mgr = getManagementContext().getLocationManager();
+ if (mgr.isManaged(location)) {
+ mgr.unmanage(location);
+ }
+ final LocationDefinition definition = sensors().get(LocationOwner.LOCATION_DEFINITION);
+ if (definition != null) {
+ getManagementContext().getLocationRegistry().removeDefinedLocation(definition.getId());
+ }
+ }
+ ManagementContext.PropertiesReloadListener listener = sensors().get(Attributes.PROPERTIES_RELOAD_LISTENER);
+ if (listener != null) {
+ getManagementContext().removePropertiesReloadListener(listener);
+ }
+
+ sensors().set(LocationOwner.LOCATION_DEFINITION, null);
+ sensors().set(LocationOwner.DYNAMIC_LOCATION, null);
+ sensors().set(LocationOwner.LOCATION_NAME, null);
+ }
+
+ @Override
+ public List<Entity> getStubHostList() {
+ if (getStubHostCluster() == null) {
+ return ImmutableList.of();
+ } else {
+ return ImmutableList.copyOf(getStubHostCluster().getMembers());
+ }
+ }
+
+ @Override
+ public DynamicCluster getStubHostCluster() {
+ return sensors().get(DOCKER_HOST_CLUSTER);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
new file mode 100644
index 0000000..05587f1
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+
+public class StubInfrastructureLocation extends AbstractLocation implements MachineProvisioningLocation<MachineLocation>, DynamicLocation<StubInfrastructure, StubInfrastructureLocation> {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(StubInfrastructureLocation.class);
+
+ @SetFromFlag("owner")
+ private StubInfrastructure infrastructure;
+
+ @SetFromFlag("machines")
+ private final SetMultimap<StubHostLocation, String> containers = Multimaps.synchronizedSetMultimap(HashMultimap.<StubHostLocation, String>create());
+
+ @Override
+ public StubInfrastructure getOwner() {
+ return infrastructure;
+ }
+
+ @Override
+ public MachineLocation obtain(Map<?, ?> flags) throws NoMachinesAvailableException {
+ StubHost host = (StubHost) Iterables.get(infrastructure.getStubHostList(), 0);
+ StubHostLocation hostLocation = host.getDynamicLocation();
+ StubContainerLocation containerLocation = hostLocation.obtain(flags);
+ containers.put(hostLocation, containerLocation.getId());
+ return containerLocation;
+ }
+
+ @Override
+ public void release(MachineLocation machine) {
+ Set<StubHostLocation> set = Multimaps.filterValues(containers, Predicates.equalTo(machine.getId())).keySet();
+ StubHostLocation hostLocation = Iterables.getOnlyElement(set);
+ hostLocation.release((StubContainerLocation)machine);
+ containers.remove(hostLocation, machine);
+ }
+
+ @Override
+ public MachineProvisioningLocation<MachineLocation> newSubLocation(Map<?, ?> newFlags) {
+ return this;
+ }
+
+ @Override
+ public Map<String, Object> getProvisioningFlags(Collection<String> tags) {
+ return ImmutableMap.of();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
new file mode 100644
index 0000000..99fd2b1
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationRegistry;
+import org.apache.brooklyn.api.location.LocationResolver.EnableableLocationResolver;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.location.BasicLocationRegistry;
+import org.apache.brooklyn.core.location.LocationPropertiesFromBrooklynProperties;
+import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
+import org.apache.brooklyn.core.location.internal.LocationInternal;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.text.KeyValueParser;
+import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * Examples of valid specs:
+ * <ul>
+ * <li>docker:infrastructureId
+ * <li>docker:infrastructureId:(name=docker-infrastructure)
+ * <li>docker:infrastructureId:dockerHostId
+ * <li>docker:infrastructureId:dockerHostId:(name=dockerHost-brooklyn-1234,user=docker)
+ * </ul>
+ */
+public class StubResolver implements EnableableLocationResolver {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StubResolver.class);
+
+ public static final String DOCKER = "docker";
+ public static final Pattern PATTERN = Pattern.compile("("+DOCKER+"|"+DOCKER.toUpperCase()+")" + ":([a-zA-Z0-9]+)" +
+ "(:([a-zA-Z0-9]+))?" + "(:\\((.*)\\))?$");
+ public static final Set<String> ACCEPTABLE_ARGS = ImmutableSet.of("name", "displayName");
+
+ public static final String DOCKER_INFRASTRUCTURE_SPEC = "docker:%s";
+ public static final String DOCKER_HOST_MACHINE_SPEC = "docker:%s:%s";
+
+ private ManagementContext managementContext;
+
+ @Override
+ public void init(ManagementContext managementContext) {
+ this.managementContext = checkNotNull(managementContext, "managementContext");
+ }
+
+ @Override
+ public String getPrefix() {
+ return DOCKER;
+ }
+
+ @Override
+ public Location newLocationFromString(Map locationFlags, String spec, LocationRegistry registry) {
+ return newLocationFromString(spec, registry, registry.getProperties(), locationFlags);
+ }
+
+ protected Location newLocationFromString(String spec, LocationRegistry registry, Map properties, Map locationFlags) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Resolving location '" + spec + "' with flags " + Joiner.on(",").withKeyValueSeparator("=").join(locationFlags));
+ }
+ String namedLocation = (String) locationFlags.get(LocationInternal.NAMED_SPEC_NAME.getName());
+
+ Matcher matcher = PATTERN.matcher(spec);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; must specify something like docker:entityId or docker:entityId:(name=abc)");
+ }
+
+ String argsPart = matcher.group(6);
+ Map<String, String> argsMap = (argsPart != null) ? KeyValueParser.parseMap(argsPart) : Collections.<String,String>emptyMap();
+ String displayNamePart = argsMap.get("displayName");
+ String namePart = argsMap.get("name");
+
+ if (!ACCEPTABLE_ARGS.containsAll(argsMap.keySet())) {
+ Set<String> illegalArgs = Sets.difference(argsMap.keySet(), ACCEPTABLE_ARGS);
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; illegal args "+illegalArgs+"; acceptable args are "+ACCEPTABLE_ARGS);
+ }
+ if (argsMap.containsKey("displayName") && Strings.isEmpty(displayNamePart)) {
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; if displayName supplied then value must be non-empty");
+ }
+ if (argsMap.containsKey("name") && Strings.isEmpty(namePart)) {
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; if name supplied then value must be non-empty");
+ }
+
+ Map<String, Object> filteredProperties = new LocationPropertiesFromBrooklynProperties().getLocationProperties(DOCKER, namedLocation, properties);
+ MutableMap<String, Object> flags = MutableMap.<String, Object>builder().putAll(filteredProperties).putAll(locationFlags).build();
+
+ String infrastructureId = matcher.group(2);
+ if (Strings.isBlank(infrastructureId)) {
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; infrastructure entity id must be non-empty");
+ }
+ String dockerHostId = matcher.group(4);
+
+ // Build the display name
+ StringBuilder name = new StringBuilder();
+ if (displayNamePart != null) {
+ name.append(displayNamePart);
+ } else {
+ name.append("Docker ");
+ if (dockerHostId == null) {
+ name.append("Infrastructure ").append(infrastructureId);
+ } else {
+ name.append("Host ").append(dockerHostId);
+ }
+ }
+ final String displayName = name.toString();
+
+ // Build the location name
+ name = new StringBuilder();
+ if (namePart != null) {
+ name.append(namePart);
+ } else {
+ name.append("docker-");
+ name.append(infrastructureId);
+ if (dockerHostId != null) {
+ name.append("-").append(dockerHostId);
+ }
+ }
+ final String locationName = name.toString();
+ StubInfrastructure infrastructure = (StubInfrastructure) managementContext.getEntityManager().getEntity(infrastructureId);
+ Iterable<Location> managedLocations = managementContext.getLocationManager().getLocations();
+
+ if (dockerHostId == null) {
+ for (Location location : managedLocations) {
+ if (location instanceof StubInfrastructureLocation) {
+ if (((StubInfrastructureLocation) location).getOwner().getId().equals(infrastructureId)) {
+ return location;
+ }
+ }
+ }
+ LocationSpec<StubInfrastructureLocation> locationSpec = LocationSpec.create(StubInfrastructureLocation.class)
+ .configure(flags)
+ .configure(DynamicLocation.OWNER, infrastructure)
+ .configure(LocationInternal.NAMED_SPEC_NAME, locationName)
+ .displayName(displayName);
+ return managementContext.getLocationManager().createLocation(locationSpec);
+ } else {
+ StubHost dockerHost = (StubHost) managementContext.getEntityManager().getEntity(dockerHostId);
+ for (Location location : managedLocations) {
+ if (location instanceof StubHostLocation) {
+ if (((StubHostLocation) location).getOwner().getId().equals(dockerHostId)) {
+ return location;
+ }
+ }
+ }
+
+ LocationSpec<StubHostLocation> locationSpec = LocationSpec.create(StubHostLocation.class)
+ .parent(infrastructure.getDynamicLocation())
+ .configure(flags)
+ .configure(DynamicLocation.OWNER, dockerHost)
+ .configure(LocationInternal.NAMED_SPEC_NAME, locationName)
+ .displayName(displayName);
+ return managementContext.getLocationManager().createLocation(locationSpec);
+ }
+ }
+
+ @Override
+ public boolean accepts(String spec, LocationRegistry registry) {
+ return BasicLocationRegistry.isResolverPrefixForSpec(this, spec, true);
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+// return Iterables.tryFind(managementContext.getEntityManager().getEntities(), Predicates.instanceOf(StubInfrastructure.class)).isPresent();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/292b4cfb/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubUtils.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubUtils.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubUtils.java
new file mode 100644
index 0000000..eaea4fc
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubUtils.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+public class StubUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StubUtils.class);
+
+ /** Do not instantiate. */
+ private StubUtils() { }
+
+ /*
+ * Configuration and constants.
+ */
+
+ public static final Predicate<Entity> sameInfrastructure(Entity entity) {
+ Preconditions.checkNotNull(entity, "entity");
+ return new SameInfrastructurePredicate(entity.getId());
+ }
+
+ public static class SameInfrastructurePredicate implements Predicate<Entity> {
+
+ private final String id;
+
+ public SameInfrastructurePredicate(String id) {
+ this.id = Preconditions.checkNotNull(id, "id");
+ }
+
+ @Override
+ public boolean apply(@Nullable Entity input) {
+ // Check if entity is deployed to a DockerContainerLocation
+ Optional<Location> lookup = Iterables.tryFind(input.getLocations(), Predicates.instanceOf(StubContainerLocation.class));
+ if (lookup.isPresent()) {
+ StubContainerLocation container = (StubContainerLocation) lookup.get();
+ // Only containers that are part of this infrastructure
+ return id.equals(container.getOwner().getDockerHost().getInfrastructure().getId());
+ } else {
+ return false;
+ }
+ }
+ };
+
+ public static final ManagementContext.PropertiesReloadListener reloadLocationListener(ManagementContext context, LocationDefinition definition) {
+ return new ReloadDockerLocation(context, definition);
+ }
+
+ public static class ReloadDockerLocation implements ManagementContext.PropertiesReloadListener {
+
+ private final ManagementContext context;
+ private final LocationDefinition definition;
+
+ public ReloadDockerLocation(ManagementContext context, LocationDefinition definition) {
+ this.context = Preconditions.checkNotNull(context, "context");
+ this.definition = Preconditions.checkNotNull(definition, "definition");
+ }
+
+ @Override
+ public void reloaded() {
+ Location resolved = context.getLocationRegistry().resolve(definition);
+ context.getLocationRegistry().updateDefinedLocation(definition);
+ context.getLocationManager().manage(resolved);
+ }
+ };
+}
[06/10] brooklyn-server git commit: Fix log.warn when calling
Location.unmanage
Posted by gr...@apache.org.
Fix log.warn when calling Location.unmanage
Previously, if a location being unmanaged had a parent, we’d try to
unmanaged it twice - the second time would give a log.warn
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/3118f427
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/3118f427
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/3118f427
Branch: refs/heads/master
Commit: 3118f427b4bc8e95ce4c19a54f97325957687d61
Parents: 3df2b8b
Author: Aled Sage <al...@gmail.com>
Authored: Tue Mar 22 12:45:03 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Mar 22 12:45:03 2016 +0000
----------------------------------------------------------------------
.../java/org/apache/brooklyn/core/location/AbstractLocation.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3118f427/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java b/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
index dc48862..d4e565e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
@@ -706,7 +706,9 @@ public abstract class AbstractLocation extends AbstractBrooklynObject implements
}
child.setParent(null);
- if (isManaged()) {
+ if (isManaged() && Locations.isManaged(child)) {
+ // This is called as part of child's LocalLocationManager.unmanage; don't try to
+ // unmanage it yet again as then would get a log.warn!
getManagementContext().getLocationManager().unmanage(child);
}
}
[09/10] brooklyn-server git commit: Clocker-testing: fix where we
delete the location
Posted by gr...@apache.org.
Clocker-testing: fix where we delete the location
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b59fda75
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b59fda75
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b59fda75
Branch: refs/heads/master
Commit: b59fda75be280dee68e44115d9ca2112e8404658
Parents: b5dae5b
Author: Aled Sage <al...@gmail.com>
Authored: Tue Mar 22 12:48:01 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Mar 22 12:48:01 2016 +0000
----------------------------------------------------------------------
.../location/dynamic/clocker/StubContainerImpl.java | 8 ++++++++
.../core/location/dynamic/clocker/StubHostImpl.java | 16 ++++++++++++++++
.../dynamic/clocker/StubInfrastructureImpl.java | 6 ++++--
3 files changed, 28 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b59fda75/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
index 45cf9d0..2ef9480 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerImpl.java
@@ -27,11 +27,13 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.mgmt.LocationManager;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
+import org.apache.brooklyn.core.entity.trait.StartableMethods;
import org.apache.brooklyn.core.feed.ConfigToAttributes;
import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
import org.apache.brooklyn.entity.stock.BasicStartableImpl;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.exceptions.Exceptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -74,6 +76,12 @@ public class StubContainerImpl extends BasicStartableImpl implements StubContain
}
@Override
+ public void stop() {
+ super.stop();
+ deleteLocation();
+ }
+
+ @Override
public StubContainerLocation createLocation(Map<String, ?> flags) {
StubHost dockerHost = getDockerHost();
StubHostLocation host = dockerHost.getDynamicLocation();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b59fda75/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
index 3139d93..314ebda 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
@@ -19,10 +19,15 @@
package org.apache.brooklyn.core.location.dynamic.clocker;
import java.util.Map;
+import java.util.Set;
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.feed.ConfigToAttributes;
import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.location.Machines;
@@ -31,9 +36,14 @@ import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
+import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
public class StubHostImpl extends EmptySoftwareProcessImpl implements StubHost {
private static final Logger LOG = LoggerFactory.getLogger(StubHostImpl.class);
@@ -83,6 +93,12 @@ public class StubHostImpl extends EmptySoftwareProcessImpl implements StubHost {
}
@Override
+ public void postStop() {
+ super.postStop();
+ deleteLocation();
+ }
+
+ @Override
public StubHostLocation createLocation(Map<String, ?> flags) {
StubInfrastructure infrastructure = getInfrastructure();
StubInfrastructureLocation docker = infrastructure.getDynamicLocation();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b59fda75/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
index 0f578bc..05367c4 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.entity.AbstractApplication;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityPredicates;
+import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.feed.ConfigToAttributes;
import org.apache.brooklyn.core.location.Locations;
@@ -132,6 +133,7 @@ public class StubInfrastructureImpl extends AbstractApplication implements StubI
*/
@Override
public void stop() {
+ setExpectedStateAndRecordLifecycleEvent(Lifecycle.STOPPING);
sensors().set(SERVICE_UP, Boolean.FALSE);
// Find all applications and stop, blocking for up to five minutes until ended
@@ -158,10 +160,10 @@ public class StubInfrastructureImpl extends AbstractApplication implements StubI
LOG.warn("Error stopping hosts", e);
}
+ deleteLocation();
+
// Stop anything else left over
super.stop();
-
- deleteLocation();
}
@Override
[02/10] brooklyn-server git commit: Clocker pattern: change how
LocationRegistry used
Posted by gr...@apache.org.
Clocker pattern: change how LocationRegistry used
Adds DynamicLocation.register() and .deregister()
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/453183f1
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/453183f1
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/453183f1
Branch: refs/heads/master
Commit: 453183f1d89336ea793aab2edbe05c3b4070104b
Parents: 292b4cf
Author: Aled Sage <al...@gmail.com>
Authored: Fri Mar 11 20:50:45 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Sat Mar 19 21:35:41 2016 +0000
----------------------------------------------------------------------
.../core/location/dynamic/DynamicLocation.java | 12 ++
.../core/location/dynamic/LocationOwner.java | 4 -
...ClockerDynamicLocationPatternRebindTest.java | 35 ++++-
.../ClockerDynamicLocationPatternTest.java | 22 ++-
.../dynamic/clocker/StubContainerLocation.java | 13 +-
.../core/location/dynamic/clocker/StubHost.java | 4 +-
.../location/dynamic/clocker/StubHostImpl.java | 38 +++--
.../dynamic/clocker/StubHostLocation.java | 70 ++++++++-
.../dynamic/clocker/StubInfrastructure.java | 7 +-
.../dynamic/clocker/StubInfrastructureImpl.java | 66 +++-----
.../clocker/StubInfrastructureLocation.java | 62 +++++++-
.../location/dynamic/clocker/StubResolver.java | 157 +++++++------------
.../dynamic/clocker/StubResolverTest.java | 82 ++++++++++
13 files changed, 384 insertions(+), 188 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/core/src/main/java/org/apache/brooklyn/core/location/dynamic/DynamicLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/dynamic/DynamicLocation.java b/core/src/main/java/org/apache/brooklyn/core/location/dynamic/DynamicLocation.java
index b04ebac..d961cdf 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/dynamic/DynamicLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/dynamic/DynamicLocation.java
@@ -20,6 +20,8 @@ package org.apache.brooklyn.core.location.dynamic;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
@@ -47,4 +49,14 @@ public interface DynamicLocation<E extends Entity & LocationOwner<L, E>, L exten
E getOwner();
+ /**
+ * An opportunity to register this location (e.g. with the {@link LocationRegistry} or the
+ * catalog, so that it will be persisted).
+ */
+ LocationDefinition register();
+
+ /**
+ * The complement of {@link #register()}, to deregister this location.
+ */
+ void deregister();
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/core/src/main/java/org/apache/brooklyn/core/location/dynamic/LocationOwner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/dynamic/LocationOwner.java b/core/src/main/java/org/apache/brooklyn/core/location/dynamic/LocationOwner.java
index 718b97e..2c5a66c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/dynamic/LocationOwner.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/dynamic/LocationOwner.java
@@ -22,7 +22,6 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
@@ -71,9 +70,6 @@ public interface LocationOwner<L extends Location & DynamicLocation<E, L>, E ext
AttributeSensor<Boolean> DYNAMIC_LOCATION_STATUS = Sensors.newBooleanSensor(
"entity.dynamicLocation.status", "The status of the location owned by this entity");
- AttributeSensor<LocationDefinition> LOCATION_DEFINITION = Sensors.newSensor(
- LocationDefinition.class, "entity.dynamicLocation.definition", "The location definition for the location owned by this entity");
-
L getDynamicLocation();
L createLocation(Map<String, ?> flags);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
index 361ee95..6ccd86c 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternRebindTest.java
@@ -29,6 +29,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.location.BasicLocationRegistry;
import org.apache.brooklyn.core.location.Locations;
@@ -41,6 +42,9 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+/**
+ * See explanation of what we're testing in {@link StubInfrastructure}.
+ */
public class ClockerDynamicLocationPatternRebindTest extends RebindTestFixtureWithApp {
@Override
@@ -59,9 +63,9 @@ public class ClockerDynamicLocationPatternRebindTest extends RebindTestFixtureWi
return result;
}
- // To make this fail (with Clocker code as at 2016-03-11) requires several apps - there's a bug
- // in rebind that only happens when there are several entities, so the order that they rebind
- // is more interleaved.
+ // To make this fail previously (with Clocker code as at 2016-03-11) required several apps -
+ // there was a bug in rebind that only happened when there were several entities, so the order
+ // that they did the rebind was more interleaved.
@Test
public void testRebind() throws Exception {
final int NUM_INFRAS = 10;
@@ -70,26 +74,45 @@ public class ClockerDynamicLocationPatternRebindTest extends RebindTestFixtureWi
// Maps from the infrastructure locSpec to the (potentially many) host locSpecs
Map<String, List<String>> locSpecs = Maps.newLinkedHashMap();
+ Map<String, List<String>> locNames = Maps.newLinkedHashMap();
for (int i = 0; i < NUM_INFRAS; i++) {
+ String infraLocName = "myname"+i;
StubInfrastructure infra = mgmt().getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class)
- .configure(StubInfrastructure.LOCATION_NAME, "myname"+i));
+ .configure(StubInfrastructure.LOCATION_NAME, infraLocName)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true));
infra.start(ImmutableList.of(loc));
infra.getStubHostCluster().resize(HOST_CLUSTER_SIZE);
assertEquals(infra.getStubHostCluster().getMembers().size(), HOST_CLUSTER_SIZE);
String infraLocSpec = infra.sensors().get(StubInfrastructure.LOCATION_SPEC);
List<String> hostLocSpecs = Lists.newArrayList();
+ List<String> hostLocNames = Lists.newArrayList();
for (Entity host : infra.getStubHostCluster().getMembers()) {
- hostLocSpecs.add(host.sensors().get(StubInfrastructure.LOCATION_SPEC));
+ hostLocSpecs.add(host.sensors().get(StubHost.LOCATION_SPEC));
+ hostLocNames.add(host.sensors().get(StubHost.LOCATION_NAME));
}
locSpecs.put(infraLocSpec, hostLocSpecs);
+ locNames.put(infraLocName, hostLocNames);
}
assertEquals(locSpecs.size(), NUM_INFRAS); // in case the infrastructures all used the same loc name!
+ assertEquals(locNames.size(), NUM_INFRAS); // in case the infrastructures all used the same loc name!
rebind();
-
+
+ for (Map.Entry<String, List<String>> entry : locNames.entrySet()) {
+ String infraLocName = entry.getKey();
+ List<String> hostLocName = entry.getValue();
+
+ StubInfrastructureLocation newInfraLoc = (StubInfrastructureLocation) mgmt().getLocationRegistry().resolve(infraLocName);
+ assertNotNull(newInfraLoc);
+ for (String hostLocSpec: hostLocName) {
+ StubHostLocation newHostLoc = (StubHostLocation) mgmt().getLocationRegistry().resolve(hostLocSpec);
+ assertNotNull(newHostLoc);
+ }
+ }
+
for (Map.Entry<String, List<String>> entry : locSpecs.entrySet()) {
String infraLocSpec = entry.getKey();
List<String> hostLocSpecs = entry.getValue();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
index 618c552..b67b11c 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/ClockerDynamicLocationPatternTest.java
@@ -20,13 +20,16 @@ package org.apache.brooklyn.core.location.dynamic.clocker;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.location.BasicLocationRegistry;
import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -35,6 +38,9 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
+/**
+ * See explanation of what we're testing in {@link StubInfrastructure}.
+ */
public class ClockerDynamicLocationPatternTest extends BrooklynAppUnitTestSupport {
private LocalhostMachineProvisioningLocation loc;
@@ -51,7 +57,8 @@ public class ClockerDynamicLocationPatternTest extends BrooklynAppUnitTestSuppor
@Test
public void testCreateAndReleaseDirectly() throws Exception {
- StubInfrastructure infra = mgmt.getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class));
+ StubInfrastructure infra = mgmt.getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution()));
infra.start(ImmutableList.of(loc));
StubInfrastructureLocation loc = infra.getDynamicLocation();
@@ -72,17 +79,24 @@ public class ClockerDynamicLocationPatternTest extends BrooklynAppUnitTestSuppor
@Test
public void testThroughLocationRegistry() throws Exception {
- StubInfrastructure infra = mgmt.getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class));
+ StubInfrastructure infra = mgmt.getEntityManager().createEntity(EntitySpec.create(StubInfrastructure.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution()));
infra.start(ImmutableList.of(loc));
String infraLocSpec = infra.sensors().get(StubInfrastructure.LOCATION_SPEC);
+ String infraLocName = infra.sensors().get(StubInfrastructure.LOCATION_NAME);
StubInfrastructureLocation infraLoc = (StubInfrastructureLocation) mgmt.getLocationRegistry().resolve(infraLocSpec);
-
+ StubInfrastructureLocation infraLoc2 = (StubInfrastructureLocation) mgmt.getLocationRegistry().resolve(infraLocName);
+ assertSame(infraLoc, infraLoc2);
+
MachineLocation machine = infraLoc.obtain(ImmutableMap.of());
StubHost host = (StubHost) Iterables.getOnlyElement(infra.getStubHostCluster().getMembers());
- String hostLocSpec = host.sensors().get(StubInfrastructure.LOCATION_SPEC);
+ String hostLocSpec = host.sensors().get(StubHost.LOCATION_SPEC);
+ String hostLocName = host.sensors().get(StubHost.LOCATION_NAME);
StubHostLocation hostLoc = (StubHostLocation) mgmt.getLocationRegistry().resolve(hostLocSpec);
+ StubHostLocation hostLoc2 = (StubHostLocation) mgmt.getLocationRegistry().resolve(hostLocName);
+ assertSame(hostLoc, hostLoc2);
StubContainer container = (StubContainer) Iterables.getOnlyElement(host.getDockerContainerCluster().getMembers());
StubContainerLocation containerLoc = container.getDynamicLocation();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
index f4b0345..570cd73 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubContainerLocation.java
@@ -18,6 +18,7 @@
*/
package org.apache.brooklyn.core.location.dynamic.clocker;
+import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
@@ -38,4 +39,14 @@ public class StubContainerLocation extends SshMachineLocation implements Dynamic
public SshMachineLocation getMachine() {
return machine;
}
-}
\ No newline at end of file
+
+ @Override
+ public LocationDefinition register() {
+ throw new UnsupportedOperationException("Container location type definition cannot be persisted");
+ }
+
+ @Override
+ public void deregister() {
+ // no-op
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
index e5b4005..6b2d319 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHost.java
@@ -24,10 +24,10 @@ import org.apache.brooklyn.core.location.dynamic.LocationOwner;
import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.entity.group.DynamicCluster;
-import org.apache.brooklyn.entity.machine.MachineEntity;
+import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
@ImplementedBy(StubHostImpl.class)
-public interface StubHost extends MachineEntity, LocationOwner<StubHostLocation, StubHost> {
+public interface StubHost extends EmptySoftwareProcess, LocationOwner<StubHostLocation, StubHost> {
AttributeSensorAndConfigKey<StubInfrastructure, StubInfrastructure> DOCKER_INFRASTRUCTURE = StubAttributes.DOCKER_INFRASTRUCTURE;
AttributeSensor<DynamicCluster> DOCKER_CONTAINER_CLUSTER = Sensors.newSensor(DynamicCluster.class,
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
index 4c2ad36..3139d93 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostImpl.java
@@ -21,23 +21,20 @@ package org.apache.brooklyn.core.location.dynamic.clocker;
import java.util.Map;
import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.feed.ConfigToAttributes;
-import org.apache.brooklyn.core.location.BasicLocationDefinition;
import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.location.Machines;
import org.apache.brooklyn.entity.group.Cluster;
import org.apache.brooklyn.entity.group.DynamicCluster;
-import org.apache.brooklyn.entity.machine.MachineEntityImpl;
+import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
-import org.apache.brooklyn.util.guava.Maybe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class StubHostImpl extends MachineEntityImpl implements StubHost {
+public class StubHostImpl extends EmptySoftwareProcessImpl implements StubHost {
private static final Logger LOG = LoggerFactory.getLogger(StubHostImpl.class);
@@ -81,14 +78,7 @@ public class StubHostImpl extends MachineEntityImpl implements StubHost {
super.preStart();
ConfigToAttributes.apply(this);
- Maybe<SshMachineLocation> found = Machines.findUniqueMachineLocation(getLocations(), SshMachineLocation.class);
-
- Map<String, ?> flags = MutableMap.<String, Object>builder()
- .putAll(config().get(LOCATION_FLAGS))
- .put("machine", found.get())
- .build();
-
- createLocation(flags);
+ createLocation(config().get(LOCATION_FLAGS));
sensors().get(DOCKER_CONTAINER_CLUSTER).sensors().set(SERVICE_UP, Boolean.TRUE);
}
@@ -96,18 +86,25 @@ public class StubHostImpl extends MachineEntityImpl implements StubHost {
public StubHostLocation createLocation(Map<String, ?> flags) {
StubInfrastructure infrastructure = getInfrastructure();
StubInfrastructureLocation docker = infrastructure.getDynamicLocation();
+ SshMachineLocation machine = Machines.findUniqueMachineLocation(getLocations(), SshMachineLocation.class).get();
String locationName = docker.getId() + "-" + getId();
- String locationSpec = String.format(StubResolver.DOCKER_HOST_MACHINE_SPEC, infrastructure.getId(), getId()) + String.format(":(name=\"%s\")", locationName);
- sensors().set(LOCATION_SPEC, locationSpec);
+ StubHostLocation location = getManagementContext().getLocationManager().createLocation(LocationSpec.create(StubHostLocation.class)
+ .parent(infrastructure.getDynamicLocation())
+ .displayName("Docker Host("+getId()+")")
+ .configure(flags)
+ .configure("owner", getProxy())
+ .configure("machine", machine)
+ .configure("locationName", locationName));
+
+ LocationDefinition definition = location.register();
- LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, flags);
- Location location = getManagementContext().getLocationRegistry().resolve(definition);
+ sensors().set(LOCATION_SPEC, definition.getSpec());
+ sensors().set(LOCATION_NAME, locationName);
sensors().set(DYNAMIC_LOCATION, location);
- sensors().set(LOCATION_NAME, location.getId());
LOG.info("New Docker host location {} created", location);
- return (StubHostLocation) location;
+ return location;
}
@Override
@@ -119,6 +116,7 @@ public class StubHostImpl extends MachineEntityImpl implements StubHost {
public void deleteLocation() {
StubHostLocation loc = (StubHostLocation) sensors().get(DYNAMIC_LOCATION);
if (loc != null) {
+ loc.deregister();
Locations.unmanage(loc);
}
sensors().set(DYNAMIC_LOCATION, null);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
index a861220..9c76848 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubHostLocation.java
@@ -18,16 +18,22 @@
*/
package org.apache.brooklyn.core.location.dynamic.clocker;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.util.Collection;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.BasicLocationDefinition;
import org.apache.brooklyn.core.location.LocationConfigKeys;
import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
@@ -46,12 +52,68 @@ public class StubHostLocation extends AbstractLocation implements MachineProvisi
private static final Logger LOG = LoggerFactory.getLogger(StubHostLocation.class);
- @SetFromFlag("machine")
- private SshMachineLocation machine;
+ public static final ConfigKey<String> LOCATION_NAME = ConfigKeys.newStringConfigKey("locationName");
+
+ public static final ConfigKey<SshMachineLocation> MACHINE = ConfigKeys.newConfigKey(
+ SshMachineLocation.class,
+ "machine");
+
+ @SetFromFlag("locationRegistrationId")
+ private String locationRegistrationId;
- @SetFromFlag("owner")
- private StubHost dockerHost;
+ private transient StubHost dockerHost;
+ private transient SshMachineLocation machine;
+
+ @Override
+ public void init() {
+ super.init();
+ dockerHost = (StubHost) checkNotNull(getConfig(OWNER), "owner");
+ machine = (SshMachineLocation) checkNotNull(getConfig(MACHINE), "machine");
+ }
+
+ @Override
+ public void rebind() {
+ super.rebind();
+ dockerHost = (StubHost) getConfig(OWNER);
+ machine = (SshMachineLocation) getConfig(MACHINE);
+
+ if (getConfig(LOCATION_NAME) != null) {
+ register();
+ }
+ }
+
+ @Override
+ public LocationDefinition register() {
+ String locationName = checkNotNull(getConfig(LOCATION_NAME), "config %s", LOCATION_NAME.getName());
+
+ LocationDefinition check = getManagementContext().getLocationRegistry().getDefinedLocationByName(locationName);
+ if (check != null) {
+ throw new IllegalStateException("Location " + locationName + " is already defined: " + check);
+ }
+
+ String hostLocId = getId();
+ String infraLocId = (getParent() != null) ? getParent().getId() : "";
+ String locationSpec = String.format(StubResolver.DOCKER_HOST_MACHINE_SPEC, infraLocId, hostLocId) + String.format(":(name=\"%s\")", locationName);
+
+ LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, ImmutableMap.<String, Object>of());
+ getManagementContext().getLocationRegistry().updateDefinedLocation(definition);
+
+ locationRegistrationId = definition.getId();
+ requestPersist();
+
+ return definition;
+ }
+
+ @Override
+ public void deregister() {
+ if (locationRegistrationId != null) {
+ getManagementContext().getLocationRegistry().removeDefinedLocation(locationRegistrationId);
+ locationRegistrationId = null;
+ requestPersist();
+ }
+ }
+
@Override
public StubHost getOwner() {
return (StubHost) getConfig(OWNER);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
index 3170cf2..f6a9afd 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructure.java
@@ -29,6 +29,8 @@ import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.group.DynamicGroup;
@@ -81,8 +83,9 @@ import org.apache.brooklyn.entity.group.DynamicMultiGroup;
*/
@ImplementedBy(StubInfrastructureImpl.class)
public interface StubInfrastructure extends Application, Startable, LocationOwner<StubInfrastructureLocation, StubInfrastructure> {
- ConfigKey<String> LOCATION_NAME = ConfigKeys.newConfigKeyWithDefault(LocationOwner.LOCATION_NAME.getConfigKey(), "my-stub-cloud");
-
+ AttributeSensorAndConfigKey<String, String> LOCATION_NAME = ConfigKeys.newSensorAndConfigKeyWithDefault(LocationOwner.LOCATION_NAME, "my-stub-cloud");
+ ConfigKey<Integer> DOCKER_HOST_CLUSTER_MIN_SIZE = ConfigKeys.newConfigKeyWithPrefix("docker.host.", DynamicCluster.INITIAL_SIZE);
+
AttributeSensor<DynamicCluster> DOCKER_HOST_CLUSTER = Sensors.newSensor(DynamicCluster.class, "docker.hosts", "Docker host cluster");
AttributeSensor<DynamicGroup> DOCKER_CONTAINER_FABRIC = Sensors.newSensor(DynamicGroup.class, "docker.fabric", "Docker container fabric");
AttributeSensor<DynamicMultiGroup> DOCKER_APPLICATIONS = Sensors.newSensor(DynamicMultiGroup.class, "docker.buckets", "Docker applications");
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
index 0d807fa..0f578bc 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureImpl.java
@@ -30,15 +30,13 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
-import org.apache.brooklyn.api.mgmt.LocationManager;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.entity.AbstractApplication;
-import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityPredicates;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.feed.ConfigToAttributes;
-import org.apache.brooklyn.core.location.BasicLocationDefinition;
+import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.location.dynamic.LocationOwner;
import org.apache.brooklyn.entity.group.BasicGroup;
import org.apache.brooklyn.entity.group.Cluster;
@@ -48,11 +46,13 @@ import org.apache.brooklyn.entity.group.DynamicMultiGroup;
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
+import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
+import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -73,7 +73,7 @@ public class StubInfrastructureImpl extends AbstractApplication implements StubI
.configure(SoftwareProcess.CHILDREN_STARTABLE_MODE, SoftwareProcess.ChildStartableMode.BACKGROUND_LATE);
DynamicCluster hosts = addChild(EntitySpec.create(DynamicCluster.class)
- .configure(Cluster.INITIAL_SIZE, 1)
+ .configure(Cluster.INITIAL_SIZE, config().get(DOCKER_HOST_CLUSTER_MIN_SIZE))
.configure(DynamicCluster.QUARANTINE_FAILED_ENTITIES, true)
.configure(DynamicCluster.MEMBER_SPEC, dockerHostSpec)
.configure(DynamicCluster.RUNNING_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty())
@@ -104,17 +104,6 @@ public class StubInfrastructureImpl extends AbstractApplication implements StubI
}
@Override
- public void rebind() {
- super.rebind();
-
- // Reload our location definition on rebind
- ManagementContext.PropertiesReloadListener listener = sensors().get(Attributes.PROPERTIES_RELOAD_LISTENER);
- if (listener != null) {
- listener.reloaded();
- }
- }
-
- @Override
public StubInfrastructureLocation getDynamicLocation() {
return (StubInfrastructureLocation) sensors().get(DYNAMIC_LOCATION);
}
@@ -178,27 +167,25 @@ public class StubInfrastructureImpl extends AbstractApplication implements StubI
@Override
public StubInfrastructureLocation createLocation(Map<String, ?> flags) {
String locationName = config().get(LOCATION_NAME);
-
- LocationDefinition check = getManagementContext().getLocationRegistry().getDefinedLocationByName(locationName);
- if (check != null) {
- throw new IllegalStateException("Location " + locationName + " is already defined: " + check);
+ if (Strings.isBlank(locationName)) {
+ String prefix = config().get(LOCATION_NAME_PREFIX);
+ String suffix = config().get(LOCATION_NAME_SUFFIX);
+ locationName = Joiner.on("-").skipNulls().join(prefix, getId(), suffix);
}
- String locationSpec = String.format(StubResolver.DOCKER_INFRASTRUCTURE_SPEC, getId()) + String.format(":(name=\"%s\")", locationName);
- sensors().set(LOCATION_SPEC, locationSpec);
- LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, flags);
- Location location = getManagementContext().getLocationRegistry().resolve(definition);
- getManagementContext().getLocationRegistry().updateDefinedLocation(definition);
-
- ManagementContext.PropertiesReloadListener listener = StubUtils.reloadLocationListener(getManagementContext(), definition);
- getManagementContext().addPropertiesReloadListener(listener);
- sensors().set(Attributes.PROPERTIES_RELOAD_LISTENER, listener);
+ StubInfrastructureLocation location = getManagementContext().getLocationManager().createLocation(LocationSpec.create(StubInfrastructureLocation.class)
+ .displayName("Docker Infrastructure("+getId()+")")
+ .configure(flags)
+ .configure("owner", getProxy())
+ .configure("locationName", locationName));
+
+ LocationDefinition definition = location.register();
- sensors().set(LocationOwner.LOCATION_DEFINITION, definition);
+ sensors().set(LocationOwner.LOCATION_SPEC, definition.getSpec());
sensors().set(LocationOwner.DYNAMIC_LOCATION, location);
- sensors().set(LocationOwner.LOCATION_NAME, location.getId());
+ sensors().set(LocationOwner.LOCATION_NAME, locationName);
- return (StubInfrastructureLocation) location;
+ return location;
}
@Override
@@ -211,21 +198,10 @@ public class StubInfrastructureImpl extends AbstractApplication implements StubI
StubInfrastructureLocation location = getDynamicLocation();
if (location != null) {
- LocationManager mgr = getManagementContext().getLocationManager();
- if (mgr.isManaged(location)) {
- mgr.unmanage(location);
- }
- final LocationDefinition definition = sensors().get(LocationOwner.LOCATION_DEFINITION);
- if (definition != null) {
- getManagementContext().getLocationRegistry().removeDefinedLocation(definition.getId());
- }
- }
- ManagementContext.PropertiesReloadListener listener = sensors().get(Attributes.PROPERTIES_RELOAD_LISTENER);
- if (listener != null) {
- getManagementContext().removePropertiesReloadListener(listener);
+ location.deregister();
+ Locations.unmanage(location);
}
- sensors().set(LocationOwner.LOCATION_DEFINITION, null);
sensors().set(LocationOwner.DYNAMIC_LOCATION, null);
sensors().set(LocationOwner.LOCATION_NAME, null);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
index 05587f1..5d5695c 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubInfrastructureLocation.java
@@ -18,14 +18,20 @@
*/
package org.apache.brooklyn.core.location.dynamic.clocker;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.BasicLocationDefinition;
import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.slf4j.Logger;
@@ -43,15 +49,65 @@ public class StubInfrastructureLocation extends AbstractLocation implements Mach
@SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(StubInfrastructureLocation.class);
- @SetFromFlag("owner")
- private StubInfrastructure infrastructure;
+ public static final ConfigKey<String> LOCATION_NAME = ConfigKeys.newStringConfigKey("locationName");
+
+ @SetFromFlag("locationRegistrationId")
+ private String locationRegistrationId;
@SetFromFlag("machines")
private final SetMultimap<StubHostLocation, String> containers = Multimaps.synchronizedSetMultimap(HashMultimap.<StubHostLocation, String>create());
+ private transient StubInfrastructure infrastructure;
+
+ @Override
+ public void init() {
+ super.init();
+ infrastructure = (StubInfrastructure) checkNotNull(getConfig(OWNER), "owner");
+ }
+
+ @Override
+ public void rebind() {
+ super.rebind();
+
+ infrastructure = (StubInfrastructure) getConfig(OWNER);
+
+ if (getConfig(LOCATION_NAME) != null) {
+ register();
+ }
+ }
+
+ @Override
+ public LocationDefinition register() {
+ String locationName = checkNotNull(getConfig(LOCATION_NAME), "config %s", LOCATION_NAME.getName());
+
+ LocationDefinition check = getManagementContext().getLocationRegistry().getDefinedLocationByName(locationName);
+ if (check != null) {
+ throw new IllegalStateException("Location " + locationName + " is already defined: " + check);
+ }
+
+ String locationSpec = String.format(StubResolver.DOCKER_INFRASTRUCTURE_SPEC, getId()) + String.format(":(name=\"%s\")", locationName);
+
+ LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, ImmutableMap.<String, Object>of());
+ getManagementContext().getLocationRegistry().updateDefinedLocation(definition);
+
+ locationRegistrationId = definition.getId();
+ requestPersist();
+
+ return definition;
+ }
+
+ @Override
+ public void deregister() {
+ if (locationRegistrationId != null) {
+ getManagementContext().getLocationRegistry().removeDefinedLocation(locationRegistrationId);
+ locationRegistrationId = null;
+ requestPersist();
+ }
+ }
+
@Override
public StubInfrastructure getOwner() {
- return infrastructure;
+ return (StubInfrastructure) getConfig(OWNER);
}
@Override
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
index 99fd2b1..8aaf4a8 100644
--- a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolver.java
@@ -26,21 +26,23 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
-import org.apache.brooklyn.api.location.LocationResolver.EnableableLocationResolver;
+import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.location.BasicLocationRegistry;
-import org.apache.brooklyn.core.location.LocationPropertiesFromBrooklynProperties;
-import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
-import org.apache.brooklyn.core.location.internal.LocationInternal;
-import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.core.objs.proxy.SpecialBrooklynObjectConstructor;
+import org.apache.brooklyn.core.objs.proxy.SpecialBrooklynObjectConstructor.Config;
import org.apache.brooklyn.util.text.KeyValueParser;
import org.apache.brooklyn.util.text.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -54,17 +56,17 @@ import com.google.common.collect.Sets;
* <li>docker:infrastructureId:dockerHostId:(name=dockerHost-brooklyn-1234,user=docker)
* </ul>
*/
-public class StubResolver implements EnableableLocationResolver {
+public class StubResolver implements LocationResolver {
private static final Logger LOG = LoggerFactory.getLogger(StubResolver.class);
- public static final String DOCKER = "docker";
+ public static final String DOCKER = "stub";
public static final Pattern PATTERN = Pattern.compile("("+DOCKER+"|"+DOCKER.toUpperCase()+")" + ":([a-zA-Z0-9]+)" +
"(:([a-zA-Z0-9]+))?" + "(:\\((.*)\\))?$");
- public static final Set<String> ACCEPTABLE_ARGS = ImmutableSet.of("name", "displayName");
+ public static final String DOCKER_INFRASTRUCTURE_SPEC = "stub:%s";
+ public static final String DOCKER_HOST_MACHINE_SPEC = "stub:%s:%s";
- public static final String DOCKER_INFRASTRUCTURE_SPEC = "docker:%s";
- public static final String DOCKER_HOST_MACHINE_SPEC = "docker:%s:%s";
+ private static final Set<String> ACCEPTABLE_ARGS = ImmutableSet.of("name");
private ManagementContext managementContext;
@@ -79,118 +81,79 @@ public class StubResolver implements EnableableLocationResolver {
}
@Override
- public Location newLocationFromString(Map locationFlags, String spec, LocationRegistry registry) {
- return newLocationFromString(spec, registry, registry.getProperties(), locationFlags);
+ public boolean accepts(String spec, LocationRegistry registry) {
+ return BasicLocationRegistry.isResolverPrefixForSpec(this, spec, true);
}
- protected Location newLocationFromString(String spec, LocationRegistry registry, Map properties, Map locationFlags) {
+ @Override
+ public boolean isEnabled() {
+ // TODO Should we base enablement on whether the required location/entity exists?
+ return true;
+ }
+
+ @Override
+ public LocationSpec<? extends Location> newLocationSpecFromString(String spec, Map<?,?> locationFlags, LocationRegistry registry) {
+ Map<?,?> properties = registry.getProperties();
+
if (LOG.isDebugEnabled()) {
LOG.debug("Resolving location '" + spec + "' with flags " + Joiner.on(",").withKeyValueSeparator("=").join(locationFlags));
}
- String namedLocation = (String) locationFlags.get(LocationInternal.NAMED_SPEC_NAME.getName());
Matcher matcher = PATTERN.matcher(spec);
if (!matcher.matches()) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; must specify something like docker:entityId or docker:entityId:(name=abc)");
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; must specify something like stub:entityId or stub:entityId:(name=abc)");
}
+ String infrastructureLocId = matcher.group(2);
+ if (Strings.isBlank(infrastructureLocId)) {
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; infrastructure location id must be non-empty");
+ }
+ String hostLocId = matcher.group(4);
+
+ // TODO Could validate that the namePart matches the existing loc
String argsPart = matcher.group(6);
Map<String, String> argsMap = (argsPart != null) ? KeyValueParser.parseMap(argsPart) : Collections.<String,String>emptyMap();
- String displayNamePart = argsMap.get("displayName");
+ @SuppressWarnings("unused")
String namePart = argsMap.get("name");
if (!ACCEPTABLE_ARGS.containsAll(argsMap.keySet())) {
Set<String> illegalArgs = Sets.difference(argsMap.keySet(), ACCEPTABLE_ARGS);
throw new IllegalArgumentException("Invalid location '"+spec+"'; illegal args "+illegalArgs+"; acceptable args are "+ACCEPTABLE_ARGS);
}
- if (argsMap.containsKey("displayName") && Strings.isEmpty(displayNamePart)) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; if displayName supplied then value must be non-empty");
- }
- if (argsMap.containsKey("name") && Strings.isEmpty(namePart)) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; if name supplied then value must be non-empty");
- }
- Map<String, Object> filteredProperties = new LocationPropertiesFromBrooklynProperties().getLocationProperties(DOCKER, namedLocation, properties);
- MutableMap<String, Object> flags = MutableMap.<String, Object>builder().putAll(filteredProperties).putAll(locationFlags).build();
-
- String infrastructureId = matcher.group(2);
- if (Strings.isBlank(infrastructureId)) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; infrastructure entity id must be non-empty");
+ Location infrastructureLoc = managementContext.getLocationManager().getLocation(infrastructureLocId);
+ if (infrastructureLoc == null) {
+ throw new IllegalArgumentException("Unknown Clocker infrastructure location id "+infrastructureLocId+", spec "+spec);
+ } else if (!(infrastructureLoc instanceof StubInfrastructureLocation)) {
+ throw new IllegalArgumentException("Invalid location id for Clocker infrastructure, spec "+spec+"; instead matches "+infrastructureLoc);
}
- String dockerHostId = matcher.group(4);
- // Build the display name
- StringBuilder name = new StringBuilder();
- if (displayNamePart != null) {
- name.append(displayNamePart);
- } else {
- name.append("Docker ");
- if (dockerHostId == null) {
- name.append("Infrastructure ").append(infrastructureId);
- } else {
- name.append("Host ").append(dockerHostId);
+ if (hostLocId != null) {
+ Location hostLoc = managementContext.getLocationManager().getLocation(hostLocId);
+ if (hostLoc == null) {
+ throw new IllegalArgumentException("Unknown Clocker host location id "+hostLocId+", spec "+spec);
+ } else if (!(hostLoc instanceof StubHostLocation)) {
+ throw new IllegalArgumentException("Invalid location id for Clocker host, spec "+spec+"; instead matches "+hostLoc);
}
- }
- final String displayName = name.toString();
-
- // Build the location name
- name = new StringBuilder();
- if (namePart != null) {
- name.append(namePart);
+
+ return LocationSpec.create(StubHostLocation.class)
+ .configure(StubLocationConstructor.LOCATION, hostLoc)
+ .configure(Config.SPECIAL_CONSTRUCTOR, StubLocationConstructor.class);
} else {
- name.append("docker-");
- name.append(infrastructureId);
- if (dockerHostId != null) {
- name.append("-").append(dockerHostId);
- }
- }
- final String locationName = name.toString();
- StubInfrastructure infrastructure = (StubInfrastructure) managementContext.getEntityManager().getEntity(infrastructureId);
- Iterable<Location> managedLocations = managementContext.getLocationManager().getLocations();
-
- if (dockerHostId == null) {
- for (Location location : managedLocations) {
- if (location instanceof StubInfrastructureLocation) {
- if (((StubInfrastructureLocation) location).getOwner().getId().equals(infrastructureId)) {
- return location;
- }
- }
- }
- LocationSpec<StubInfrastructureLocation> locationSpec = LocationSpec.create(StubInfrastructureLocation.class)
- .configure(flags)
- .configure(DynamicLocation.OWNER, infrastructure)
- .configure(LocationInternal.NAMED_SPEC_NAME, locationName)
- .displayName(displayName);
- return managementContext.getLocationManager().createLocation(locationSpec);
- } else {
- StubHost dockerHost = (StubHost) managementContext.getEntityManager().getEntity(dockerHostId);
- for (Location location : managedLocations) {
- if (location instanceof StubHostLocation) {
- if (((StubHostLocation) location).getOwner().getId().equals(dockerHostId)) {
- return location;
- }
- }
- }
-
- LocationSpec<StubHostLocation> locationSpec = LocationSpec.create(StubHostLocation.class)
- .parent(infrastructure.getDynamicLocation())
- .configure(flags)
- .configure(DynamicLocation.OWNER, dockerHost)
- .configure(LocationInternal.NAMED_SPEC_NAME, locationName)
- .displayName(displayName);
- return managementContext.getLocationManager().createLocation(locationSpec);
+ return LocationSpec.create(StubInfrastructureLocation.class)
+ .configure(StubLocationConstructor.LOCATION, infrastructureLoc)
+ .configure(Config.SPECIAL_CONSTRUCTOR, StubLocationConstructor.class);
}
}
- @Override
- public boolean accepts(String spec, LocationRegistry registry) {
- return BasicLocationRegistry.isResolverPrefixForSpec(this, spec, true);
- }
-
- @Override
- public boolean isEnabled() {
- return true;
-// return Iterables.tryFind(managementContext.getEntityManager().getEntities(), Predicates.instanceOf(StubInfrastructure.class)).isPresent();
+ @Beta
+ public static class StubLocationConstructor implements SpecialBrooklynObjectConstructor {
+ public static ConfigKey<Location> LOCATION = ConfigKeys.newConfigKey(Location.class, "stubresolver.location");
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T create(ManagementContext mgmt, Class<T> type, AbstractBrooklynObjectSpec<?, ?> spec) {
+ return (T) checkNotNull(spec.getConfig().get(LOCATION), LOCATION.getName());
+ }
}
-
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/453183f1/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolverTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolverTest.java b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolverTest.java
new file mode 100644
index 0000000..6ffb387
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/core/location/dynamic/clocker/StubResolverTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.location.dynamic.clocker;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.location.BasicLocationRegistry;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class StubResolverTest extends BrooklynAppUnitTestSupport {
+
+ private StubInfrastructure infrastructure;
+ private Location localhostLoc;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ StubResolver stubResolver = new StubResolver();
+ ((BasicLocationRegistry)mgmt.getLocationRegistry()).registerResolver(stubResolver);
+
+ infrastructure = app.createAndManageChild(EntitySpec.create(StubInfrastructure.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution())
+ .configure(StubInfrastructure.DOCKER_HOST_CLUSTER_MIN_SIZE, 1));
+ localhostLoc = mgmt.getLocationManager()
+ .createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
+ app.start(ImmutableList.of(localhostLoc));
+ }
+
+ @Test
+ public void testResolveInfrastructure() {
+ String spec = "stub:" + infrastructure.getDynamicLocation().getId();
+ StubInfrastructureLocation loc = (StubInfrastructureLocation) mgmt.getLocationRegistry().resolve(spec);
+ assertEquals(loc, infrastructure.getDynamicLocation());
+
+ String spec2 = infrastructure.sensors().get(LocationOwner.LOCATION_SPEC);
+ StubInfrastructureLocation loc2 = (StubInfrastructureLocation) mgmt.getLocationRegistry().resolve(spec2);
+ assertEquals(loc2, infrastructure.getDynamicLocation());
+ }
+
+ @Test
+ public void testResolveHost() {
+ StubHost host = (StubHost) Iterables.getOnlyElement(infrastructure.getStubHostCluster().getMembers());
+
+ String spec = "stub:" + infrastructure.getDynamicLocation().getId() + ":" + host.getDynamicLocation().getId();
+ StubHostLocation loc = (StubHostLocation) mgmt.getLocationRegistry().resolve(spec);
+ assertEquals(loc, host.getDynamicLocation());
+
+
+ String spec2 = host.sensors().get(LocationOwner.LOCATION_SPEC);
+ StubHostLocation loc2 = (StubHostLocation) mgmt.getLocationRegistry().resolve(spec2);
+ assertEquals(loc2, host.getDynamicLocation());
+ }
+}
[03/10] brooklyn-server git commit: ServerPool: creates/registers
single ServerPoolLocation
Posted by gr...@apache.org.
ServerPool: creates/registers single ServerPoolLocation
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/9f1a1208
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/9f1a1208
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/9f1a1208
Branch: refs/heads/master
Commit: 9f1a120812895a604f42df29f8e16ec4d4a1ed30
Parents: 453183f
Author: Aled Sage <al...@gmail.com>
Authored: Thu Mar 17 12:59:24 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Sat Mar 19 22:03:55 2016 +0000
----------------------------------------------------------------------
.../entity/machine/pool/ServerPool.java | 5 +-
.../entity/machine/pool/ServerPoolImpl.java | 53 +++++++++-------
.../entity/machine/pool/ServerPoolLocation.java | 53 ++++++++++++++--
.../pool/ServerPoolLocationResolver.java | 64 +++++++++----------
.../machine/pool/AbstractServerPoolTest.java | 23 ++++---
.../pool/ServerPoolLocationResolverTest.java | 65 ++++++--------------
.../entity/machine/pool/ServerPoolTest.java | 8 +--
7 files changed, 148 insertions(+), 123 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPool.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPool.java b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPool.java
index 668a89e..4e42778 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPool.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPool.java
@@ -21,8 +21,6 @@ package org.apache.brooklyn.entity.machine.pool;
import java.util.Collection;
import java.util.Map;
-import com.google.common.annotations.Beta;
-
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
@@ -41,6 +39,8 @@ import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.machine.MachineEntity;
+import com.google.common.annotations.Beta;
+
/**
* A preallocated server pool is an entity that other applications can deploy to.
* Behaving as a cluster, the machines it creates for its members are reused.
@@ -70,6 +70,7 @@ import org.apache.brooklyn.entity.machine.MachineEntity;
@ImplementedBy(ServerPoolImpl.class)
@Beta
public interface ServerPool extends DynamicCluster, LocationOwner<ServerPoolLocation, ServerPool> {
+ ConfigKey<String> LOCATION_NAME_PREFIX = ConfigKeys.newConfigKeyWithDefault(LocationOwner.LOCATION_NAME_PREFIX, "server-pool");
ConfigKey<Integer> INITIAL_SIZE = ConfigKeys.newConfigKeyWithDefault(DynamicCluster.INITIAL_SIZE, 2);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolImpl.java b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolImpl.java
index 513ee29..e7ad6db 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolImpl.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolImpl.java
@@ -25,6 +25,8 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.api.location.LocationRegistry;
+import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.mgmt.LocationManager;
@@ -38,19 +40,19 @@ import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.location.BasicLocationDefinition;
import org.apache.brooklyn.core.location.Machines;
import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
import org.apache.brooklyn.core.location.internal.LocationInternal;
import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import org.apache.brooklyn.entity.group.DynamicClusterImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.task.DynamicTasks;
import org.apache.brooklyn.util.guava.Maybe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
@@ -64,6 +66,19 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
+/**
+ * The normal usage pattern is to instantiate this entity to create your cluster, which will
+ * automatically create a {@link ServerPoolLocation}. The location can be looked up from the
+ * {@link LocationRegistry} (e.g. {@code mgmt.getLocationRegistry().resolve("my-pool-name")}),
+ * which uses the {@link ServerPoolLocationResolver}.
+ *
+ * Each location delegates to the associated {@link ServerPool} to claim machines (which are
+ * provisioned as required), and to release machines back to the pool.
+ *
+ * This differs from Clocker's use of {@link DynamicLocation} in that the ServerPool has <em>multiple</em>
+ * locations. This makes the use of {@link LocationOwner} a little confusing
+ * (e.g. {@link LocationOwner#DYNAMIC_LOCATION} is not set).
+ */
public class ServerPoolImpl extends DynamicClusterImpl implements ServerPool {
private static final Logger LOG = LoggerFactory.getLogger(ServerPoolImpl.class);
@@ -96,9 +111,6 @@ public class ServerPoolImpl extends DynamicClusterImpl implements ServerPool {
public static final AttributeSensor<Map<MachineLocation, Entity>> MACHINE_ENTITY = Sensors.newSensor(new TypeToken<Map<MachineLocation, Entity>>() {},
"pool.machineEntityMap", "A mapping of machine locations and their entities");
- public static final AttributeSensor<LocationDefinition> DYNAMIC_LOCATION_DEFINITION = Sensors.newSensor(LocationDefinition.class,
- "pool.locationDefinition", "The location definition used to create the pool's dynamic location");
-
public static final ConfigKey<Boolean> REMOVABLE = ConfigKeys.newBooleanConfigKey(
"pool.member.removable", "Whether a pool member is removable from the cluster. Used to denote additional " +
"existing machines that were manually added to the pool", true);
@@ -171,16 +183,18 @@ public class ServerPoolImpl extends DynamicClusterImpl implements ServerPool {
locationName = Joiner.on("-").skipNulls().join(prefix, getId(), suffix);
}
- String locationSpec = String.format(ServerPoolLocationResolver.POOL_SPEC, getId()) + String.format(":(name=\"%s\")", locationName);
- LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, flags);
- getManagementContext().getLocationRegistry().updateDefinedLocation(definition);
- Location location = getManagementContext().getLocationManager().createLocation( getManagementContext().getLocationRegistry().getLocationSpec(definition).get() );
- LOG.info("Resolved and registered dynamic location {}: {}", locationName, location);
+ ServerPoolLocation location = getManagementContext().getLocationManager().createLocation(LocationSpec.create(ServerPoolLocation.class)
+ .displayName("Server Pool(" + getId() + ")")
+ .configure(flags)
+ .configure("owner", getProxy())
+ .configure("locationName", locationName));
+
+ LocationDefinition definition = location.register();
+ LOG.info("Resolved and registered dynamic location {} for server pool {}: {}", new Object[] {locationName, this, location});
- sensors().set(LOCATION_SPEC, locationSpec);
+ sensors().set(LOCATION_SPEC, definition.getSpec());
+ sensors().set(LOCATION_NAME, locationName);
sensors().set(DYNAMIC_LOCATION, location);
- sensors().set(LOCATION_NAME, location.getId());
- sensors().set(DYNAMIC_LOCATION_DEFINITION, definition);
return (ServerPoolLocation) location;
}
@@ -189,20 +203,15 @@ public class ServerPoolImpl extends DynamicClusterImpl implements ServerPool {
public void deleteLocation() {
LocationManager mgr = getManagementContext().getLocationManager();
ServerPoolLocation location = getDynamicLocation();
- if (mgr.isManaged(location)) {
+ if (location != null && mgr.isManaged(location)) {
LOG.debug("{} deleting and unmanaging location {}", this, location);
+ location.deregister();
mgr.unmanage(location);
}
- // definition will only be null if deleteLocation has already been called, e.g. by two calls to stop().
- LocationDefinition definition = getAttribute(DYNAMIC_LOCATION_DEFINITION);
- if (definition != null) {
- LOG.debug("{} unregistering dynamic location {}", this, definition);
- getManagementContext().getLocationRegistry().removeDefinedLocation(definition.getId());
- }
+
sensors().set(LOCATION_SPEC, null);
sensors().set(DYNAMIC_LOCATION, null);
sensors().set(LOCATION_NAME, null);
- sensors().set(DYNAMIC_LOCATION_DEFINITION, null);
}
@Override
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocation.java b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocation.java
index bc1e2dd..3bb985a 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocation.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocation.java
@@ -23,19 +23,21 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Map;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
+import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.BasicLocationDefinition;
import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
public class ServerPoolLocation extends AbstractLocation implements MachineProvisioningLocation<MachineLocation>,
DynamicLocation<ServerPool, ServerPoolLocation> {
@@ -46,6 +48,12 @@ public class ServerPoolLocation extends AbstractLocation implements MachineProvi
public static final ConfigKey<ServerPool> OWNER = ConfigKeys.newConfigKey(
ServerPool.class, "pool.location.owner");
+ @SetFromFlag("locationName")
+ public static final ConfigKey<String> LOCATION_NAME = ConfigKeys.newStringConfigKey("pool.location.name");
+
+ @SetFromFlag("locationRegistrationId")
+ private String locationRegistrationId;
+
@Override
public void init() {
LOG.debug("Initialising. Owner is: {}", checkNotNull(getConfig(OWNER), OWNER.getName()));
@@ -53,6 +61,41 @@ public class ServerPoolLocation extends AbstractLocation implements MachineProvi
}
@Override
+ public void rebind() {
+ super.rebind();
+
+ if (config().get(LOCATION_NAME) != null) {
+ register();
+ }
+ }
+
+ @Override
+ public LocationDefinition register() {
+ String locationName = checkNotNull(config().get(LOCATION_NAME), "config %s", LOCATION_NAME.getName());
+ LocationDefinition check = getManagementContext().getLocationRegistry().getDefinedLocationByName(locationName);
+ if (check != null) {
+ throw new IllegalStateException("Location " + locationName + " is already defined: " + check);
+ }
+
+ String locationSpec = String.format(ServerPoolLocationResolver.POOL_SPEC, getId()) + String.format(":(name=\"%s\")", locationName);
+
+ LocationDefinition definition = new BasicLocationDefinition(locationName, locationSpec, ImmutableMap.<String, Object>of());
+ getManagementContext().getLocationRegistry().updateDefinedLocation(definition);
+
+ locationRegistrationId = definition.getId();
+ requestPersist();
+
+ return definition;
+ }
+
+ @Override
+ public void deregister() {
+ if (locationRegistrationId != null) {
+ getManagementContext().getLocationRegistry().removeDefinedLocation(locationRegistrationId);
+ }
+ }
+
+ @Override
public ServerPool getOwner() {
return getConfig(OWNER);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolver.java b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolver.java
index 54f232b..6cc9102 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolver.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolver.java
@@ -26,22 +26,24 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.location.BasicLocationRegistry;
import org.apache.brooklyn.core.location.LocationConfigUtils;
-import org.apache.brooklyn.core.location.LocationPropertiesFromBrooklynProperties;
-import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
-import org.apache.brooklyn.core.location.internal.LocationInternal;
-import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.core.objs.proxy.SpecialBrooklynObjectConstructor;
+import org.apache.brooklyn.core.objs.proxy.SpecialBrooklynObjectConstructor.Config;
import org.apache.brooklyn.util.text.KeyValueParser;
import org.apache.brooklyn.util.text.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -55,7 +57,7 @@ public class ServerPoolLocationResolver implements LocationResolver {
":([a-zA-Z0-9]+)" + // pool Id
"(:\\((.*)\\))?$"); // arguments, e.g. displayName
- private static final Set<String> ACCEPTABLE_ARGS = ImmutableSet.of("name", "displayName");
+ private static final Set<String> ACCEPTABLE_ARGS = ImmutableSet.of("name");
private ManagementContext managementContext;
@@ -85,7 +87,6 @@ public class ServerPoolLocationResolver implements LocationResolver {
if (LOG.isDebugEnabled()) {
LOG.debug("Resolving location '" + spec + "' with flags " + Joiner.on(",").withKeyValueSeparator("=").join(locationFlags));
}
- String namedLocation = (String) locationFlags.get(LocationInternal.NAMED_SPEC_NAME.getName());
Matcher matcher = PATTERN.matcher(spec);
if (!matcher.matches()) {
@@ -94,43 +95,42 @@ public class ServerPoolLocationResolver implements LocationResolver {
throw new IllegalArgumentException(m);
}
+ // TODO Could validate that the namePart matches the existing poolLoc
String argsPart = matcher.group(4);
Map<String, String> argsMap = (argsPart != null) ? KeyValueParser.parseMap(argsPart) : Collections.<String,String>emptyMap();
- String displayNamePart = argsMap.get("displayName");
+ @SuppressWarnings("unused")
String namePart = argsMap.get("name");
if (!ACCEPTABLE_ARGS.containsAll(argsMap.keySet())) {
Set<String> illegalArgs = Sets.difference(argsMap.keySet(), ACCEPTABLE_ARGS);
throw new IllegalArgumentException("Invalid location '"+spec+"'; illegal args "+illegalArgs+"; acceptable args are "+ACCEPTABLE_ARGS);
}
- if (argsMap.containsKey("displayName") && Strings.isEmpty(displayNamePart)) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; if displayName supplied then value must be non-empty");
- }
- if (argsMap.containsKey("name") && Strings.isEmpty(namePart)) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; if name supplied then value must be non-empty");
- }
- Map<String, Object> filteredProperties = new LocationPropertiesFromBrooklynProperties()
- .getLocationProperties(PREFIX, namedLocation, registry.getProperties());
- MutableMap<String, Object> flags = MutableMap.<String, Object>builder()
- .putAll(filteredProperties)
- .putAll(locationFlags)
- .build();
-
- String poolId = matcher.group(2);
- if (Strings.isBlank(poolId)) {
- throw new IllegalArgumentException("Invalid location '"+spec+"'; pool's entity id must be non-empty");
+ String poolLocId = matcher.group(2);
+ if (Strings.isBlank(poolLocId)) {
+ throw new IllegalArgumentException("Invalid location '"+spec+"'; pool's location id must be non-empty");
}
- final String displayName = displayNamePart != null ? displayNamePart : "Server Pool " + poolId;
- final String locationName = namePart != null ? namePart : "serverpool-" + poolId;
+ Location poolLoc = managementContext.getLocationManager().getLocation(poolLocId);
+ if (poolLoc == null) {
+ throw new IllegalArgumentException("Unknown ServerPool location id "+poolLocId+", spec "+spec);
+ } else if (!(poolLoc instanceof ServerPoolLocation)) {
+ throw new IllegalArgumentException("Invalid location id for ServerPool, spec "+spec+"; instead matches "+poolLoc);
+ }
- Entity pool = managementContext.getEntityManager().getEntity(poolId);
return LocationSpec.create(ServerPoolLocation.class)
- .configure(flags)
- .configure(DynamicLocation.OWNER, pool)
- .configure(LocationInternal.NAMED_SPEC_NAME, locationName)
- .displayName(displayName);
+ .configure(LocationConstructor.LOCATION, poolLoc)
+ .configure(Config.SPECIAL_CONSTRUCTOR, LocationConstructor.class);
+ }
+
+ @Beta
+ public static class LocationConstructor implements SpecialBrooklynObjectConstructor {
+ public static ConfigKey<Location> LOCATION = ConfigKeys.newConfigKey(Location.class, "serverpoolresolver.location");
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T create(ManagementContext mgmt, Class<T> type, AbstractBrooklynObjectSpec<?, ?> spec) {
+ return (T) checkNotNull(spec.getConfig().get(LOCATION), LOCATION.getName());
+ }
}
-
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/AbstractServerPoolTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/AbstractServerPoolTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/AbstractServerPoolTest.java
index 4a13d0d..0da5a2e 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/AbstractServerPoolTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/AbstractServerPoolTest.java
@@ -30,12 +30,11 @@ import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.entity.machine.pool.ServerPool;
import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
-import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -62,15 +61,14 @@ public abstract class AbstractServerPoolTest {
createdApps.clear();
mgmt = createManagementContext();
location = createLocation();
- EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class)
- .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution());
- poolApp = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+ poolApp = mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution()));
pool = poolApp.createAndManageChild(EntitySpec.create(ServerPool.class)
.configure(ServerPool.INITIAL_SIZE, getInitialPoolSize())
.configure(ServerPool.MEMBER_SPEC, EntitySpec.create(EmptySoftwareProcess.class)));
poolApp.start(ImmutableList.of(location));
- EntityTestUtils.assertAttributeEqualsEventually(pool, Attributes.SERVICE_UP, true);
+ EntityAsserts.assertAttributeEqualsEventually(pool, Attributes.SERVICE_UP, true);
assertAvailableCountEventuallyEquals(getInitialPoolSize());
}
@@ -120,7 +118,7 @@ public abstract class AbstractServerPoolTest {
}
protected void assertAvailableCountEventuallyEquals(ServerPool pool, int count) {
- EntityTestUtils.assertAttributeEqualsEventually(pool, ServerPool.AVAILABLE_COUNT, count);
+ EntityAsserts.assertAttributeEqualsEventually(pool, ServerPool.AVAILABLE_COUNT, count);
}
protected void assertClaimedCountEventuallyEquals(int count) {
@@ -128,16 +126,17 @@ public abstract class AbstractServerPoolTest {
}
protected void assertClaimedCountEventuallyEquals(ServerPool pool, Integer count) {
- EntityTestUtils.assertAttributeEqualsEventually(pool, ServerPool.CLAIMED_COUNT, count);
+ EntityAsserts.assertAttributeEqualsEventually(pool, ServerPool.CLAIMED_COUNT, count);
}
protected TestApplication createAppWithChildren(int numChildren) {
if (numChildren < 0) fail("Invalid number of children for app: " + numChildren);
- EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class)
- .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution());
- TestApplication app = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+
+ TestApplication app = mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution()));
+
while (numChildren-- > 0) {
- app.createAndManageChild(EntitySpec.create(EmptySoftwareProcess.class));
+ app.addChild(EntitySpec.create(EmptySoftwareProcess.class));
}
createdApps.add(app);
return app;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolverTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolverTest.java
index cd71497..482ba42 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolverTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolLocationResolverTest.java
@@ -20,71 +20,44 @@ package org.apache.brooklyn.entity.machine.pool;
import static org.testng.Assert.assertEquals;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
-import org.apache.brooklyn.core.internal.BrooklynProperties;
-import org.apache.brooklyn.core.location.dynamic.DynamicLocation;
-import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
-import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.apache.brooklyn.entity.machine.pool.ServerPool;
-import org.apache.brooklyn.entity.machine.pool.ServerPoolLocation;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.location.dynamic.LocationOwner;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
-import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
-
-public class ServerPoolLocationResolverTest {
+public class ServerPoolLocationResolverTest extends BrooklynAppUnitTestSupport {
- private LocalManagementContext managementContext;
- private Entity locationOwner;
+ private ServerPool serverPool;
@BeforeMethod(alwaysRun=true)
+ @Override
public void setUp() throws Exception {
- managementContext = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty());
- TestApplication t = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
- locationOwner = t.createAndManageChild(EntitySpec.create(ServerPool.class)
+ super.setUp();
+ serverPool = app.createAndManageChild(EntitySpec.create(ServerPool.class)
+ .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution())
.configure(ServerPool.INITIAL_SIZE, 0)
.configure(ServerPool.MEMBER_SPEC, EntitySpec.create(EmptySoftwareProcess.class)));
- Location poolLocation = managementContext.getLocationManager()
+ Location localhostLoc = mgmt.getLocationManager()
.createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
- t.start(ImmutableList.of(poolLocation));
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (managementContext != null) Entities.destroyAll(managementContext);
+ app.start(ImmutableList.of(localhostLoc));
}
@Test
public void testResolve() {
- ServerPoolLocation location = resolve("pool:" + locationOwner.getId());
- assertEquals(location.getOwner().getId(), locationOwner.getId());
+ String spec = "pool:" + serverPool.getDynamicLocation().getId();
+ ServerPoolLocation loc = (ServerPoolLocation) mgmt.getLocationRegistry().getLocationManaged(spec);
+ assertEquals(loc, serverPool.getDynamicLocation());
+
+ String spec2 = serverPool.sensors().get(LocationOwner.LOCATION_SPEC);
+ ServerPoolLocation loc2 = (ServerPoolLocation) mgmt.getLocationRegistry().getLocationManaged(spec2);
+ assertEquals(loc2, serverPool.getDynamicLocation());
}
-
- @Test
- public void testSetsDisplayName() {
- ServerPoolLocation location = resolve("pool:" + locationOwner.getId() + ":(displayName=xyz)");
- assertEquals(location.getDisplayName(), "xyz");
- }
-
- private ServerPoolLocation resolve(String val) {
- Map<String, Object> flags = MutableMap.<String, Object>of(DynamicLocation.OWNER.getName(), locationOwner);
- Location l = managementContext.getLocationRegistry().getLocationManaged(val, flags);
- Assert.assertNotNull(l);
- return (ServerPoolLocation) l;
- }
-
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/9f1a1208/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolTest.java
index 4a24d62..3dacf7f 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/machine/pool/ServerPoolTest.java
@@ -28,10 +28,10 @@ import java.util.Iterator;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.entity.machine.pool.ServerPoolImpl;
-import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
@@ -59,7 +59,7 @@ public class ServerPoolTest extends AbstractServerPoolTest {
public void testFailureWhenNotEnoughServersAvailable() {
TestApplication app = createAppWithChildren(getInitialPoolSize() + 1);
assertNoMachinesAvailableForApp(app);
- EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+ EntityAsserts.assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
}
@Test
@@ -68,7 +68,7 @@ public class ServerPoolTest extends AbstractServerPoolTest {
TestApplication app2 = createAppWithChildren(1);
app.start(ImmutableList.of(pool.getDynamicLocation()));
- EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
+ EntityAsserts.assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
assertAvailableCountEventuallyEquals(0);
assertNoMachinesAvailableForApp(app2);
@@ -77,7 +77,7 @@ public class ServerPoolTest extends AbstractServerPoolTest {
assertAvailableCountEventuallyEquals(getInitialPoolSize());
app2.start(ImmutableList.of(pool.getDynamicLocation()));
- EntityTestUtils.assertAttributeEqualsEventually(app2, Attributes.SERVICE_UP, true);
+ EntityAsserts.assertAttributeEqualsEventually(app2, Attributes.SERVICE_UP, true);
assertAvailableCountEventuallyEquals(getInitialPoolSize() - 1);
assertClaimedCountEventuallyEquals(1);
[08/10] brooklyn-server git commit: Fix XML serialiser for
SpecConverter
Posted by gr...@apache.org.
Fix XML serialiser for SpecConverter
It was not thread-safe. The XmlMementoSerializer uses a single
instance of SpecConverter. If multiple threads tried to deserialise
different objects at the same time, they’d overwrite the “instance”
value and cause serious problems deserialising.
Now use thread-local storage for the “instance” cache.
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b5dae5b7
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b5dae5b7
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b5dae5b7
Branch: refs/heads/master
Commit: b5dae5b7ad5b4d0919e00da1f02b5a54a1e4d3e1
Parents: 89b3a66
Author: Aled Sage <al...@gmail.com>
Authored: Tue Mar 22 12:47:36 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Mar 22 12:47:36 2016 +0000
----------------------------------------------------------------------
.../core/mgmt/persist/XmlMementoSerializer.java | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b5dae5b7/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
index 588f8fd..0df2340 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
@@ -393,6 +393,12 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
}
}
+ // Would prefer this as a field of SpecConverter, but can't do that because the class is not static.
+ // Must use thread-local storage because a single instance of the SpecConverter is used by this
+ // XmlMementoSerializer. In BrooklynMementoPersisterToObjectStore.visitMemento, it uses a thread-pool
+ // for concurrently deserializing multiple objects.
+ private static final ThreadLocal<Object> SpecConverterLocalInstance = new ThreadLocal<Object>();
+
/** When reading/writing specs, it checks whether there is a catalog item id set and uses it to load */
public class SpecConverter extends ReflectionConverter {
SpecConverter() {
@@ -454,25 +460,25 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
result.catalogItemId(catalogItemId);
return result;
} finally {
- instance = null;
+ SpecConverterLocalInstance.remove();
if (customLoaderSet) {
popXstreamCustomClassLoader();
}
}
}
- Object instance;
-
@Override
protected Object instantiateNewInstance(HierarchicalStreamReader reader, UnmarshallingContext context) {
// the super calls getAttribute which requires that we have not yet done moveDown,
// so we do this earlier and cache it for when we call super.unmarshal
+ Object instance = SpecConverterLocalInstance.get();
if (instance==null)
throw new IllegalStateException("Instance should be created and cached");
return instance;
}
protected void instantiateNewInstanceSettingCache(HierarchicalStreamReader reader, UnmarshallingContext context) {
- instance = super.instantiateNewInstance(reader, context);
+ Object instance = super.instantiateNewInstance(reader, context);
+ SpecConverterLocalInstance.set(instance);
}
}
[05/10] brooklyn-server git commit: BROOKLYN-242: fix race in
BasicTest.get()
Posted by gr...@apache.org.
BROOKLYN-242: fix race in BasicTest.get()
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/3df2b8b4
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/3df2b8b4
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/3df2b8b4
Branch: refs/heads/master
Commit: 3df2b8b4c131eedd889a319a8ba1f03cfe32e547
Parents: 0b9682b
Author: Aled Sage <al...@gmail.com>
Authored: Tue Mar 22 12:44:11 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Mar 22 12:44:11 2016 +0000
----------------------------------------------------------------------
.../brooklyn/util/core/task/BasicTask.java | 11 +++++++-
.../core/effector/EffectorBasicTest.java | 29 ++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3df2b8b4/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
index efd3001..410ba12 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
@@ -451,7 +451,16 @@ public class BasicTask<T> implements TaskInternal<T> {
}
Long remaining = end==null ? null : end - System.currentTimeMillis();
if (isDone()) {
- return internalFuture.get(1, TimeUnit.MILLISECONDS);
+ // Don't just call internalFuture.get(1ms) - see comment in isDone() about setting of endTimeUtc,
+ // and see BROOKLYN-242.
+ if (internalFuture == null) {
+ assert cancelled: "task="+this+"; endTimeUtc="+endTimeUtc+"; cancelled="+cancelled+"; isDone=true; null internal future";
+ throw new CancellationException();
+ } else if (remaining == null) {
+ return internalFuture.get();
+ } else {
+ return internalFuture.get(Math.max(remaining, 1000), TimeUnit.MILLISECONDS);
+ }
} else if (remaining == null) {
return internalFuture.get();
} else if (remaining > 0) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3df2b8b4/core/src/test/java/org/apache/brooklyn/core/effector/EffectorBasicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/EffectorBasicTest.java b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorBasicTest.java
index 05b3a10..8af533f 100644
--- a/core/src/test/java/org/apache/brooklyn/core/effector/EffectorBasicTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorBasicTest.java
@@ -18,6 +18,8 @@
*/
package org.apache.brooklyn.core.effector;
+import static org.testng.Assert.assertEquals;
+
import java.util.List;
import java.util.concurrent.Callable;
@@ -25,6 +27,7 @@ import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.mgmt.HasTaskChildren;
import org.apache.brooklyn.api.mgmt.Task;
import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.StartableApplication;
import org.apache.brooklyn.core.entity.trait.FailingEntity;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.location.SimulatedLocation;
@@ -36,11 +39,13 @@ import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.time.Duration;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
public class EffectorBasicTest extends BrooklynAppUnitTestSupport {
@@ -92,6 +97,30 @@ public class EffectorBasicTest extends BrooklynAppUnitTestSupport {
Assert.assertTrue(starting.getTags().contains(ManagementContextInternal.EFFECTOR_TAG));
}
+ @Test
+ public void testInvokeEffectorListWithEmpty() throws Exception{
+ Entities.invokeEffectorList(app, ImmutableList.<StartableApplication>of(), Startable.STOP).get(Duration.THIRTY_SECONDS);
+ }
+
+ @Test
+ public void testInvokeEffectorList() throws Exception{
+ List<TestEntity> entities = Lists.newArrayList();
+ for (int i = 0; i < 10; i++) {
+ entities.add(app.addChild(EntitySpec.create(TestEntity.class)));
+ }
+ Entities.invokeEffectorList(app, entities, Startable.STOP).get(Duration.THIRTY_SECONDS);
+ for (TestEntity entity : entities) {
+ assertEquals(entity.getCallHistory(), ImmutableList.of("stop"));
+ }
+ }
+
+ @Test(expectedExceptions=IllegalStateException.class, expectedExceptionsMessageRegExp=".*no longer managed.*")
+ public void testInvokeEffectorListWithEmptyUsingUnmanagedContext() throws Exception{
+ TestEntity entity = app.addChild(EntitySpec.create(TestEntity.class));
+ Entities.unmanage(entity);
+ Entities.invokeEffectorList(entity, ImmutableList.<StartableApplication>of(), Startable.STOP).get(Duration.THIRTY_SECONDS);
+ }
+
// check various failure situations
private FailingEntity createFailingEntity() {
[10/10] brooklyn-server git commit: This closes #59
Posted by gr...@apache.org.
This closes #59
* github/pr/59:
Clocker-testing: fix where we delete the location
Fix XML serialiser for SpecConverter
LocationFactor’s “special constructor” for pre-existing loc
Fix log.warn when calling Location.unmanage
BROOKLYN-242: fix race in BasicTest.get()
NotUpDiagnostics: don’t collect if starting && !up
ServerPool: creates/registers single ServerPoolLocation
Clocker pattern: change how LocationRegistry used
Test the Clocker pattern (of LocationOwner and DynamicLocation)
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b8211ed1
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b8211ed1
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b8211ed1
Branch: refs/heads/master
Commit: b8211ed17c354dba49ad33d7bf6ee5db675ff6a9
Parents: 1e5f3b6 b59fda7
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Mar 22 17:17:25 2016 +0000
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Tue Mar 22 17:17:25 2016 +0000
----------------------------------------------------------------------
.../core/location/AbstractLocation.java | 4 +-
.../core/location/dynamic/DynamicLocation.java | 12 +
.../core/location/dynamic/LocationOwner.java | 4 -
.../core/mgmt/persist/XmlMementoSerializer.java | 14 +-
.../objs/proxy/InternalLocationFactory.java | 13 ++
.../brooklyn/util/core/task/BasicTask.java | 11 +-
.../core/effector/EffectorBasicTest.java | 29 +++
.../entity/machine/pool/ServerPool.java | 5 +-
.../entity/machine/pool/ServerPoolImpl.java | 53 +++--
.../entity/machine/pool/ServerPoolLocation.java | 53 ++++-
.../pool/ServerPoolLocationResolver.java | 64 +++---
...ClockerDynamicLocationPatternRebindTest.java | 136 +++++++++++
.../ClockerDynamicLocationPatternTest.java | 110 +++++++++
.../dynamic/clocker/StubAttributes.java | 34 +++
.../location/dynamic/clocker/StubContainer.java | 33 +++
.../dynamic/clocker/StubContainerImpl.java | 131 +++++++++++
.../dynamic/clocker/StubContainerLocation.java | 52 +++++
.../core/location/dynamic/clocker/StubHost.java | 38 ++++
.../location/dynamic/clocker/StubHostImpl.java | 141 ++++++++++++
.../dynamic/clocker/StubHostLocation.java | 171 ++++++++++++++
.../dynamic/clocker/StubInfrastructure.java | 95 ++++++++
.../dynamic/clocker/StubInfrastructureImpl.java | 224 +++++++++++++++++++
.../clocker/StubInfrastructureLocation.java | 139 ++++++++++++
.../location/dynamic/clocker/StubResolver.java | 159 +++++++++++++
.../dynamic/clocker/StubResolverTest.java | 82 +++++++
.../location/dynamic/clocker/StubUtils.java | 95 ++++++++
.../machine/pool/AbstractServerPoolTest.java | 23 +-
.../pool/ServerPoolLocationResolverTest.java | 65 ++----
.../entity/machine/pool/ServerPoolTest.java | 8 +-
29 files changed, 1865 insertions(+), 133 deletions(-)
----------------------------------------------------------------------
[07/10] brooklyn-server git commit: LocationFactor’s “special constructor” for pre-existing loc
Posted by gr...@apache.org.
LocationFactor’s “special constructor” for pre-existing loc
If location already existed, then don’t try to manage it and don’t
reset its config. Previously we got a log.warn about an attempt to
manage the location when it was already managed.
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/89b3a663
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/89b3a663
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/89b3a663
Branch: refs/heads/master
Commit: 89b3a663902fb6ecdfe6666c641ce75ffca514e0
Parents: 3118f42
Author: Aled Sage <al...@gmail.com>
Authored: Tue Mar 22 12:46:02 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Mar 22 12:46:02 2016 +0000
----------------------------------------------------------------------
.../core/objs/proxy/InternalLocationFactory.java | 13 +++++++++++++
1 file changed, 13 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/89b3a663/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalLocationFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalLocationFactory.java b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalLocationFactory.java
index baf0e5b..4ba0658 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalLocationFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalLocationFactory.java
@@ -27,12 +27,15 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.location.AbstractLocation;
+import org.apache.brooklyn.core.location.Locations;
import org.apache.brooklyn.core.location.internal.LocationInternal;
import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.core.flags.FlagUtils;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
@@ -46,6 +49,8 @@ import com.google.common.collect.ImmutableMap;
*/
public class InternalLocationFactory extends InternalFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(InternalLocationFactory.class);
+
/**
* Returns true if this is a "new-style" location (i.e. where not expected to call the constructor to instantiate it).
*
@@ -96,9 +101,17 @@ public class InternalLocationFactory extends InternalFactory {
T loc = construct(clazz, spec, null);
+ if (Locations.isManaged(loc)) {
+ // Construct can return an existing instance, if using SpecialBrooklynObjectConstructor.Config.SPECIAL_CONSTRUCTOR.
+ // In which case, don't reconfigure it (don't change its parent, etc).
+ LOG.debug("Location-factory returning pre-existing location; skipping initialization of {}", loc);
+ return loc;
+ }
+
if (spec.getId() != null) {
FlagUtils.setFieldsFromFlags(ImmutableMap.of("id", spec.getId()), loc);
}
+
managementContext.prePreManage(loc);
if (spec.getDisplayName()!=null)
[04/10] brooklyn-server git commit: NotUpDiagnostics: don’t collect if starting && !up
Posted by gr...@apache.org.
NotUpDiagnostics: don’t collect if starting && !up
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/0b9682b8
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/0b9682b8
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/0b9682b8
Branch: refs/heads/master
Commit: 0b9682b8830df7715bb8b579cfc40a1734f03038
Parents: 9f1a120
Author: Aled Sage <al...@gmail.com>
Authored: Fri Mar 18 23:09:04 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Sat Mar 19 22:03:56 2016 +0000
----------------------------------------------------------------------
.../apache/brooklyn/entity/software/base/SoftwareProcessImpl.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0b9682b8/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
index ace4ebe..4bf6543 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
@@ -172,7 +172,7 @@ public abstract class SoftwareProcessImpl extends AbstractEntity implements Soft
Lifecycle state = entity.getAttribute(SERVICE_STATE_ACTUAL);
if (up == null || up) {
entity.sensors().set(ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, ImmutableMap.<String, Object>of());
- } else if (state == null || state == Lifecycle.CREATED) {
+ } else if (state == null || state == Lifecycle.CREATED || state == Lifecycle.STARTING) {
// not yet started; do nothing
} else if (state == Lifecycle.STOPPING || state == Lifecycle.STOPPED || state == Lifecycle.DESTROYED) {
// stopping/stopped, so expect not to be up; get rid of the diagnostics.