Merge "Native ScalingPolicy resource"
This commit is contained in:
commit
2478007285
@ -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,
|
||||
}
|
||||
|
@ -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()))
|
||||
|
Loading…
Reference in New Issue
Block a user