brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From drigod...@apache.org
Subject [1/2] brooklyn-server git commit: AutoScalerPolicy to resize to limits on expunge
Date Wed, 23 Aug 2017 11:26:51 GMT
Repository: brooklyn-server
Updated Branches:
  refs/heads/master 86070d8a1 -> acb5a68c3


AutoScalerPolicy to resize to limits on expunge


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/00318ef3
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/00318ef3
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/00318ef3

Branch: refs/heads/master
Commit: 00318ef30bac60f0f3d0147f868918999b1b1833
Parents: d961de3
Author: Martin Harris <martin@cloudsoft.io>
Authored: Thu Aug 17 14:52:10 2017 +0100
Committer: Martin Harris <github@nakomis.com>
Committed: Wed Aug 23 10:36:34 2017 +0100

----------------------------------------------------------------------
 .../test/entity/TestSizeRecordingCluster.java   |  39 +++++++
 .../entity/TestSizeRecordingClusterImpl.java    |  59 ++++++++++
 .../policy/autoscaling/AutoScalerPolicy.java    |  21 ++++
 .../AutoScalerPolicyPoolSizeTest.java           | 110 +++++++++++++++++++
 4 files changed, 229 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/00318ef3/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingCluster.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingCluster.java
b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingCluster.java
new file mode 100644
index 0000000..107e65d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingCluster.java
@@ -0,0 +1,39 @@
+/*
+ * 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.test.entity;
+
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+
+import java.util.List;
+
+/**
+ * Similar to {@link TestCluster}, however the intercepts are simply used to record the resize,
and not
+ * mock them, instead delegating to {@link DynamicCluster}
+ */
+@ImplementedBy(TestSizeRecordingClusterImpl.class)
+public interface TestSizeRecordingCluster extends DynamicCluster {
+
+    AttributeSensor<Integer> SIZE_HISTORY_RECORD_COUNT = Sensors.newIntegerSensor("size.history.count",
"Number of entries in the size history record");
+
+    List<Integer> getSizeHistory();
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/00318ef3/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingClusterImpl.java
b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingClusterImpl.java
new file mode 100644
index 0000000..5a59c77
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestSizeRecordingClusterImpl.java
@@ -0,0 +1,59 @@
+/*
+ * 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.test.entity;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.brooklyn.entity.group.DynamicClusterImpl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class TestSizeRecordingClusterImpl extends DynamicClusterImpl implements TestSizeRecordingCluster
{
+
+    public TestSizeRecordingClusterImpl () {
+    }
+
+    private final List<Integer> sizeHistory = Collections.synchronizedList(new ArrayList<Integer>());
+
+    @Override
+    public Integer resize(Integer desiredSize) {
+        int existingSize = getCurrentSize();
+        int newSize = super.resize(desiredSize);
+        if (newSize != existingSize) {
+            addSizeHistory(newSize);
+        }
+        return newSize;
+    }
+
+    @Override
+    public List<Integer> getSizeHistory() {
+        synchronized (sizeHistory) {
+            return ImmutableList.copyOf(sizeHistory);
+        }
+    }
+
+    private void addSizeHistory(int newSize) {
+        synchronized (sizeHistory) {
+            sizeHistory.add(newSize);
+            sensors().set(SIZE_HISTORY_RECORD_COUNT, sizeHistory.size());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/00318ef3/policy/src/main/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicy.java
b/policy/src/main/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicy.java
index a3760da..a09c39d 100644
--- a/policy/src/main/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicy.java
+++ b/policy/src/main/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicy.java
@@ -45,6 +45,7 @@ import org.apache.brooklyn.core.entity.trait.Startable;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.policy.AbstractPolicy;
 import org.apache.brooklyn.core.sensor.BasicNotificationSensor;
+import org.apache.brooklyn.entity.group.DynamicCluster;
 import org.apache.brooklyn.policy.autoscaling.SizeHistory.WindowSummary;
 import org.apache.brooklyn.policy.loadbalancing.LoadBalancingPolicy;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -458,6 +459,25 @@ public class AutoScalerPolicy extends AbstractPolicy {
         }
     };
 
+    /**
+     * This should usually be a no-op as the min and max pool sizes are taken into account
when
+     * an automatic resize event occurs, however this covers the special case where the user
+     * has manually resized the pool
+     */
+    private SensorEventListener<? super Integer> poolEventHandler = new SensorEventListener<Integer>()
{
+        @Override
+        public void onEvent(SensorEvent<Integer> event) {
+            Sensor<Integer> sensor = event.getSensor();
+            Preconditions.checkArgument(sensor.equals(DynamicCluster.GROUP_SIZE), "Unexpected
sensor " + sensor);
+            Integer size = event.getValue();
+            if (size > getMaxPoolSize()) {
+                scheduleResize(getMaxPoolSize());
+            } else if (size < getMinPoolSize()) {
+                scheduleResize(getMinPoolSize());
+            }
+        }
+    };
+
     public AutoScalerPolicy() {
     }
     
@@ -687,6 +707,7 @@ public class AutoScalerPolicy extends AbstractPolicy {
         subscriptions().subscribe(poolEntity, getPoolColdSensor(), utilizationEventHandler);
         subscriptions().subscribe(poolEntity, getPoolHotSensor(), utilizationEventHandler);
         subscriptions().subscribe(poolEntity, getPoolOkSensor(), utilizationEventHandler);
+        subscriptions().subscribe(poolEntity, DynamicCluster.GROUP_SIZE, poolEventHandler);
     }
     
     private ThreadFactory newThreadFactory() {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/00318ef3/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyPoolSizeTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyPoolSizeTest.java
b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyPoolSizeTest.java
new file mode 100644
index 0000000..b03c194
--- /dev/null
+++ b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyPoolSizeTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.policy.autoscaling;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.trait.Resizable;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestCluster;
+import org.apache.brooklyn.core.test.entity.TestSizeRecordingCluster;
+import org.apache.brooklyn.entity.stock.BasicStartable;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+public class AutoScalerPolicyPoolSizeTest extends BrooklynAppUnitTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AutoScalerPolicyPoolSizeTest.class);
+
+    private static final int CLUSTER_INIITIAL_SIZE = 3;
+    private static final int CLUSTER_MIN_SIZE = 2;
+    private static final int CLUSTER_MAX_SIZE = 4;
+
+    AutoScalerPolicy policy;
+    TestSizeRecordingCluster cluster;
+    List<Integer> resizes = MutableList.of();
+
+    @BeforeMethod(alwaysRun = true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        LOG.info("resetting " + getClass().getSimpleName());
+        cluster = app.createAndManageChild(EntitySpec.create(TestSizeRecordingCluster.class)
+                .configure(TestCluster.INITIAL_SIZE, CLUSTER_INIITIAL_SIZE)
+                .configure(TestCluster.MEMBER_SPEC, EntitySpec.create(BasicStartable.class))
+        );
+        PolicySpec<AutoScalerPolicy> policySpec = PolicySpec.create(AutoScalerPolicy.class)
+                .configure(AutoScalerPolicy.RESIZE_OPERATOR, new ResizeOperator() {
+                    @Override
+                    public Integer resize(Entity entity, Integer desiredSize) {
+                        LOG.info("resizing to " + desiredSize);
+                        resizes.add(desiredSize);
+                        return ((Resizable) entity).resize(desiredSize);
+                    }
+                })
+                .configure(AutoScalerPolicy.MIN_POOL_SIZE, CLUSTER_MIN_SIZE)
+                .configure(AutoScalerPolicy.MAX_POOL_SIZE, CLUSTER_MAX_SIZE);
+        policy = cluster.policies().add(policySpec);
+        app.start(ImmutableList.of());
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws Exception {
+        try {
+            if (policy != null) policy.destroy();
+        } finally {
+            super.tearDown();
+            cluster = null;
+            policy = null;
+        }
+    }
+
+    @Test
+    public void testResizeUp() throws Exception {
+        EntityAsserts.assertAttributeEqualsEventually(cluster, TestCluster.GROUP_SIZE, CLUSTER_INIITIAL_SIZE);
+        // Simulate user expunging the entities manually
+        for (int i = 0; i < CLUSTER_MAX_SIZE - CLUSTER_MIN_SIZE; i++) {
+            Entities.destroyCatching(cluster.getMembers().iterator().next());
+        }
+        EntityAsserts.assertAttributeEqualsEventually(cluster, TestSizeRecordingCluster.SIZE_HISTORY_RECORD_COUNT,
2);
+        Assert.assertEquals((int)cluster.getSizeHistory().get(0), CLUSTER_INIITIAL_SIZE);
+        Assert.assertEquals((int)cluster.getSizeHistory().get(1), CLUSTER_MIN_SIZE);
+    }
+
+    @Test
+    public void testResizeDown() throws Exception {
+        EntityAsserts.assertAttributeEqualsEventually(cluster, TestCluster.GROUP_SIZE, CLUSTER_INIITIAL_SIZE);
+        cluster.resize(CLUSTER_MAX_SIZE + 2);
+        EntityAsserts.assertAttributeEqualsEventually(cluster, TestSizeRecordingCluster.SIZE_HISTORY_RECORD_COUNT,
3);
+        Assert.assertEquals((int)cluster.getSizeHistory().get(0), CLUSTER_INIITIAL_SIZE);
+        Assert.assertEquals((int)cluster.getSizeHistory().get(1), CLUSTER_MAX_SIZE + 2);
+        Assert.assertEquals((int)cluster.getSizeHistory().get(2), CLUSTER_MAX_SIZE);
+    }
+}


Mime
View raw message