Add the AutoScalingGroupName to the server Tags
Then use that to find the correct watch rule. blueprint watch-ceilometer Change-Id: I11f1556c1a55a06e1bf47e0baa156e0765f711ce
This commit is contained in:
parent
e6ec146fcf
commit
31e53d4fe7
@ -283,15 +283,6 @@ class WatchController(object):
|
||||
else:
|
||||
dimensions.append(dimension)
|
||||
|
||||
# We expect an AlarmName dimension as currently the engine
|
||||
# implementation requires metric data to be associated
|
||||
# with an alarm. When this is fixed, we can simply
|
||||
# parse the user-defined dimensions and add the list to
|
||||
# the metric data
|
||||
if not watch_name:
|
||||
logger.error("Request does not contain AlarmName dimension!")
|
||||
return exception.HeatMissingParameterError("AlarmName dimension")
|
||||
|
||||
# Extract the required data from the metric_data
|
||||
# and format dict to pass to engine
|
||||
data = {'Namespace': namespace,
|
||||
|
@ -135,11 +135,22 @@ class InstanceGroup(resource.Resource):
|
||||
instance_definition = self.stack.t['Resources'][conf]
|
||||
|
||||
# honour the Tags property in the InstanceGroup and AutoScalingGroup
|
||||
tags = self.properties.data.get('Tags', [])
|
||||
instance_definition['Properties']['Tags'] = tags
|
||||
|
||||
instance_definition['Properties']['Tags'] = self._tags()
|
||||
return GroupedInstance(name, instance_definition, self.stack)
|
||||
|
||||
def _tags(self):
|
||||
"""
|
||||
Make sure that we add a tag that Ceilometer can pick up.
|
||||
These need to be prepended with 'metering.'.
|
||||
"""
|
||||
tags = self.properties.get('Tags') or []
|
||||
for t in tags:
|
||||
if t['Key'].startswith('metering.'):
|
||||
# the user has added one, don't add another.
|
||||
return tags
|
||||
return tags + [{'Key': 'metering.groupname',
|
||||
'Value': self.FnGetRefId()}]
|
||||
|
||||
def _instances(self):
|
||||
'''
|
||||
Convert the stored instance list into a list of GroupedInstance objects
|
||||
@ -323,7 +334,6 @@ class AutoScalingGroup(InstanceGroup, CooldownMixin):
|
||||
'Cooldown', 'DesiredCapacity',)
|
||||
|
||||
def handle_create(self):
|
||||
|
||||
if self.properties['DesiredCapacity']:
|
||||
num_to_create = int(self.properties['DesiredCapacity'])
|
||||
else:
|
||||
@ -406,6 +416,17 @@ class AutoScalingGroup(InstanceGroup, CooldownMixin):
|
||||
|
||||
return result
|
||||
|
||||
def _tags(self):
|
||||
"""Add Identifing Tags to all servers in the group.
|
||||
|
||||
This is so the Dimensions received from cfn-push-stats all include
|
||||
the groupname and stack id.
|
||||
Note: the group name must match what is returned from FnGetRefId
|
||||
"""
|
||||
autoscaling_tag = [{'Key': 'AutoScalingGroupName',
|
||||
'Value': self.FnGetRefId()}]
|
||||
return super(AutoScalingGroup, self)._tags() + autoscaling_tag
|
||||
|
||||
def FnGetRefId(self):
|
||||
return unicode(self.name)
|
||||
|
||||
|
@ -662,9 +662,24 @@ class EngineService(service.Service):
|
||||
This could be used by CloudWatch and WaitConditions
|
||||
and treat HA service events like any other CloudWatch.
|
||||
'''
|
||||
rule = watchrule.WatchRule.load(cnxt, watch_name)
|
||||
rule.create_watch_data(stats_data)
|
||||
logger.debug('new watch:%s data:%s' % (watch_name, str(stats_data)))
|
||||
def get_matching_watches():
|
||||
if watch_name:
|
||||
yield watchrule.WatchRule.load(cnxt, watch_name)
|
||||
else:
|
||||
for wr in db_api.watch_rule_get_all(cnxt):
|
||||
if watchrule.rule_can_use_sample(wr, stats_data):
|
||||
yield watchrule.WatchRule.load(cnxt, watch=wr)
|
||||
|
||||
rule_run = False
|
||||
for rule in get_matching_watches():
|
||||
rule.create_watch_data(stats_data)
|
||||
rule_run = True
|
||||
|
||||
if not rule_run:
|
||||
if watch_name is None:
|
||||
watch_name = 'Unknown'
|
||||
raise exception.WatchRuleNotFound(watch_name=watch_name)
|
||||
|
||||
return stats_data
|
||||
|
||||
@request_context
|
||||
|
@ -309,3 +309,32 @@ class WatchRule(object):
|
||||
logger.warning("Unable to override state %s for watch %s" %
|
||||
(self.state, self.name))
|
||||
return actions
|
||||
|
||||
|
||||
def rule_can_use_sample(wr, stats_data):
|
||||
def match_dimesions(rule, data):
|
||||
for k, v in iter(rule.items()):
|
||||
if k not in data:
|
||||
return False
|
||||
elif v != data[k]:
|
||||
return False
|
||||
return True
|
||||
|
||||
if wr.state == WatchRule.SUSPENDED:
|
||||
return False
|
||||
if wr.rule['MetricName'] not in stats_data:
|
||||
return False
|
||||
|
||||
rule_dims = dict((d['Name'], d['Value'])
|
||||
for d in wr.rule.get('Dimensions', []))
|
||||
|
||||
for k, v in iter(stats_data.items()):
|
||||
if k == 'Namespace':
|
||||
continue
|
||||
if k == wr.rule['MetricName']:
|
||||
data_dims = v.get('Dimensions', {})
|
||||
if isinstance(data_dims, list):
|
||||
data_dims = data_dims[0]
|
||||
if match_dimesions(rule_dims, data_dims):
|
||||
return True
|
||||
return False
|
||||
|
@ -168,6 +168,7 @@ class ServerTagsTest(HeatTestCase):
|
||||
def test_group_tags(self):
|
||||
tags = [{'Key': 'Food', 'Value': 'yum'}]
|
||||
metadata = dict((tm['Key'], tm['Value']) for tm in tags)
|
||||
metadata['metering.groupname'] = 'WebServer'
|
||||
group = self._setup_test_group(intags=tags, nova_tags=metadata)
|
||||
self.m.ReplayAll()
|
||||
scheduler.TaskRunner(group.create)()
|
||||
|
@ -644,6 +644,137 @@ class WatchRuleTest(HeatTestCase):
|
||||
dbwr = db_api.watch_rule_get_by_name(self.ctx, 'create_data_test')
|
||||
self.assertEqual(dbwr.watch_data, [])
|
||||
|
||||
@utils.wr_delete_after
|
||||
def test_create_watch_data_match(self):
|
||||
rule = {u'EvaluationPeriods': u'1',
|
||||
u'AlarmDescription': u'test alarm',
|
||||
u'Period': u'300',
|
||||
u'ComparisonOperator': u'GreaterThanThreshold',
|
||||
u'Statistic': u'SampleCount',
|
||||
u'Threshold': u'2',
|
||||
u'Dimensions': [{u'Name': 'AutoScalingGroupName',
|
||||
u'Value': 'group_x'}],
|
||||
u'MetricName': u'CreateDataMetric'}
|
||||
self.wr = watchrule.WatchRule(context=self.ctx,
|
||||
watch_name='create_data_test',
|
||||
stack_id=self.stack_id, rule=rule)
|
||||
self.wr.store()
|
||||
|
||||
data = {u'CreateDataMetric': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [{u'AutoScalingGroupName':
|
||||
u'group_x'}]}}
|
||||
self.assertTrue(watchrule.rule_can_use_sample(self.wr, data))
|
||||
|
||||
@utils.wr_delete_after
|
||||
def test_create_watch_data_match_2(self):
|
||||
rule = {u'EvaluationPeriods': u'1',
|
||||
u'AlarmDescription': u'test alarm',
|
||||
u'Period': u'300',
|
||||
u'ComparisonOperator': u'GreaterThanThreshold',
|
||||
u'Statistic': u'SampleCount',
|
||||
u'Threshold': u'2',
|
||||
u'Dimensions': [{u'Name': 'AutoScalingGroupName',
|
||||
u'Value': 'group_x'}],
|
||||
u'MetricName': u'CreateDataMetric'}
|
||||
self.wr = watchrule.WatchRule(context=self.ctx,
|
||||
watch_name='create_data_test',
|
||||
stack_id=self.stack_id, rule=rule)
|
||||
self.wr.store()
|
||||
|
||||
data = {u'not_interesting': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'group_x'}]},
|
||||
u'CreateDataMetric': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'group_x'}]}}
|
||||
self.assertTrue(watchrule.rule_can_use_sample(self.wr, data))
|
||||
|
||||
def test_create_watch_data_match_3(self):
|
||||
rule = {u'EvaluationPeriods': u'1',
|
||||
u'AlarmDescription': u'test alarm',
|
||||
u'Period': u'300',
|
||||
u'ComparisonOperator': u'GreaterThanThreshold',
|
||||
u'Statistic': u'SampleCount',
|
||||
u'Threshold': u'2',
|
||||
u'Dimensions': [{u'Name': 'AutoScalingGroupName',
|
||||
u'Value': 'group_x'}],
|
||||
u'MetricName': u'CreateDataMetric'}
|
||||
self.wr = watchrule.WatchRule(context=self.ctx,
|
||||
watch_name='create_data_test',
|
||||
stack_id=self.stack_id, rule=rule)
|
||||
self.wr.store()
|
||||
|
||||
data = {u'CreateDataMetric': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'not_this'}]},
|
||||
u'CreateDataMetric': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'group_x'}]}}
|
||||
self.assertTrue(watchrule.rule_can_use_sample(self.wr, data))
|
||||
|
||||
def test_create_watch_data_not_match_metric(self):
|
||||
rule = {u'EvaluationPeriods': u'1',
|
||||
u'AlarmDescription': u'test alarm',
|
||||
u'Period': u'300',
|
||||
u'ComparisonOperator': u'GreaterThanThreshold',
|
||||
u'Statistic': u'SampleCount',
|
||||
u'Threshold': u'2',
|
||||
u'Dimensions': [{u'Name': 'AutoScalingGroupName',
|
||||
u'Value': 'group_x'}],
|
||||
u'MetricName': u'CreateDataMetric'}
|
||||
self.wr = watchrule.WatchRule(context=self.ctx,
|
||||
watch_name='create_data_test',
|
||||
stack_id=self.stack_id, rule=rule)
|
||||
self.wr.store()
|
||||
|
||||
data = {u'not_this': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'group_x'}]},
|
||||
u'nor_this': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'group_x'}]}}
|
||||
self.assertFalse(watchrule.rule_can_use_sample(self.wr, data))
|
||||
|
||||
def test_create_watch_data_not_match_dimensions(self):
|
||||
rule = {u'EvaluationPeriods': u'1',
|
||||
u'AlarmDescription': u'test alarm',
|
||||
u'Period': u'300',
|
||||
u'ComparisonOperator': u'GreaterThanThreshold',
|
||||
u'Statistic': u'SampleCount',
|
||||
u'Threshold': u'2',
|
||||
u'Dimensions': [{u'Name': 'AutoScalingGroupName',
|
||||
u'Value': 'group_x'}],
|
||||
u'MetricName': u'CreateDataMetric'}
|
||||
self.wr = watchrule.WatchRule(context=self.ctx,
|
||||
watch_name='create_data_test',
|
||||
stack_id=self.stack_id, rule=rule)
|
||||
self.wr.store()
|
||||
|
||||
data = {u'CreateDataMetric': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'AutoScalingGroupName':
|
||||
u'not_this'}]},
|
||||
u'CreateDataMetric': {"Unit": "Counter",
|
||||
"Value": "1",
|
||||
"Dimensions": [
|
||||
{u'wrong_key':
|
||||
u'group_x'}]}}
|
||||
self.assertFalse(watchrule.rule_can_use_sample(self.wr, data))
|
||||
|
||||
def test_destroy(self):
|
||||
rule = {'EvaluationPeriods': '1',
|
||||
'MetricName': 'test_metric',
|
||||
|
Loading…
Reference in New Issue
Block a user