Adds loadBalancer.changeServerPool
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
index 34c324e..bd5bc15 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
@@ -33,6 +33,7 @@
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.annotation.EffectorParam;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
@@ -148,9 +149,25 @@
protected void removeServerPoolMemberTrackingPolicy() {
if (serverPoolMemberTrackerPolicy != null) {
policies().remove(serverPoolMemberTrackerPolicy);
+ serverPoolMemberTrackerPolicy = null;
}
}
+ protected boolean hasServerPoolMemberTrackingPolicy() {
+ if (serverPoolMemberTrackerPolicy != null) return true;
+
+ // On rebind, might not have set the field yet
+ for (Policy p: policies()) {
+ if (p instanceof ServerPoolMemberTrackerPolicy) {
+ LOG.info(this+" picking up "+p+" as the tracker (already set, often due to rebind)");
+ serverPoolMemberTrackerPolicy = (ServerPoolMemberTrackerPolicy) p;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public static class ServerPoolMemberTrackerPolicy extends AbstractMembershipTrackingPolicy {
@Override
protected void onEntityEvent(EventType type, Entity entity) {
@@ -411,8 +428,9 @@
public Task<?> updateAsync() {
synchronized (serverPoolAddresses) {
Task<?> result = null;
- if (!isActive()) updateNeeded = true;
- else {
+ if (!isActive()) {
+ updateNeeded = true;
+ } else {
updateNeeded = false;
LOG.debug("Updating {} in response to changes", this);
LOG.info("Updating {}, server pool targets {}", new Object[] {this, getAttribute(SERVER_POOL_TARGETS)});
@@ -425,6 +443,20 @@
}
}
+ @Override
+ public void changeServerPool(String groupId) {
+ Group newGroup = (Group) getManagementContext().getEntityManager().getEntity(groupId);
+ if (newGroup == null) {
+ throw new IllegalArgumentException("Group '"+groupId+"' not found");
+ }
+
+ config().set(SERVER_POOL, newGroup);
+ if (hasServerPoolMemberTrackingPolicy()) {
+ addServerPoolMemberTrackingPolicy();
+ }
+ updateNeeded();
+ }
+
protected void onServerPoolMemberChanged(Entity member) {
synchronized (serverPoolAddresses) {
if (LOG.isTraceEnabled()) LOG.trace("For {}, considering membership of {} which is in locations {}",
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
index 15cd94d..24d57fa 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractNonProvisionedControllerImpl.java
@@ -39,6 +39,7 @@
import org.apache.brooklyn.core.feed.ConfigToAttributes;
import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import org.apache.brooklyn.entity.proxy.AbstractControllerImpl.MapAttribute;
+import org.apache.brooklyn.entity.proxy.AbstractControllerImpl.ServerPoolMemberTrackerPolicy;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.slf4j.Logger;
@@ -215,9 +216,25 @@
protected void removeServerPoolMemberTrackingPolicy() {
if (serverPoolMemberTrackerPolicy != null) {
policies().remove(serverPoolMemberTrackerPolicy);
+ serverPoolMemberTrackerPolicy = null;
}
}
+ protected boolean hasServerPoolMemberTrackingPolicy() {
+ if (serverPoolMemberTrackerPolicy != null) return true;
+
+ // On rebind, might not have set the field yet
+ for (Policy p: policies()) {
+ if (p instanceof ServerPoolMemberTrackerPolicy) {
+ LOG.info(this+" picking up "+p+" as the tracker (already set, often due to rebind)");
+ serverPoolMemberTrackerPolicy = (ServerPoolMemberTrackerPolicy) p;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public static class ServerPoolMemberTrackerPolicy extends AbstractMembershipTrackingPolicy {
@Override
protected void onEntityEvent(EventType type, Entity entity) {
@@ -263,8 +280,9 @@
public Task<?> updateAsync() {
synchronized (mutex) {
Task<?> result = null;
- if (!isActive()) updateNeeded = true;
- else {
+ if (!isActive()) {
+ updateNeeded = true;
+ } else {
updateNeeded = false;
LOG.debug("Updating {} in response to changes", this);
LOG.info("Updating {}, server pool targets {}", new Object[] {this, getAttribute(SERVER_POOL_TARGETS)});
@@ -276,6 +294,20 @@
}
}
+ @Override
+ public void changeServerPool(String groupId) {
+ Group newGroup = (Group) getManagementContext().getEntityManager().getEntity(groupId);
+ if (newGroup == null) {
+ throw new IllegalArgumentException("Group '"+groupId+"' not found");
+ }
+
+ config().set(SERVER_POOL, newGroup);
+ if (hasServerPoolMemberTrackingPolicy()) {
+ addServerPoolMemberTrackingPolicy();
+ }
+ updateNeeded();
+ }
+
protected void onServerPoolMemberChanged(Entity member) {
synchronized (mutex) {
if (LOG.isTraceEnabled()) LOG.trace("For {}, considering membership of {} which is in locations {}",
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
index 6ff9cb4..689f22b 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
@@ -27,6 +27,7 @@
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.annotation.Effector;
+import org.apache.brooklyn.core.annotation.EffectorParam;
import org.apache.brooklyn.core.config.BasicConfigKey;
import org.apache.brooklyn.core.effector.MethodEffector;
import org.apache.brooklyn.core.entity.Attributes;
@@ -132,6 +133,10 @@
public static final MethodEffector<Void> UPDATE = new MethodEffector<Void>(LoadBalancer.class, "update");
+ @Effector(description="Change the target server pool")
+ public void changeServerPool(
+ @EffectorParam(name="groupId") String groupId);
+
@Effector(description="Forces reload of the configuration")
public void reload();
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancerClusterImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
index ff23089..863b7ed 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancerClusterImpl.java
@@ -21,6 +21,7 @@
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.entity.group.DynamicClusterImpl;
/**
@@ -73,4 +74,18 @@
}
}
}
+
+ @Override
+ public void changeServerPool(String groupId) {
+ Group newGroup = (Group) getManagementContext().getEntityManager().getEntity(groupId);
+ if (newGroup == null) {
+ throw new IllegalArgumentException("Group '"+groupId+"' not found");
+ }
+
+ for (Entity member : getMembers()) {
+ if (member instanceof LoadBalancer) {
+ ((LoadBalancer)member).changeServerPool(groupId);
+ }
+ }
+ }
}
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractAbstractControllerTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractAbstractControllerTest.java
index eba82c5..a9065c5 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractAbstractControllerTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractAbstractControllerTest.java
@@ -229,6 +229,28 @@
assertEventuallyAddressesMatch(ImmutableList.<Entity>of());
}
+ @Test
+ public void testUpdateCalledWhenServerPoolGroupSwapped() {
+ // Second cluster with one child
+ DynamicCluster cluster2 = app.addChild(EntitySpec.create(DynamicCluster.class)
+ .configure("initialSize", 1)
+ .configure("memberSpec", EntitySpec.create(TestEntity.class).impl(WebServerEntity.class)));
+ cluster2.start(ImmutableList.of());
+
+ Entity child = Iterables.getOnlyElement(cluster2.getMembers());
+ child.sensors().set(WebServerEntity.HTTP_PORT, 1234);
+ child.sensors().set(Startable.SERVICE_UP, true);
+
+ // Reconfigure the controller to point at the new cluster
+ controller.changeServerPool(cluster2.getId());
+ assertEquals(controller.config().get(LoadBalancer.SERVER_POOL), cluster2);
+ assertEventuallyAddressesMatchCluster(cluster2);
+
+ // And remove all children; expect all addresses to go away
+ cluster2.resize(0);
+ assertEventuallyAddressesMatchCluster(cluster2);
+ }
+
protected void assertEventuallyAddressesMatchCluster() {
assertEventuallyAddressesMatchCluster(cluster);
}