Merge "Native ScalingPolicy resource"

This commit is contained in:
Jenkins 2014-03-05 18:58:36 +00:00 committed by Gerrit Code Review
commit 2478007285
2 changed files with 151 additions and 2 deletions

View File

@ -888,6 +888,9 @@ class ScalingPolicy(signal_responder.SignalResponder, CooldownMixin):
'Cooldown',
)
EXACT_CAPACITY, CHANGE_IN_CAPACITY, PERCENT_CHANGE_IN_CAPACITY = (
'ExactCapacity', 'ChangeInCapacity', 'PercentChangeInCapacity')
properties_schema = {
AUTO_SCALING_GROUP_NAME: properties.Schema(
properties.Schema.STRING,
@ -941,6 +944,9 @@ class ScalingPolicy(signal_responder.SignalResponder, CooldownMixin):
self.name,
self.context)
def _get_adjustement_type(self):
return self.properties[self.ADJUSTMENT_TYPE]
def handle_signal(self, details=None):
# ceilometer sends details like this:
# {u'alarm_id': ID, u'previous': u'ok', u'current': u'alarm',
@ -981,8 +987,8 @@ class ScalingPolicy(signal_responder.SignalResponder, CooldownMixin):
'name': self.name, 'group': group.name,
'asgn_id': asgn_id,
'filter': self.properties[self.SCALING_ADJUSTMENT]})
group.adjust(self.properties[self.SCALING_ADJUSTMENT],
self.properties[self.ADJUSTMENT_TYPE])
adjustment_type = self._get_adjustement_type()
group.adjust(self.properties[self.SCALING_ADJUSTMENT], adjustment_type)
self._cooldown_timestamp("%s : %s" %
(self.properties[self.ADJUSTMENT_TYPE],
@ -1003,6 +1009,72 @@ class ScalingPolicy(signal_responder.SignalResponder, CooldownMixin):
return unicode(self.name)
class AutoScalingPolicy(ScalingPolicy):
"""A resource to manage scaling of `OS::Heat::AutoScalingGroup`.
**Note** while it may incidentally support
`AWS::AutoScaling::AutoScalingGroup` for now, please don't use it for that
purpose and use `AWS::AutoScaling::ScalingPolicy` instead.
"""
PROPERTIES = (
AUTO_SCALING_GROUP_NAME, SCALING_ADJUSTMENT, ADJUSTMENT_TYPE,
COOLDOWN,
) = (
'auto_scaling_group_id', 'scaling_adjustment', 'adjustment_type',
'cooldown',
)
EXACT_CAPACITY, CHANGE_IN_CAPACITY, PERCENT_CHANGE_IN_CAPACITY = (
'exact_capacity', 'change_in_capacity', 'percent_change_in_capacity')
properties_schema = {
AUTO_SCALING_GROUP_NAME: properties.Schema(
properties.Schema.STRING,
_('AutoScaling group ID to apply policy to.'),
required=True
),
SCALING_ADJUSTMENT: properties.Schema(
properties.Schema.NUMBER,
_('Size of adjustment.'),
required=True,
update_allowed=True
),
ADJUSTMENT_TYPE: properties.Schema(
properties.Schema.STRING,
_('Type of adjustment (absolute or percentage).'),
required=True,
constraints=[
constraints.AllowedValues([CHANGE_IN_CAPACITY,
EXACT_CAPACITY,
PERCENT_CHANGE_IN_CAPACITY]),
],
update_allowed=True
),
COOLDOWN: properties.Schema(
properties.Schema.NUMBER,
_('Cooldown period, in seconds.'),
update_allowed=True
),
}
update_allowed_keys = ('Properties',)
attributes_schema = {
"alarm_url": _("A signed url to handle the alarm.")
}
def _get_adjustement_type(self):
adjustment_type = self.properties[self.ADJUSTMENT_TYPE]
return ''.join([t.capitalize() for t in adjustment_type.split('_')])
def _resolve_attribute(self, name):
if name == 'alarm_url' and self.resource_id is not None:
return unicode(self._get_signed_url())
def FnGetRefId(self):
return resource.Resource.FnGetRefId(self)
def resource_mapping():
return {
'AWS::AutoScaling::LaunchConfiguration': LaunchConfiguration,
@ -1010,4 +1082,5 @@ def resource_mapping():
'AWS::AutoScaling::ScalingPolicy': ScalingPolicy,
'OS::Heat::InstanceGroup': InstanceGroup,
'OS::Heat::AutoScalingGroup': AutoScalingResourceGroup,
'OS::Heat::ScalingPolicy': AutoScalingPolicy,
}

View File

@ -11,6 +11,7 @@
# under the License.
import copy
import datetime
from oslo.config import cfg
@ -21,6 +22,8 @@ from heat.engine import clients
from heat.engine import resource
from heat.engine import scheduler
from heat.openstack.common import timeutils
from heat.tests import fakes
from heat.tests import utils
from heat.tests import generic_resource
@ -298,3 +301,76 @@ class HeatScalingGroupWithCFNScalingPolicyTest(HeatTestCase):
self.assertEqual(1, len(group.get_instances()))
scale_up.signal()
self.assertEqual(2, len(group.get_instances()))
class ScalingPolicyTest(HeatTestCase):
as_template = '''
heat_template_version: 2013-05-23
resources:
my-policy:
type: OS::Heat::ScalingPolicy
properties:
auto_scaling_group_id: {get_resource: my-group}
adjustment_type: change_in_capacity
scaling_adjustment: 1
my-group:
type: OS::Heat::AutoScalingGroup
properties:
max_size: 5
min_size: 1
resource:
type: ResourceWithProps
properties:
Foo: hello
'''
def setUp(self):
super(ScalingPolicyTest, self).setUp()
utils.setup_dummy_db()
resource._register_class('ResourceWithProps',
generic_resource.ResourceWithProps)
self.fc = fakes.FakeKeystoneClient()
client = self.patchobject(clients.OpenStackClients, "keystone")
client.return_value = self.fc
self.parsed = template_format.parse(self.as_template)
def test_alarm_attribute(self):
stack = utils.parse_stack(self.parsed)
stack.create()
policy = stack['my-policy']
self.assertIn("my-policy", policy.FnGetAtt('alarm_url'))
def test_signal(self):
stack = utils.parse_stack(self.parsed)
stack.create()
self.assertEqual((stack.CREATE, stack.COMPLETE), stack.state)
policy = stack['my-policy']
group = stack['my-group']
self.assertEqual("1234", policy.FnGetRefId())
self.assertEqual(1, len(group.get_instance_names()))
policy.signal()
self.assertEqual(2, len(group.get_instance_names()))
def test_signal_with_cooldown(self):
self.parsed['resources']['my-policy']['properties']['cooldown'] = 60
stack = utils.parse_stack(self.parsed)
stack.create()
policy = stack['my-policy']
group = stack['my-group']
self.assertEqual(1, len(group.get_instance_names()))
policy.signal()
self.assertEqual(2, len(group.get_instance_names()))
policy.signal()
# The second signal shouldn't have changed it because of cooldown
self.assertEqual(2, len(group.get_instance_names()))
past = timeutils.strtime(timeutils.utcnow() -
datetime.timedelta(seconds=65))
policy.metadata = {past: 'ChangeInCapacity : 1'}
policy.signal()
self.assertEqual(3, len(group.get_instance_names()))