Skip to content

Commit

Permalink
Merge pull request #305 from aledsage/fix/disable-auto-resize-down
Browse files Browse the repository at this point in the history
Issue #288: Disable auto-scale down of docker-host-cluster
  • Loading branch information
grkvlt committed May 6, 2016
2 parents 5a2b4c3 + 68d38e4 commit 7ed96f8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ public class ContainerHeadroomEnricher extends AbstractEnricher {
public static final ConfigKey<Double> CONTAINER_HEADROOM_PERCENTAGE = ConfigKeys.newDoubleConfigKey(
"docker.container.cluster.headroom.percent", "Required headroom (percentage free containers) for the Docker cluster");

public static final ConfigKey<Boolean> CLUSTER_TOO_COLD_ENABLED = ConfigKeys.newBooleanConfigKey(
"docker.container.cluster.cold.enabled",
"Whether to emit too-cold events (which can trigger auto-scaling down)",
false);

public static final AttributeSensor<Integer> CONTAINERS_NEEDED = Sensors.newIntegerSensor(
"docker.container.cluster.needed", "Number of containers needed to give requierd headroom");
public static final AttributeSensor<Double> DOCKER_CONTAINER_UTILISATION = Sensors.newDoubleSensor(
Expand Down Expand Up @@ -130,6 +135,7 @@ private void recalculate() {
if (maxContainers == null) {
maxContainers = MaxContainersPlacementStrategy.DEFAULT_MAX_CONTAINERS;
}
boolean tooColdEnabled = Boolean.TRUE.equals(config().get(CLUSTER_TOO_COLD_ENABLED));

// Calculate cluster state
Integer containers = entity.sensors().get(DockerInfrastructure.DOCKER_CONTAINER_COUNT);
Expand Down Expand Up @@ -172,7 +178,7 @@ private void recalculate() {
if (needed > 0) {
lastPublished = DOCKER_CONTAINER_CLUSTER_HOT;
emit(DOCKER_CONTAINER_CLUSTER_HOT, properties);
} else if (available > (headroom + maxContainers)) {
} else if (tooColdEnabled && available > (headroom + maxContainers)) {
lastPublished = DOCKER_CONTAINER_CLUSTER_COLD;
emit(DOCKER_CONTAINER_CLUSTER_COLD, properties);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@
import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.api.sensor.SensorEvent;
import org.apache.brooklyn.api.sensor.SensorEventListener;
import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.sensor.BasicNotificationSensor;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.group.DynamicGroup;
import org.apache.brooklyn.entity.stock.BasicStartableImpl;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;

Expand All @@ -66,14 +66,14 @@ public void setUp() throws Exception {
.configure(MaxContainersPlacementStrategy.DOCKER_CONTAINER_CLUSTER_MAX_SIZE, 8));

listener = new RecordingSensorEventListener();
app.subscribe(entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_CLUSTER_HOT, listener);
app.subscribe(entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_CLUSTER_COLD, listener);
app.subscribe(entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_CLUSTER_OK, listener);
app.subscriptions().subscribe(entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_CLUSTER_HOT, listener);
app.subscriptions().subscribe(entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_CLUSTER_COLD, listener);
app.subscriptions().subscribe(entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_CLUSTER_OK, listener);
}

@Test
public void testNoEventsWhenAllOk() throws Exception {
entity.addEnricher(EnricherSpec.create(ContainerHeadroomEnricher.class)
entity.enrichers().add(EnricherSpec.create(ContainerHeadroomEnricher.class)
.configure(ContainerHeadroomEnricher.CONTAINER_HEADROOM, 4));

entity.sensors().set(DockerInfrastructure.DOCKER_HOST_COUNT, 2);
Expand All @@ -87,7 +87,7 @@ public void testNoEventsWhenAllOk() throws Exception {
// second later then our subsequent assertion will fail.
@Test(groups="integration")
public void testTooHotWhenHeadroomExceeded() throws Exception {
entity.addEnricher(EnricherSpec.create(ContainerHeadroomEnricher.class)
entity.enrichers().add(EnricherSpec.create(ContainerHeadroomEnricher.class)
.configure(ContainerHeadroomEnricher.CONTAINER_HEADROOM, 4));

// Too hot: headroom insufficient by one container
Expand Down Expand Up @@ -138,8 +138,9 @@ public void testTooHotWhenHeadroomExceeded() throws Exception {
// See comment on testTooHotThenOk.
@Test(groups="integration")
public void testTooColdThenOk() throws Exception {
entity.addEnricher(EnricherSpec.create(ContainerHeadroomEnricher.class)
.configure(ContainerHeadroomEnricher.CONTAINER_HEADROOM, 4));
entity.enrichers().add(EnricherSpec.create(ContainerHeadroomEnricher.class)
.configure(ContainerHeadroomEnricher.CONTAINER_HEADROOM, 4)
.configure(ContainerHeadroomEnricher.CLUSTER_TOO_COLD_ENABLED, true));

// Too cold - only need one host rather than 10
entity.sensors().set(DockerInfrastructure.DOCKER_HOST_COUNT, 10);
Expand All @@ -152,7 +153,7 @@ public void testTooColdThenOk() throws Exception {
.lowThreshold((80d - (4 + 8)) / 80)
.highThreshold(76d/80));

// Too hot - only need one host rather than 2
// Too cold - only need one host rather than 2
listener.clearEventsContinually();
entity.sensors().set(DockerInfrastructure.DOCKER_HOST_COUNT, 2);

Expand Down Expand Up @@ -181,6 +182,25 @@ public void testTooColdThenOk() throws Exception {
assertNoEventsContinually();
}

// Integration because takes over a second, and because time-sensitive:
// See comment on testTooHotThenOk.
@Test(groups="integration")
public void testTooColdNotPublishedByDefault() throws Exception {
entity.enrichers().add(EnricherSpec.create(ContainerHeadroomEnricher.class)
.configure(ContainerHeadroomEnricher.CONTAINER_HEADROOM, 4));

// Too cold - only need one host rather than 10.
// Same state as in testTooColdThenOk, so know that it really is "too cold".
entity.sensors().set(DockerInfrastructure.DOCKER_HOST_COUNT, 10);
entity.sensors().set(DockerInfrastructure.DOCKER_CONTAINER_COUNT, 1);

// Make everything ok again; do not expect an "ok"
entity.sensors().set(DockerInfrastructure.DOCKER_HOST_COUNT, 2);
entity.sensors().set(DockerInfrastructure.DOCKER_CONTAINER_COUNT, 8);

assertNoEventsContinually();
}

private void assertNoEventsContinually() {
Asserts.succeedsContinually(new Runnable() {
public void run() {
Expand All @@ -201,8 +221,8 @@ private void assertOk(final CurrentStatus status) {
}

private void assertTemperatureEvent(final CurrentStatus status, final BasicNotificationSensor<Map> eventType) {
EntityTestUtils.assertAttributeEqualsEventually(assertMap, entity, ContainerHeadroomEnricher.CONTAINERS_NEEDED, status.needed);
EntityTestUtils.assertAttributeEqualsEventually(assertMap, entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_UTILISATION, status.utilization);
EntityAsserts.assertAttributeEqualsEventually(assertMap, entity, ContainerHeadroomEnricher.CONTAINERS_NEEDED, status.needed);
EntityAsserts.assertAttributeEqualsEventually(assertMap, entity, ContainerHeadroomEnricher.DOCKER_CONTAINER_UTILISATION, status.utilization);

Asserts.succeedsEventually(assertMap, new Runnable() {
public void run() {
Expand Down

0 comments on commit 7ed96f8

Please sign in to comment.