From e983f0696918382c70ac6f0932b2363f96188d4a Mon Sep 17 00:00:00 2001 From: Winson Chan Date: Fri, 17 May 2013 11:30:33 -0700 Subject: [PATCH] UpdateStack for AWS::AutoScaling::ScalingPolicy Implemented update support of the ScalingPolicy resource in an existing stack. ScalingAdjustment, AdjustmentType, and Cooldown properties are allowed properties for update. A handle_update method is added to update differences in the template. Change-Id: Ieeae93560a315a8a35c6fb2d8f1d78a89123bec3 blueprint: scalingpolicy-update-stack --- heat/engine/resources/autoscaling.py | 27 +++++++++++ heat/tests/test_autoscaling.py | 71 +++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/heat/engine/resources/autoscaling.py b/heat/engine/resources/autoscaling.py index 81a0f027b3..3f14014175 100644 --- a/heat/engine/resources/autoscaling.py +++ b/heat/engine/resources/autoscaling.py @@ -426,9 +426,36 @@ class ScalingPolicy(resource.Resource, CooldownMixin): 'Cooldown': {'Type': 'Number'}, } + update_allowed_keys = ('Properties',) + update_allowed_properties = ('ScalingAdjustment', 'AdjustmentType', + 'Cooldown',) + def __init__(self, name, json_snippet, stack): super(ScalingPolicy, self).__init__(name, json_snippet, stack) + def handle_update(self, json_snippet): + try: + tmpl_diff = self.update_template_diff(json_snippet) + except NotImplementedError: + logger.error("Could not update %s, invalid key" % self.name) + return self.UPDATE_REPLACE + + try: + prop_diff = self.update_template_diff_properties(json_snippet) + except NotImplementedError: + logger.error("Could not update %s, invalid Property" % self.name) + return self.UPDATE_REPLACE + + # If Properties has changed, update self.properties, so we + # get the new values during any subsequent adjustment + if prop_diff: + self.properties = Properties(self.properties_schema, + json_snippet.get('Properties', {}), + self.stack.resolve_runtime_data, + self.name) + + return self.UPDATE_COMPLETE + def alarm(self): if self._cooldown_inprogress(): logger.info("%s NOT performing scaling action, cooldown %s" % diff --git a/heat/tests/test_autoscaling.py b/heat/tests/test_autoscaling.py index dc6578cc60..f556ebcf7d 100644 --- a/heat/tests/test_autoscaling.py +++ b/heat/tests/test_autoscaling.py @@ -41,7 +41,7 @@ as_template = ''' "AvailabilityZones" : ["nova"], "LaunchConfigurationName" : { "Ref" : "LaunchConfig" }, "MinSize" : "1", - "MaxSize" : "3", + "MaxSize" : "5", "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ] } }, @@ -354,7 +354,7 @@ class AutoScalingTest(HeatTestCase): resource.resource_id) # raise above the max - resource.adjust(2) + resource.adjust(4) self.assertEqual('WebServerGroup-0,WebServerGroup-1', resource.resource_id) @@ -825,3 +825,70 @@ class AutoScalingTest(HeatTestCase): resource.delete() self.m.VerifyAll() + + def test_scaling_policy_update(self): + t = template_format.parse(as_template) + stack = parse_stack(t) + + # Create initial group + self._stub_lb_reload(['WebServerGroup-0']) + now = timeutils.utcnow() + self._stub_meta_expected(now, 'ExactCapacity : 1') + self._stub_create(1) + self.m.ReplayAll() + resource = self.create_scaling_group(t, stack, 'WebServerGroup') + stack.resources['WebServerGroup'] = resource + self.assertEqual('WebServerGroup-0', resource.resource_id) + + # Create initial scaling policy + up_policy = self.create_scaling_policy(t, stack, + 'WebServerScaleUpPolicy') + + # Scale up one + self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1']) + self._stub_meta_expected(now, 'ChangeInCapacity : 1', 2) + self._stub_create(1) + self.m.ReplayAll() + + # Trigger alarm + up_policy.alarm() + self.assertEqual('WebServerGroup-0,WebServerGroup-1', + resource.resource_id) + + # Update scaling policy + update_snippet = copy.deepcopy(up_policy.parsed_template()) + update_snippet['Properties']['ScalingAdjustment'] = '2' + self.assertEqual(asc.ScalingPolicy.UPDATE_COMPLETE, + up_policy.handle_update(update_snippet)) + self.assertEqual('2', + up_policy.properties['ScalingAdjustment']) + + # Now move time on 61 seconds - Cooldown in template is 60 + # so this should trigger a scale-up + previous_meta = {timeutils.strtime(now): 'ChangeInCapacity : 1'} + self.m.VerifyAll() + self.m.UnsetStubs() + + self.m.StubOutWithMock(Metadata, '__get__') + Metadata.__get__(mox.IgnoreArg(), up_policy, mox.IgnoreArg() + ).AndReturn(previous_meta) + Metadata.__get__(mox.IgnoreArg(), resource, mox.IgnoreArg() + ).AndReturn(previous_meta) + + now = now + datetime.timedelta(seconds=61) + + self._stub_lb_reload(['WebServerGroup-0', 'WebServerGroup-1', + 'WebServerGroup-2', 'WebServerGroup-3'], + unset=False) + self._stub_meta_expected(now, 'ChangeInCapacity : 2', 2) + self._stub_create(2) + self.m.ReplayAll() + + # Trigger alarm + up_policy.alarm() + self.assertEqual('WebServerGroup-0,WebServerGroup-1,' + 'WebServerGroup-2,WebServerGroup-3', + resource.resource_id) + + resource.delete() + self.m.VerifyAll()