This closes #147
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);
     }