
It is convenient to have all exceptions in exception module. Also it is reduces namespace cluttering of resource module and decreases the number of dependencies in other modules (we do not need to import resource in some cases for now). UpdateReplace exception is moved in this patch. Change-Id: Ief441ca2022a0d50e88d709d1a062631479715b7
162 lines
5.3 KiB
Python
162 lines
5.3 KiB
Python
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
import copy
|
|
|
|
from heat.common import exception
|
|
from heat.common import template_format
|
|
from heat.engine.resources.openstack.heat import cloud_watch
|
|
from heat.engine import rsrc_defn
|
|
from heat.engine import scheduler
|
|
from heat.engine import watchrule
|
|
from heat.tests import common
|
|
from heat.tests import utils
|
|
|
|
|
|
alarm_template = '''
|
|
{
|
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
|
"Description" : "Alarm Test",
|
|
"Parameters" : {},
|
|
"Resources" : {
|
|
"MEMAlarmHigh": {
|
|
"Type": "AWS::CloudWatch::Alarm",
|
|
"Properties": {
|
|
"AlarmDescription": "Scale-up if MEM > 50% for 1 minute",
|
|
"MetricName": "MemoryUtilization",
|
|
"Namespace": "system/linux",
|
|
"Statistic": "Average",
|
|
"Period": "60",
|
|
"EvaluationPeriods": "1",
|
|
"Threshold": "50",
|
|
"AlarmActions": [],
|
|
"Dimensions": [],
|
|
"ComparisonOperator": "GreaterThanThreshold"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
|
|
|
|
class CloudWatchAlarmTest(common.HeatTestCase):
|
|
def setUp(self):
|
|
super(CloudWatchAlarmTest, self).setUp()
|
|
|
|
def create_alarm(self, t, stack, resource_name):
|
|
resource_defns = stack.t.resource_definitions(stack)
|
|
rsrc = cloud_watch.CloudWatchAlarm(resource_name,
|
|
resource_defns[resource_name],
|
|
stack)
|
|
self.assertIsNone(rsrc.validate())
|
|
scheduler.TaskRunner(rsrc.create)()
|
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
|
return rsrc
|
|
|
|
def test_mem_alarm_high_update_no_replace(self):
|
|
'''
|
|
Make sure that we can change the update-able properties
|
|
without replacing the Alarm rsrc.
|
|
'''
|
|
t = template_format.parse(alarm_template)
|
|
|
|
# short circuit the alarm's references
|
|
properties = t['Resources']['MEMAlarmHigh']['Properties']
|
|
properties['AlarmActions'] = ['a']
|
|
properties['Dimensions'] = [{'a': 'v'}]
|
|
|
|
stack = utils.parse_stack(t)
|
|
# the watch rule needs a valid stack_id
|
|
stack.store()
|
|
|
|
self.m.ReplayAll()
|
|
rsrc = self.create_alarm(t, stack, 'MEMAlarmHigh')
|
|
props = copy.copy(rsrc.properties.data)
|
|
props.update({
|
|
'ComparisonOperator': 'LessThanThreshold',
|
|
'AlarmDescription': 'fruity',
|
|
'EvaluationPeriods': '2',
|
|
'Period': '90',
|
|
'Statistic': 'Maximum',
|
|
'Threshold': '39',
|
|
})
|
|
snippet = rsrc_defn.ResourceDefinition(rsrc.name,
|
|
rsrc.type(),
|
|
props)
|
|
|
|
scheduler.TaskRunner(rsrc.update, snippet)()
|
|
|
|
scheduler.TaskRunner(rsrc.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 = template_format.parse(alarm_template)
|
|
|
|
# short circuit the alarm's references
|
|
properties = t['Resources']['MEMAlarmHigh']['Properties']
|
|
properties['AlarmActions'] = ['a']
|
|
properties['Dimensions'] = [{'a': 'v'}]
|
|
|
|
stack = utils.parse_stack(t)
|
|
# the watch rule needs a valid stack_id
|
|
stack.store()
|
|
|
|
self.m.ReplayAll()
|
|
rsrc = self.create_alarm(t, stack, 'MEMAlarmHigh')
|
|
props = copy.copy(rsrc.properties.data)
|
|
props['MetricName'] = 'temp'
|
|
snippet = rsrc_defn.ResourceDefinition(rsrc.name,
|
|
rsrc.type(),
|
|
props)
|
|
|
|
updater = scheduler.TaskRunner(rsrc.update, snippet)
|
|
self.assertRaises(exception.UpdateReplace, updater)
|
|
|
|
scheduler.TaskRunner(rsrc.delete)()
|
|
self.m.VerifyAll()
|
|
|
|
def test_suspend_resume(self):
|
|
t = template_format.parse(alarm_template)
|
|
stack_name = "test_cw_alarm_sus_res_stack"
|
|
stack = utils.parse_stack(t, stack_name=stack_name)
|
|
# the watch rule needs a valid stack_id
|
|
stack.store()
|
|
|
|
self.m.ReplayAll()
|
|
rsrc = self.create_alarm(t, stack, 'MEMAlarmHigh')
|
|
scheduler.TaskRunner(rsrc.suspend)()
|
|
self.assertEqual((rsrc.SUSPEND, rsrc.COMPLETE), rsrc.state)
|
|
|
|
self.ctx = utils.dummy_context()
|
|
|
|
wr = watchrule.WatchRule.load(
|
|
self.ctx, watch_name="%s-MEMAlarmHigh" % stack_name)
|
|
|
|
self.assertEqual(watchrule.WatchRule.SUSPENDED, wr.state)
|
|
|
|
scheduler.TaskRunner(rsrc.resume)()
|
|
self.assertEqual((rsrc.RESUME, rsrc.COMPLETE), rsrc.state)
|
|
|
|
wr = watchrule.WatchRule.load(
|
|
self.ctx, watch_name="%s-MEMAlarmHigh" % stack_name)
|
|
|
|
self.assertEqual(watchrule.WatchRule.NODATA, wr.state)
|
|
|
|
scheduler.TaskRunner(rsrc.delete)()
|
|
self.m.VerifyAll()
|