Merge "Allow non-replacement updates of Alarms"

This commit is contained in:
Jenkins 2013-05-03 09:03:37 +00:00 committed by Gerrit Code Review
commit b1f3073f2e
2 changed files with 106 additions and 2 deletions

View File

@ -16,6 +16,7 @@
from heat.common import exception
from heat.engine import watchrule
from heat.engine import resource
from heat.engine.properties import Properties
from heat.db import api as db_api
from heat.openstack.common import log as logging
@ -73,6 +74,14 @@ class CloudWatchAlarm(resource.Resource):
'Count/Second', None]}}
strict_dependency = False
update_allowed_keys = ('Properties',)
# allow the properties that affect the watch calculation.
# note: when using in-instance monitoring you can only change the
# metric name if you re-configure the instance too.
update_allowed_properties = ('ComparisonOperator', 'AlarmDescription',
'EvaluationPeriods', 'Period', 'Statistic',
'AlarmActions', 'OKActions', 'Units'
'InsufficientDataActions', 'Threshold')
def handle_create(self):
wr = watchrule.WatchRule(context=self.context,
@ -82,7 +91,33 @@ class CloudWatchAlarm(resource.Resource):
wr.store()
def handle_update(self, json_snippet):
return self.UPDATE_REPLACE
try:
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)
loader = watchrule.WatchRule.load
wr = loader(self.context,
watch_name=self.physical_resource_name())
wr.rule = self.parsed_template('Properties')
wr.store()
return self.UPDATE_COMPLETE
def handle_delete(self):
try:

View File

@ -25,6 +25,7 @@ from heat.common import template_format
from heat.engine.resources import autoscaling as asc
from heat.engine.resources import loadbalancer
from heat.engine.resources import instance
from heat.engine.resources import cloud_watch
from heat.engine import clients
from heat.engine import parser
from heat.engine import scheduler
@ -84,6 +85,16 @@ class AutoScalingTest(HeatTestCase):
resource.state)
return resource
def create_alarm(self, t, stack, resource_name):
resource = cloud_watch.CloudWatchAlarm(resource_name,
t['Resources'][resource_name],
stack)
self.assertEqual(None, resource.validate())
scheduler.TaskRunner(resource.create)()
self.assertEqual(cloud_watch.CloudWatchAlarm.CREATE_COMPLETE,
resource.state)
return resource
def _stub_create(self, num):
self.m.StubOutWithMock(eventlet, 'sleep')
@ -266,7 +277,6 @@ class AutoScalingTest(HeatTestCase):
self.assertEqual('WebServerGroup', resource.FnGetRefId())
self.assertEqual('WebServerGroup-0', resource.resource_id)
update_snippet = copy.deepcopy(resource.parsed_template())
old_cd = update_snippet['Properties']['Cooldown']
update_snippet['Properties']['Cooldown'] = '61'
self.assertEqual(asc.AutoScalingGroup.UPDATE_COMPLETE,
resource.handle_update(update_snippet))
@ -274,6 +284,65 @@ class AutoScalingTest(HeatTestCase):
resource.delete()
self.m.VerifyAll()
def test_mem_alarm_high_update_no_replace(self):
'''
Make sure that we can change the update-able properties
without replacing the Alarm resource.
'''
t = self.load_template()
#short circuit the alarm's references
properties = t['Resources']['MEMAlarmHigh']['Properties']
properties['AlarmActions'] = ['a']
properties['Dimensions'] = [{'a': 'v'}]
stack = self.parse_stack(t)
# the watch rule needs a valid stack_id
stack.store()
self.m.ReplayAll()
resource = self.create_alarm(t, stack, 'MEMAlarmHigh')
snippet = copy.deepcopy(resource.parsed_template())
snippet['Properties']['ComparisonOperator'] = 'LessThanThreshold'
snippet['Properties']['AlarmDescription'] = 'fruity'
snippet['Properties']['EvaluationPeriods'] = '2'
snippet['Properties']['Period'] = '90'
snippet['Properties']['Statistic'] = 'Maximum'
snippet['Properties']['Threshold'] = '39'
self.assertEqual(cloud_watch.CloudWatchAlarm.UPDATE_COMPLETE,
resource.handle_update(snippet))
resource.delete()
self.m.VerifyAll()
def test_mem_alarm_high_update_replace(self):
'''
Make sure that the Alarm resource IS replaced when non-update-able
properties are changed.
'''
t = self.load_template()
#short circuit the alarm's references
properties = t['Resources']['MEMAlarmHigh']['Properties']
properties['AlarmActions'] = ['a']
properties['Dimensions'] = [{'a': 'v'}]
stack = self.parse_stack(t)
# the watch rule needs a valid stack_id
stack.store()
self.m.ReplayAll()
resource = self.create_alarm(t, stack, 'MEMAlarmHigh')
snippet = copy.deepcopy(resource.parsed_template())
snippet['Properties']['MetricName'] = 'temp'
self.assertEqual(cloud_watch.CloudWatchAlarm.UPDATE_REPLACE,
resource.handle_update(snippet))
resource.delete()
self.m.VerifyAll()
def test_scaling_group_adjust(self):
t = self.load_template()
stack = self.parse_stack(t)