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
'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,
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:
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
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')
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))
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)