From 9e688a116963c9310d077cf21ef7a15dcb142008 Mon Sep 17 00:00:00 2001 From: Joe Keen Date: Mon, 27 Apr 2015 15:55:55 -0600 Subject: [PATCH] Cleanup Removed non-events API methods --- .../api/alarm_definitions_api_v2.py | 51 -- monasca_events_api/api/alarms_api_v2.py | 55 -- monasca_events_api/api/monasca_api_v2.py | 47 -- .../api/monasca_notifications_api_v2.py | 46 -- .../expression_parser/__init__.py | 0 .../expression_parser/alarm_expr_parser.py | 297 -------- .../middleware/metric_validator.py | 125 ---- .../alarm_definition_request_body_schema.py | 52 -- .../v2/common/schemas/dimensions_schema.py | 33 - .../v2/common/schemas/metric_name_schema.py | 31 - .../schemas/metrics_request_body_schema.py | 40 - .../notifications_request_body_schema.py | 41 -- .../v2/reference/alarm_definitions.py | 687 ------------------ monasca_events_api/v2/reference/alarming.py | 176 ----- monasca_events_api/v2/reference/alarms.py | 328 --------- monasca_events_api/v2/reference/metrics.py | 230 ------ .../v2/reference/notifications.py | 185 ----- 17 files changed, 2424 deletions(-) delete mode 100644 monasca_events_api/api/alarm_definitions_api_v2.py delete mode 100644 monasca_events_api/api/alarms_api_v2.py delete mode 100644 monasca_events_api/api/monasca_api_v2.py delete mode 100644 monasca_events_api/api/monasca_notifications_api_v2.py delete mode 100644 monasca_events_api/expression_parser/__init__.py delete mode 100644 monasca_events_api/expression_parser/alarm_expr_parser.py delete mode 100644 monasca_events_api/middleware/metric_validator.py delete mode 100644 monasca_events_api/v2/common/schemas/alarm_definition_request_body_schema.py delete mode 100644 monasca_events_api/v2/common/schemas/dimensions_schema.py delete mode 100644 monasca_events_api/v2/common/schemas/metric_name_schema.py delete mode 100644 monasca_events_api/v2/common/schemas/metrics_request_body_schema.py delete mode 100644 monasca_events_api/v2/common/schemas/notifications_request_body_schema.py delete mode 100644 monasca_events_api/v2/reference/alarm_definitions.py delete mode 100644 monasca_events_api/v2/reference/alarming.py delete mode 100644 monasca_events_api/v2/reference/alarms.py delete mode 100644 monasca_events_api/v2/reference/metrics.py delete mode 100644 monasca_events_api/v2/reference/notifications.py diff --git a/monasca_events_api/api/alarm_definitions_api_v2.py b/monasca_events_api/api/alarm_definitions_api_v2.py deleted file mode 100644 index e9ab555..0000000 --- a/monasca_events_api/api/alarm_definitions_api_v2.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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. -from monasca.common import resource_api -from monasca.openstack.common import log - -LOG = log.getLogger(__name__) - - -class AlarmDefinitionsV2API(object): - - def __init__(self, global_conf): - - super(AlarmDefinitionsV2API, self).__init__(global_conf) - - LOG.debug('initializing AlarmDefinitionsV2API!') - self.global_conf = global_conf - - @resource_api.Restify('/v2.0/alarm-definitions', method='post') - def do_post_alarm_definitions(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='get') - def do_get_alarm_definition(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='put') - def do_put_alarm_definitions(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarm-definitions', method='get') - def do_get_alarm_definitions(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='patch') - def do_patch_alarm_definitions(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='delete') - def do_delete_alarm_definitions(self, req, res, id): - res.status = '501 Not Implemented' diff --git a/monasca_events_api/api/alarms_api_v2.py b/monasca_events_api/api/alarms_api_v2.py deleted file mode 100644 index 7a4f611..0000000 --- a/monasca_events_api/api/alarms_api_v2.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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. -from monasca.common import resource_api -from monasca.openstack.common import log - -LOG = log.getLogger(__name__) - - -class AlarmsV2API(object): - - def __init__(self, global_conf): - - super(AlarmsV2API, self).__init__(global_conf) - - LOG.debug('initializing AlarmsV2API!') - self.global_conf = global_conf - - @resource_api.Restify('/v2.0/alarms/{id}', method='put') - def do_put_alarms(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarms/{id}', method='patch') - def do_patch_alarms(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarms/{id}', method='delete') - def do_delete_alarms(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarms/', method='get') - def do_get_alarms(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarms/{id}', method='get') - def do_get_alarm_by_id(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarms/x', method='get') - def do_get_alarms_state_history(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/alarms/{id}/state-history', method='get') - def do_get_alarm_state_history(self, req, res, id): - res.status = '501 Not Implemented' diff --git a/monasca_events_api/api/monasca_api_v2.py b/monasca_events_api/api/monasca_api_v2.py deleted file mode 100644 index 1048b64..0000000 --- a/monasca_events_api/api/monasca_api_v2.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2013 IBM Corp -# -# Author: Tong Li -# -# 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. - -from monasca.common import resource_api -from monasca.openstack.common import log - - -LOG = log.getLogger(__name__) - - -class V2API(object): - def __init__(self, global_conf): - LOG.debug('initializing V2API!') - self.global_conf = global_conf - - @resource_api.Restify('/v2.0/metrics', method='get') - def do_get_metrics(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/metrics/', method='post') - def do_post_metrics(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/{version_id}', method='get') - def do_get_version(self, req, res, version_id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/metrics/measurements', method='get') - def do_get_measurements(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/metrics/statistics', method='get') - def do_get_statistics(self, req, res): - res.status = '501 Not Implemented' diff --git a/monasca_events_api/api/monasca_notifications_api_v2.py b/monasca_events_api/api/monasca_notifications_api_v2.py deleted file mode 100644 index bfd0e6c..0000000 --- a/monasca_events_api/api/monasca_notifications_api_v2.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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. - -from monasca.common import resource_api -from monasca.openstack.common import log - - -LOG = log.getLogger(__name__) - - -class NotificationsV2API(object): - - def __init__(self, global_conf): - LOG.debug('initializing V2API!') - self.global_conf = global_conf - - @resource_api.Restify('/v2.0/notification-methods', method='post') - def do_post_notification_methods(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/notification-methods/{id}', method='delete') - def do_delete_notification_methods(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/notification-methods', method='get') - def do_get_notification_methods(self, req, res): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/notification-methods/{id}', method='get') - def do_get_notification_method(self, req, res, id): - res.status = '501 Not Implemented' - - @resource_api.Restify('/v2.0/notification-methods/{id}', method='put') - def do_put_notification_methods(self, req, res, id): - res.status = '501 Not Implemented' diff --git a/monasca_events_api/expression_parser/__init__.py b/monasca_events_api/expression_parser/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_events_api/expression_parser/alarm_expr_parser.py b/monasca_events_api/expression_parser/alarm_expr_parser.py deleted file mode 100644 index ad96c35..0000000 --- a/monasca_events_api/expression_parser/alarm_expr_parser.py +++ /dev/null @@ -1,297 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2014 Hewlett-Packard -# -# 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 itertools -import sys - -import pyparsing - - -class SubExpr(object): - - def __init__(self, tokens): - - self._sub_expr = tokens - self._func = tokens.func - self._metric_name = tokens.metric_name - self._dimensions = tokens.dimensions.dimensions_list - self._operator = tokens.relational_op - self._threshold = tokens.threshold - self._period = tokens.period - self._periods = tokens.periods - self._id = None - - @property - def sub_expr_str(self): - """Get the entire sub expression as a string with no spaces.""" - return "".join(list(itertools.chain(*self._sub_expr))) - - @property - def fmtd_sub_expr_str(self): - """Get the entire sub expressions as a string with spaces.""" - result = "{}({}".format(self._func.encode('utf8'), - self._metric_name.encode('utf8')) - - if self._dimensions: - result += "{{{}}}".format(self._dimensions.encode('utf8')) - - if self._period: - result += ", {}".format(self._period.encode('utf8')) - - result += ")" - - result += " {} {}".format(self._operator.encode('utf8'), - self._threshold.encode('utf8')) - - if self._periods: - result += " times {}".format(self._periods.encode('utf8')) - - return result.decode('utf8') - - @property - def dimensions_str(self): - """Get all the dimensions as a single comma delimited string.""" - return self._dimensions - - @property - def operands_list(self): - """Get this sub expression as a list.""" - return [self] - - @property - def func(self): - """Get the function as it appears in the orig expression.""" - return self._func - - @property - def normalized_func(self): - """Get the function upper-cased.""" - return self._func.upper() - - @property - def metric_name(self): - """Get the metric name as it appears in the orig expression.""" - return self._metric_name - - @property - def normalized_metric_name(self): - """Get the metric name lower-cased.""" - return self._metric_name.lower() - - @property - def dimensions(self): - """Get the dimensions.""" - return self._dimensions - - @property - def dimensions_as_list(self): - """Get the dimensions as a list.""" - if self._dimensions: - return self._dimensions.split(",") - else: - return [] - - @property - def operator(self): - """Get the operator.""" - return self._operator - - @property - def threshold(self): - """Get the threshold value.""" - return self._threshold - - @property - def period(self): - """Get the period. Default is 60 seconds.""" - if self._period: - return self._period - else: - return u'60' - - @property - def periods(self): - """Get the periods. Default is 1.""" - if self._periods: - return self._periods - else: - return u'1' - - @property - def normalized_operator(self): - """Get the operator as one of LT, GT, LTE, or GTE.""" - if self._operator.lower() == "lt" or self._operator == "<": - return u"LT" - elif self._operator.lower() == "gt" or self._operator == ">": - return u"GT" - elif self._operator.lower() == "lte" or self._operator == "<=": - return u"LTE" - elif self._operator.lower() == "gte" or self._operator == ">=": - return u"GTE" - - @property - def id(self): - """Get the id used to identify this sub expression in the repo.""" - return self._id - - @id.setter - def id(self, id): - """Set the d used to identify this sub expression in the repo.""" - self._id = id - - -class BinaryOp(object): - def __init__(self, tokens): - self.op = tokens[0][1] - self.operands = tokens[0][0::2] - - @property - def operands_list(self): - return ([sub_operand for operand in self.operands for sub_operand in - operand.operands_list]) - - -class AndSubExpr(BinaryOp): - """Expand later as needed.""" - pass - - -class OrSubExpr(BinaryOp): - """Expand later as needed.""" - pass - - -COMMA = pyparsing.Literal(",") -LPAREN = pyparsing.Literal("(") -RPAREN = pyparsing.Literal(")") -EQUAL = pyparsing.Literal("=") -LBRACE = pyparsing.Literal("{") -RBRACE = pyparsing.Literal("}") - -# Initialize non-ascii unicode code points in the Basic Multilingual Plane. -unicode_printables = u''.join( - unichr(c) for c in xrange(128, 65536) if not unichr(c).isspace()) - -# Does not like comma. No Literals from above allowed. -valid_identifier_chars = ( - (unicode_printables + pyparsing.alphanums + ".-_#!$%&'*+/:;?@[\\]^`|~")) - -metric_name = ( - pyparsing.Word(valid_identifier_chars, min=1, max=255)("metric_name")) -dimension_name = pyparsing.Word(valid_identifier_chars, min=1, max=255) -dimension_value = pyparsing.Word(valid_identifier_chars, min=1, max=255) - -integer_number = pyparsing.Word(pyparsing.nums) -decimal_number = pyparsing.Word(pyparsing.nums + ".") - -max = pyparsing.CaselessLiteral("max") -min = pyparsing.CaselessLiteral("min") -avg = pyparsing.CaselessLiteral("avg") -count = pyparsing.CaselessLiteral("count") -sum = pyparsing.CaselessLiteral("sum") -func = (max | min | avg | count | sum)("func") - -less_than_op = ( - (pyparsing.CaselessLiteral("<") | pyparsing.CaselessLiteral("lt"))) -less_than_eq_op = ( - (pyparsing.CaselessLiteral("<=") | pyparsing.CaselessLiteral("lte"))) -greater_than_op = ( - (pyparsing.CaselessLiteral(">") | pyparsing.CaselessLiteral("gt"))) -greater_than_eq_op = ( - (pyparsing.CaselessLiteral(">=") | pyparsing.CaselessLiteral("gte"))) - -# Order is important. Put longer prefix first. -relational_op = ( - less_than_eq_op | less_than_op | greater_than_eq_op | greater_than_op)( - "relational_op") - -AND = pyparsing.CaselessLiteral("and") | pyparsing.CaselessLiteral("&&") -OR = pyparsing.CaselessLiteral("or") | pyparsing.CaselessLiteral("||") -logical_op = (AND | OR)("logical_op") - -times = pyparsing.CaselessLiteral("times") - -dimension = pyparsing.Group(dimension_name + EQUAL + dimension_value) - -# Cannot have any whitespace after the comma delimiter. -dimension_list = pyparsing.Group(pyparsing.Optional( - LBRACE + pyparsing.delimitedList(dimension, delim=',', combine=True)( - "dimensions_list") + RBRACE)) - -metric = metric_name + dimension_list("dimensions") -period = integer_number("period") -threshold = decimal_number("threshold") -periods = integer_number("periods") - -expression = pyparsing.Forward() - -sub_expression = (func + LPAREN + metric + pyparsing.Optional( - COMMA + period) + RPAREN + relational_op + threshold + pyparsing.Optional( - times + periods) | LPAREN + expression + RPAREN) - -sub_expression.setParseAction(SubExpr) - -expression = ( - pyparsing.operatorPrecedence(sub_expression, - [(AND, 2, pyparsing.opAssoc.LEFT, AndSubExpr), - (OR, 2, pyparsing.opAssoc.LEFT, OrSubExpr)])) - - -class AlarmExprParser(object): - def __init__(self, expr): - self._expr = expr - - @property - def sub_expr_list(self): - # Remove all spaces before parsing. Simple, quick fix for whitespace - # issue with dimension list not allowing whitespace after comma. - parseResult = (expression + pyparsing.stringEnd).parseString( - self._expr.replace(' ', '')) - sub_expr_list = parseResult[0].operands_list - return sub_expr_list - - -def main(): - """Used for development and testing.""" - - expr0 = ( - "max(-_.千幸福的笑脸{घोड़ा=馬, " - "dn2=dv2,千幸福的笑脸घ=千幸福的笑脸घ}) gte 100 " - "times 3 && " - "(min(ເຮືອນ{dn3=dv3,家=дом}) < 10 or sum(biz{dn5=dv5}) >9 9and " - "count(fizzle) lt 0 or count(baz) > 1)".decode('utf8')) - - expr1 = ("max(foo{hostname=mini-mon,千=千}, 120) > 100 and (max(bar)>100 " - " or max(biz)>100)".decode('utf8')) - - expr2 = "max(foo)>=100" - - for expr in (expr0, expr1, expr2): - print ('orig expr: {}'.format(expr.encode('utf8'))) - alarmExprParser = AlarmExprParser(expr) - sub_expr = alarmExprParser.sub_expr_list - for sub_expression in sub_expr: - print ('sub expr: {}'.format( - sub_expression.sub_expr_str.encode('utf8'))) - print ('fmtd sub expr: {}'.format( - sub_expression.fmtd_sub_expr_str.encode('utf8'))) - print ('sub_expr dimensions: {}'.format( - sub_expression.dimensions_str.encode('utf8'))) - print () - print () - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/monasca_events_api/middleware/metric_validator.py b/monasca_events_api/middleware/metric_validator.py deleted file mode 100644 index db69632..0000000 --- a/monasca_events_api/middleware/metric_validator.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2013 IBM Corp -# -# Author: Tong Li -# -# 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 datetime -import StringIO -try: - import ujson as json -except ImportError: - import json - - -class MetricValidator(object): - """middleware that validate the metric input stream. - - This middleware checks if the input stream actually follows metric spec - and all the messages in the request has valid metric data. If the body - is valid json and compliant with the spec, then the request will forward - the request to the next in the pipeline, otherwise, it will reject the - request with response code of 400 or 406. - """ - def __init__(self, app, conf): - self.app = app - self.conf = conf - - def _is_valid_metric(self, metric): - """Validate a message - - The external message format is - { - "name":"name1", - "dimensions":{ - "key1":"value1", - "key2":"value2" - }, - "timestamp":1405630174, - "value":1.0 - } - - Once this is validated, the message needs to be transformed into - the following internal format: - - The current valid message format is as follows (interna): - { - "metric": {"something": "The metric as a JSON object"}, - "meta": { - "tenantId": "the tenant ID acquired", - "region": "the region that the metric was submitted under", - }, - "creation_time": "the time when the API received the metric", - } - """ - if (metric.get('name') and metric.get('dimensions') and - metric.get('timestamp') and metric.get('value')): - return True - else: - return False - - def __call__(self, env, start_response): - # if request starts with /datapoints/, then let it go on. - # this login middle - if (env.get('PATH_INFO', '').startswith('/v2.0/metrics') and - env.get('REQUEST_METHOD', '') == 'POST'): - # We only check the requests which are posting against metrics - # endpoint - try: - body = env['wsgi.input'].read() - metrics = json.loads(body) - # Do business logic validation here. - is_valid = True - if isinstance(metrics, list): - for metric in metrics: - if not self._is_valid_metric(metric): - is_valid = False - break - else: - is_valid = self._is_valid_metric(metrics) - - if is_valid: - # If the message is valid, then wrap it into this internal - # format. The tenantId should be available from the - # request since this should have been authenticated. - # ideally this transformation should be done somewhere - # else. For the sake of simplicity, do the simple one - # here to make the life a bit easier. - - # TODO(HP) Add logic to get region id from request header - # HTTP_X_SERVICE_CATALOG, then find endpoints, then region - region_id = None - msg = {'metric': metrics, - 'meta': {'tenantId': env.get('HTTP_X_PROJECT_ID'), - 'region': region_id}, - 'creation_time': datetime.datetime.now()} - env['wsgi.input'] = StringIO.StringIO(json.dumps(msg)) - return self.app(env, start_response) - except Exception: - pass - # It is either invalid or exceptioned out while parsing json - # we will send the request back with 400. - start_response("400 Bad Request", [], '') - return [] - else: - # not a metric post request, move on. - return self.app(env, start_response) - - -def filter_factory(global_conf, **local_conf): - - def validator_filter(app): - return MetricValidator(app, local_conf) - - return validator_filter diff --git a/monasca_events_api/v2/common/schemas/alarm_definition_request_body_schema.py b/monasca_events_api/v2/common/schemas/alarm_definition_request_body_schema.py deleted file mode 100644 index 874a6e6..0000000 --- a/monasca_events_api/v2/common/schemas/alarm_definition_request_body_schema.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 voluptuous - -from monasca.openstack.common import log -from monasca.v2.common.schemas import exceptions - - -LOG = log.getLogger(__name__) - -alarm_definition_schema = { - voluptuous.Required('name'): voluptuous.All(voluptuous.Any(str, unicode), - voluptuous.Length(max=250)), - voluptuous.Required('expression'): voluptuous.All( - voluptuous.Any(str, unicode), voluptuous.Length(max=4096)), - voluptuous.Optional('description'): voluptuous.All( - voluptuous.Any(str, unicode), voluptuous.Length(max=250)), - voluptuous.Optional('severity'): voluptuous.All( - voluptuous.Any('low', 'medium', 'high', 'critical', 'LOW', "MEDIUM", - 'HIGH', 'CRITICAL')), - voluptuous.Optional('match_by'): voluptuous.All( - voluptuous.Any([unicode], [str]), voluptuous.Length(max=255)), - voluptuous.Optional('ok_actions'): voluptuous.All( - voluptuous.Any([str], [unicode]), voluptuous.Length(max=400)), - voluptuous.Optional('alarm_actions'): voluptuous.All( - voluptuous.Any([str], [unicode]), voluptuous.Length(max=400)), - voluptuous.Optional('undetermined_actions'): voluptuous.All( - voluptuous.Any([str], [unicode]), voluptuous.Length(max=400)), - voluptuous.Optional('actions_enabled'): bool} - -request_body_schema = voluptuous.Schema(alarm_definition_schema, required=True, - extra=True) - - -def validate(msg): - try: - request_body_schema(msg) - except Exception as ex: - LOG.debug(ex) - raise exceptions.ValidationException(str(ex)) diff --git a/monasca_events_api/v2/common/schemas/dimensions_schema.py b/monasca_events_api/v2/common/schemas/dimensions_schema.py deleted file mode 100644 index 648ede2..0000000 --- a/monasca_events_api/v2/common/schemas/dimensions_schema.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 voluptuous - -from monasca.openstack.common import log -from monasca.v2.common.schemas import exceptions - -LOG = log.getLogger(__name__) - -dimensions_schema = voluptuous.Schema({ - voluptuous.All(voluptuous.Any(str, unicode), - voluptuous.Length(max=255)): voluptuous.All( - voluptuous.Any(str, unicode), voluptuous.Length(max=255))}) - - -def validate(dimensions): - try: - dimensions_schema(dimensions) - except Exception as ex: - LOG.debug(ex) - raise exceptions.ValidationException(str(ex)) diff --git a/monasca_events_api/v2/common/schemas/metric_name_schema.py b/monasca_events_api/v2/common/schemas/metric_name_schema.py deleted file mode 100644 index 95eec5a..0000000 --- a/monasca_events_api/v2/common/schemas/metric_name_schema.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 voluptuous - -from monasca.openstack.common import log -from monasca.v2.common.schemas import exceptions - -LOG = log.getLogger(__name__) - -metric_name_schema = voluptuous.Schema( - voluptuous.All(voluptuous.Any(str, unicode), voluptuous.Length(max=64))) - - -def validate(name): - try: - metric_name_schema(name) - except Exception as ex: - LOG.debug(ex) - raise exceptions.ValidationException(str(ex)) diff --git a/monasca_events_api/v2/common/schemas/metrics_request_body_schema.py b/monasca_events_api/v2/common/schemas/metrics_request_body_schema.py deleted file mode 100644 index 79b8e1d..0000000 --- a/monasca_events_api/v2/common/schemas/metrics_request_body_schema.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 voluptuous - -from monasca.openstack.common import log -from monasca.v2.common.schemas import dimensions_schema -from monasca.v2.common.schemas import exceptions -from monasca.v2.common.schemas import metric_name_schema - -LOG = log.getLogger(__name__) - -metric_schema = { - voluptuous.Required('name'): metric_name_schema.metric_name_schema, - voluptuous.Optional('dimensions'): dimensions_schema.dimensions_schema, - voluptuous.Required('timestamp'): voluptuous.All( - voluptuous.Any(int, float), voluptuous.Range(min=0)), - voluptuous.Required('value'): voluptuous.Any(int, float)} - -request_body_schema = voluptuous.Schema( - voluptuous.Any(metric_schema, [metric_schema])) - - -def validate(msg): - try: - request_body_schema(msg) - except Exception as ex: - LOG.debug(ex) - raise exceptions.ValidationException(str(ex)) diff --git a/monasca_events_api/v2/common/schemas/notifications_request_body_schema.py b/monasca_events_api/v2/common/schemas/notifications_request_body_schema.py deleted file mode 100644 index 7fed239..0000000 --- a/monasca_events_api/v2/common/schemas/notifications_request_body_schema.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 voluptuous - -from monasca.openstack.common import log -from monasca.v2.common.schemas import exceptions - -LOG = log.getLogger(__name__) - -notification_schema = { - voluptuous.Required('name'): voluptuous.Schema( - voluptuous.All(voluptuous.Any(str, unicode), - voluptuous.Length(max=250))), - voluptuous.Required('type'): voluptuous.Schema( - voluptuous.Any("EMAIL", "email", "WEBHOOK", "webhook", - "PAGERDUTY", "pagerduty")), - voluptuous.Required('address'): voluptuous.Schema( - voluptuous.All(voluptuous.Any(str, unicode), - voluptuous.Length(max=100)))} - -request_body_schema = voluptuous.Schema(voluptuous.Any(notification_schema)) - - -def validate(msg): - try: - request_body_schema(msg) - except Exception as ex: - LOG.debug(ex) - raise exceptions.ValidationException(str(ex)) diff --git a/monasca_events_api/v2/reference/alarm_definitions.py b/monasca_events_api/v2/reference/alarm_definitions.py deleted file mode 100644 index 80ae277..0000000 --- a/monasca_events_api/v2/reference/alarm_definitions.py +++ /dev/null @@ -1,687 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 re - -import falcon -from oslo.config import cfg -import pyparsing - -from monasca.api import alarm_definitions_api_v2 -from monasca.common.repositories import exceptions -from monasca.common import resource_api -import monasca.expression_parser.alarm_expr_parser -from monasca.openstack.common import log -from monasca.v2.common.schemas import (alarm_definition_request_body_schema - as schema_alarms) -from monasca.v2.common.schemas import exceptions as schemas_exceptions -from monasca.v2.reference import alarming -from monasca.v2.reference import helpers -from monasca.v2.reference import resource - - -LOG = log.getLogger(__name__) - - -class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, - alarming.Alarming): - def __init__(self, global_conf): - - try: - - super(AlarmDefinitions, self).__init__(global_conf) - - self._region = cfg.CONF.region - - self._default_authorized_roles = ( - cfg.CONF.security.default_authorized_roles) - self._delegate_authorized_roles = ( - cfg.CONF.security.delegate_authorized_roles) - self._post_metrics_authorized_roles = ( - cfg.CONF.security.default_authorized_roles + - cfg.CONF.security.agent_authorized_roles) - - self._alarm_definitions_repo = resource_api.init_driver( - 'monasca.repositories', - cfg.CONF.repositories.alarm_definitions_driver) - - except Exception as ex: - LOG.exception(ex) - raise exceptions.RepositoryException(ex) - - @resource_api.Restify('/v2.0/alarm-definitions', method='post') - def do_post_alarm_definitions(self, req, res): - helpers.validate_authorization(req, self._default_authorized_roles) - - alarm_definition = helpers.read_json_msg_body(req) - - self._validate_alarm_definition(alarm_definition) - - tenant_id = helpers.get_tenant_id(req) - name = get_query_alarm_definition_name(alarm_definition) - expression = get_query_alarm_definition_expression(alarm_definition) - description = get_query_alarm_definition_description(alarm_definition) - severity = get_query_alarm_definition_severity(alarm_definition) - match_by = get_query_alarm_definition_match_by(alarm_definition) - alarm_actions = get_query_alarm_definition_alarm_actions( - alarm_definition) - undetermined_actions = get_query_alarm_definition_undetermined_actions( - alarm_definition) - ok_actions = get_query_ok_actions(alarm_definition) - - result = self._alarm_definition_create(tenant_id, name, expression, - description, severity, match_by, - alarm_actions, - undetermined_actions, - ok_actions) - - helpers.add_links_to_resource(result, req.uri) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_201 - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='get') - def do_get_alarm_definition(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - - result = self._alarm_definition_show(tenant_id, id) - - helpers.add_links_to_resource(result, re.sub('/' + id, '', req.uri)) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='put') - def do_put_alarm_definitions(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - - alarm_definition = helpers.read_json_msg_body(req) - - self._validate_alarm_definition(alarm_definition) - - tenant_id = helpers.get_tenant_id(req) - - # Mandatory positional args - name = get_query_alarm_definition_name(alarm_definition) - expression = get_query_alarm_definition_expression(alarm_definition) - actions_enabled = ( - get_query_alarm_definition_actions_enabled(alarm_definition, - required=True)) - - # Validator makes actions_enabled optional. So, check it here. - if not actions_enabled: - raise falcon.HTTPBadRequest('Bad request', 'Missing ' - 'actions_enabled') - - # Optional args - description = get_query_alarm_definition_description(alarm_definition, - return_none=True) - alarm_actions = get_query_alarm_definition_alarm_actions( - alarm_definition, return_none=True) - ok_actions = get_query_ok_actions(alarm_definition, return_none=True) - undetermined_actions = get_query_alarm_definition_undetermined_actions( - alarm_definition, return_none=True) - match_by = get_query_alarm_definition_match_by(alarm_definition, - return_none=True) - severity = get_query_alarm_definition_severity(alarm_definition, - return_none=True) - - result = self._alarm_definition_update_or_patch(tenant_id, - id, - name, - expression, - actions_enabled, - description, - alarm_actions, - ok_actions, - undetermined_actions, - match_by, - severity, - patch=False) - - helpers.add_links_to_resource(result, req.uri) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarm-definitions', method='get') - def do_get_alarm_definitions(self, req, res): - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - name = helpers.get_query_name(req) - dimensions = helpers.get_query_dimensions(req) - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - - result = self._alarm_definition_list(tenant_id, name, dimensions, - req.uri, offset) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='patch') - def do_patch_alarm_definitions(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - - alarm_definition = helpers.read_json_msg_body(req) - - tenant_id = helpers.get_tenant_id(req) - - # Optional args - name = get_query_alarm_definition_name(alarm_definition, - return_none=True) - expression = get_query_alarm_definition_expression(alarm_definition, - return_none=True) - actions_enabled = ( - get_query_alarm_definition_actions_enabled(alarm_definition, - return_none=True)) - - description = get_query_alarm_definition_description(alarm_definition, - return_none=True) - alarm_actions = get_query_alarm_definition_alarm_actions( - alarm_definition, return_none=True) - ok_actions = get_query_ok_actions(alarm_definition, return_none=True) - undetermined_actions = get_query_alarm_definition_undetermined_actions( - alarm_definition, return_none=True) - match_by = get_query_alarm_definition_match_by(alarm_definition, - return_none=True) - severity = get_query_alarm_definition_severity(alarm_definition, - return_none=True) - - result = self._alarm_definition_update_or_patch(tenant_id, - id, - name, - expression, - actions_enabled, - description, - alarm_actions, - ok_actions, - undetermined_actions, - match_by, - severity, - patch=True) - - helpers.add_links_to_resource(result, req.uri) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarm-definitions/{id}', method='delete') - def do_delete_alarm_definitions(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - self._alarm_definition_delete(tenant_id, id) - res.status = falcon.HTTP_204 - - @resource.resource_try_catch_block - def _alarm_definition_show(self, tenant_id, id): - - alarm_definition_row = ( - self._alarm_definitions_repo.get_alarm_definition(tenant_id, id)) - - return self._build_alarm_definition_show_result(alarm_definition_row) - - def _build_alarm_definition_show_result(self, alarm_definition_row): - - match_by = get_comma_separated_str_as_list( - alarm_definition_row['match_by']) - - alarm_actions_list = get_comma_separated_str_as_list( - alarm_definition_row['alarm_actions']) - - ok_actions_list = get_comma_separated_str_as_list( - alarm_definition_row['ok_actions']) - - undetermined_actions_list = get_comma_separated_str_as_list( - alarm_definition_row['undetermined_actions']) - - result = { - u'actions_enabled': alarm_definition_row['actions_enabled'] == 1, - u'alarm_actions': alarm_actions_list, - u'undetermined_actions': undetermined_actions_list, - u'ok_actions': ok_actions_list, - u'description': alarm_definition_row['description'].decode( - 'utf8'), - u'expression': alarm_definition_row['expression'].decode('utf8'), - u'id': alarm_definition_row['id'].decode('utf8'), - u'match_by': match_by, - u'name': alarm_definition_row['name'].decode('utf8'), - u'severity': alarm_definition_row['severity'].decode( - 'utf8').upper()} - - return result - - @resource.resource_try_catch_block - def _alarm_definition_delete(self, tenant_id, id): - - sub_alarm_definition_rows = ( - self._alarm_definitions_repo.get_sub_alarm_definitions(id)) - alarm_metric_rows = self._alarm_definitions_repo.get_alarm_metrics( - tenant_id, id) - sub_alarm_rows = self._alarm_definitions_repo.get_sub_alarms( - tenant_id, id) - - if not self._alarm_definitions_repo.delete_alarm_definition( - tenant_id, id): - raise falcon.HTTPNotFound - - self._send_alarm_definition_deleted_event(id, - sub_alarm_definition_rows) - - self._send_alarm_event(u'alarm-deleted', tenant_id, id, - alarm_metric_rows, sub_alarm_rows) - - @resource.resource_try_catch_block - def _alarm_definition_list(self, tenant_id, name, dimensions, req_uri, - offset): - - alarm_definition_rows = ( - self._alarm_definitions_repo.get_alarm_definitions(tenant_id, name, - dimensions, - offset)) - - result = [] - for alarm_definition_row in alarm_definition_rows: - match_by = get_comma_separated_str_as_list( - alarm_definition_row['match_by']) - - alarm_actions_list = get_comma_separated_str_as_list( - alarm_definition_row['alarm_actions']) - - ok_actions_list = get_comma_separated_str_as_list( - alarm_definition_row['ok_actions']) - - undetermined_actions_list = get_comma_separated_str_as_list( - alarm_definition_row['undetermined_actions']) - - ad = {u'id': alarm_definition_row['id'].decode('utf8'), - u'name': alarm_definition_row['name'].decode("utf8"), - u'description': alarm_definition_row['description'].decode( - 'utf8') if alarm_definition_row['description'] else u'', - u'expression': alarm_definition_row['expression'].decode( - 'utf8'), u'match_by': match_by, - u'severity': alarm_definition_row['severity'].decode( - 'utf8').upper(), - u'actions_enabled': - alarm_definition_row['actions_enabled'] == 1, - u'alarm_actions': alarm_actions_list, - u'ok_actions': ok_actions_list, - u'undetermined_actions': undetermined_actions_list} - - helpers.add_links_to_resource(ad, req_uri) - result.append(ad) - - result = helpers.paginate(result, req_uri, offset) - - return result - - def _validate_alarm_definition(self, alarm_definition): - - try: - schema_alarms.validate(alarm_definition) - except schemas_exceptions.ValidationException as ex: - LOG.debug(ex) - raise falcon.HTTPBadRequest('Bad request', ex.message) - - @resource.resource_try_catch_block - def _alarm_definition_update_or_patch(self, tenant_id, - id, - name, - expression, - actions_enabled, - description, - alarm_actions, - ok_actions, - undetermined_actions, - match_by, - severity, - patch): - - if expression: - try: - sub_expr_list = ( - monasca.expression_parser.alarm_expr_parser. - AlarmExprParser(expression).sub_expr_list) - - except pyparsing.ParseException as ex: - LOG.exception(ex) - title = "Invalid alarm expression".encode('utf8') - msg = "parser failed on expression '{}' at column {}".format( - expression.encode('utf8'), str(ex.column).encode('utf8')) - raise falcon.HTTPBadRequest(title, msg) - else: - sub_expr_list = None - - alarm_def_row, sub_alarm_def_dicts = ( - self._alarm_definitions_repo.update_or_patch_alarm_definition( - tenant_id, - id, - name, - expression, - sub_expr_list, - actions_enabled, - description, - alarm_actions, - ok_actions, - undetermined_actions, - match_by, - severity, - patch)) - - old_sub_alarm_def_event_dict = ( - self._build_sub_alarm_def_update_dict( - sub_alarm_def_dicts['old'])) - - new_sub_alarm_def_event_dict = ( - self._build_sub_alarm_def_update_dict(sub_alarm_def_dicts[ - 'new'])) - - changed_sub_alarm_def_event_dict = ( - self._build_sub_alarm_def_update_dict(sub_alarm_def_dicts[ - 'changed'])) - - unchanged_sub_alarm_def_event_dict = ( - self._build_sub_alarm_def_update_dict(sub_alarm_def_dicts[ - 'unchanged'])) - - alarm_def_event_dict = ( - {u'tenantId': tenant_id, - u'alarmDefinitionId': id, - u'alarmName': name, - u'alarmDescription': description, - u'alarmExpression': expression, - u'severity': severity, - u'matchBy': match_by, - u'alarmActionsEnabled': actions_enabled, - u'oldAlarmSubExpressions': old_sub_alarm_def_event_dict, - u'changedSubExpressions': changed_sub_alarm_def_event_dict, - u'unchangedSubExpressions': unchanged_sub_alarm_def_event_dict, - u'newAlarmSubExpressions': new_sub_alarm_def_event_dict}) - - alarm_definition_updated_event = ( - {u'alarm-definition-updated': alarm_def_event_dict}) - - self.send_event(self.events_message_queue, - alarm_definition_updated_event) - - result = self._build_alarm_definition_show_result(alarm_def_row) - - return result - - def _build_sub_alarm_def_update_dict(self, sub_alarm_def_dict): - - sub_alarm_def_update_dict = {} - for id, sub_alarm_def in sub_alarm_def_dict.items(): - dimensions = {} - for name, value in sub_alarm_def.dimensions.items(): - dimensions[u'uname'] = value - sub_alarm_def_update_dict[sub_alarm_def.id] = {} - sub_alarm_def_update_dict[sub_alarm_def.id][u'function'] = ( - sub_alarm_def.function) - sub_alarm_def_update_dict[sub_alarm_def.id][ - u'metricDefinition'] = ( - {u'name': sub_alarm_def.metric_name, - u'dimensions': dimensions}) - sub_alarm_def_update_dict[sub_alarm_def.id][u'operator'] = ( - sub_alarm_def.operator) - sub_alarm_def_update_dict[sub_alarm_def.id][u'threshold'] = ( - sub_alarm_def.threshold) - sub_alarm_def_update_dict[sub_alarm_def.id][u'period'] = ( - sub_alarm_def.period) - sub_alarm_def_update_dict[sub_alarm_def.id][u'periods'] = ( - sub_alarm_def.periods) - sub_alarm_def_update_dict[sub_alarm_def.id][u'expression'] = ( - sub_alarm_def.expression) - - return sub_alarm_def_update_dict - - @resource.resource_try_catch_block - def _alarm_definition_create(self, tenant_id, name, expression, - description, severity, match_by, - alarm_actions, undetermined_actions, - ok_actions): - try: - - sub_expr_list = ( - monasca.expression_parser.alarm_expr_parser. - AlarmExprParser(expression).sub_expr_list) - - except pyparsing.ParseException as ex: - LOG.exception(ex) - title = "Invalid alarm expression".encode('utf8') - msg = "parser failed on expression '{}' at column {}".format( - expression.encode('utf8'), str(ex.column).encode('utf8')) - raise falcon.HTTPBadRequest(title, msg) - - alarm_definition_id = ( - self._alarm_definitions_repo. - create_alarm_definition(tenant_id, - name, - expression, - sub_expr_list, - description, - severity, - match_by, - alarm_actions, - undetermined_actions, - ok_actions)) - - self._send_alarm_definition_created_event(tenant_id, - alarm_definition_id, - name, expression, - sub_expr_list, - description, match_by) - result = ( - {u'alarm_actions': alarm_actions, u'ok_actions': ok_actions, - u'description': description, u'match_by': match_by, - u'severity': severity, u'actions_enabled': u'true', - u'undetermined_actions': undetermined_actions, - u'expression': expression, u'id': alarm_definition_id, - u'name': name}) - - return result - - def _send_alarm_definition_deleted_event(self, alarm_definition_id, - sub_alarm_definition_rows): - - sub_alarm_definition_deleted_event_msg = {} - alarm_definition_deleted_event_msg = {u"alarm-definition-deleted": { - u"alarmDefinitionId": alarm_definition_id, - u'subAlarmMetricDefinitions': - sub_alarm_definition_deleted_event_msg}} - - for sub_alarm_definition in sub_alarm_definition_rows: - sub_alarm_definition_deleted_event_msg[ - sub_alarm_definition['id']] = { - u'name': sub_alarm_definition['metric_name']} - dimensions = {} - sub_alarm_definition_deleted_event_msg[sub_alarm_definition['id']][ - u'dimensions'] = dimensions - if sub_alarm_definition['dimensions']: - for dimension in sub_alarm_definition['dimensions'].split(','): - parsed_dimension = dimension.split('=') - dimensions[parsed_dimension[0]] = parsed_dimension[1] - - self.send_event(self.events_message_queue, - alarm_definition_deleted_event_msg) - - def _send_alarm_definition_created_event(self, tenant_id, - alarm_definition_id, name, - expression, sub_expr_list, - description, match_by): - - alarm_definition_created_event_msg = { - u'alarm-definition-created': {u'tenantId': tenant_id, - u'alarmDefinitionId': - alarm_definition_id, - u'alarmName': name, - u'alarmDescription': description, - u'alarmExpression': expression, - u'matchBy': match_by}} - - sub_expr_event_msg = {} - for sub_expr in sub_expr_list: - sub_expr_event_msg[sub_expr.id] = { - u'function': sub_expr.normalized_func} - metric_definition = {u'name': sub_expr.normalized_metric_name} - sub_expr_event_msg[sub_expr.id][ - u'metricDefinition'] = metric_definition - dimensions = {} - for dimension in sub_expr.dimensions_as_list: - parsed_dimension = dimension.split("=") - dimensions[parsed_dimension[0]] = parsed_dimension[1] - metric_definition[u'dimensions'] = dimensions - sub_expr_event_msg[sub_expr.id][ - u'operator'] = sub_expr.normalized_operator - sub_expr_event_msg[sub_expr.id][u'threshold'] = sub_expr.threshold - sub_expr_event_msg[sub_expr.id][u'period'] = sub_expr.period - sub_expr_event_msg[sub_expr.id][u'periods'] = sub_expr.periods - sub_expr_event_msg[sub_expr.id][ - u'expression'] = sub_expr.fmtd_sub_expr_str - - alarm_definition_created_event_msg[u'alarm-definition-created'][ - u'alarmSubExpressions'] = sub_expr_event_msg - - self.send_event(self.events_message_queue, - alarm_definition_created_event_msg) - - -def get_query_alarm_definition_name(alarm_definition, return_none=False): - try: - if 'name' in alarm_definition: - name = alarm_definition['name'] - return name - else: - if return_none: - return None - else: - raise Exception("Missing name") - except Exception as ex: - LOG.debug(ex) - raise falcon.HTTPBadRequest('Bad request', ex.message) - - -def get_query_alarm_definition_expression(alarm_definition, - return_none=False): - try: - if 'expression' in alarm_definition: - expression = alarm_definition['expression'] - return expression - else: - if return_none: - return None - else: - raise Exception("Missing expression") - except Exception as ex: - LOG.debug(ex) - raise falcon.HTTPBadRequest('Bad request', ex.message) - - -def get_query_alarm_definition_description(alarm_definition, - return_none=False): - if 'description' in alarm_definition: - return alarm_definition['description'] - else: - if return_none: - return None - else: - return '' - - -def get_query_alarm_definition_severity(alarm_definition, return_none=False): - if 'severity' in alarm_definition: - severity = alarm_definition['severity'] - severity = severity.decode('utf8').upper() - if severity not in ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']: - raise falcon.HTTPBadRequest('Bad request', 'Invalid severity') - return severity - else: - if return_none: - return None - else: - return 'LOW' - - -def get_query_alarm_definition_match_by(alarm_definition, return_none=False): - if 'match_by' in alarm_definition: - match_by = alarm_definition['match_by'] - return match_by - else: - if return_none: - return None - else: - return [] - - -def get_query_alarm_definition_alarm_actions(alarm_definition, - return_none=False): - if 'alarm_actions' in alarm_definition: - alarm_actions = alarm_definition['alarm_actions'] - return alarm_actions - else: - if return_none: - return None - else: - return [] - - -def get_query_alarm_definition_undetermined_actions(alarm_definition, - return_none=False): - if 'undetermined_actions' in alarm_definition: - undetermined_actions = alarm_definition['undetermined_actions'] - return undetermined_actions - else: - if return_none: - return None - else: - return [] - - -def get_query_ok_actions(alarm_definition, return_none=False): - if 'ok_actions' in alarm_definition: - ok_actions = alarm_definition['ok_actions'] - return ok_actions - else: - if return_none: - return None - else: - return [] - - -def get_query_alarm_definition_actions_enabled(alarm_definition, - required=False, - return_none=False): - try: - if 'actions_enabled' in alarm_definition: - enabled_actions = alarm_definition['actions_enabled'] - return enabled_actions - else: - if return_none: - return None - elif required: - raise Exception("Missing actions-enabled") - else: - return '' - except Exception as ex: - LOG.debug(ex) - raise falcon.HTTPBadRequest('Bad request', ex.message) - - -def get_comma_separated_str_as_list(comma_separated_str): - if not comma_separated_str: - return [] - else: - return comma_separated_str.decode('utf8').split(',') diff --git a/monasca_events_api/v2/reference/alarming.py b/monasca_events_api/v2/reference/alarming.py deleted file mode 100644 index 797ea8e..0000000 --- a/monasca_events_api/v2/reference/alarming.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 falcon -from oslo.config import cfg - -from monasca.common.messaging import exceptions as message_queue_exceptions -from monasca.common import resource_api -import monasca.expression_parser.alarm_expr_parser -from monasca.openstack.common import log -from monasca.v2.reference import helpers - - -LOG = log.getLogger(__name__) - - -class Alarming(object): - """Super class for Alarms and AlarmDefinitions. - - Shared attributes and methods for classes Alarms and AlarmDefinitions. - """ - - def __init__(self, global_conf): - - super(Alarming, self).__init__() - - self.events_message_queue = ( - resource_api.init_driver('monasca.messaging', - cfg.CONF.messaging.driver, - (['events']))) - - self.alarm_state_transitions_message_queue = ( - resource_api.init_driver('monasca.messaging', - cfg.CONF.messaging.driver, - (['alarm-state-transitions']))) - - def _send_alarm_transitioned_event(self, tenant_id, alarm_id, - alarm_definition_row, - alarm_metric_rows, - old_state, new_state): - - metrics = [] - alarm_transitioned_event_msg = {u'alarm-transitioned': { - u'tenantId': tenant_id, - u'alarmId': alarm_id, - u'alarmDefinitionId': alarm_definition_row['id'], - u'alarmName': alarm_definition_row['name'], - u'alarmDescription': alarm_definition_row['description'], - u'actionsEnabled': alarm_definition_row['actions_enabled'] == 1, - u'stateChangeReason': 'Alarm state updated via API', - u'severity': alarm_definition_row['severity'], - u'oldState': old_state, - u'newState': new_state, - u'metrics': metrics} - } - - for alarm_metric_row in alarm_metric_rows: - metric = self._build_metric(alarm_metric_row) - metrics.append(metric) - - self.send_event(self.alarm_state_transitions_message_queue, - alarm_transitioned_event_msg) - - def _build_metric(self, alarm_metric_row): - - dimensions = {} - - metric = {u'name': alarm_metric_row['name'], - u'dimensions': dimensions} - - for dimension in alarm_metric_row['dimensions'].split(','): - parsed_dimension = dimension.split('=') - dimensions[parsed_dimension[0]] = parsed_dimension[1] - - return metric - - def _send_alarm_event(self, event_type, tenant_id, alarm_definition_id, - alarm_metric_rows, sub_alarm_rows, extra_info=None): - - if not alarm_metric_rows: - return - - # Build a dict mapping alarm id -> list of sub alarms. - sub_alarm_dict = {} - for sub_alarm_row in sub_alarm_rows: - if sub_alarm_row['alarm_id'] in sub_alarm_dict: - sub_alarm_dict[sub_alarm_row['alarm_id']] += [sub_alarm_row] - else: - sub_alarm_dict[sub_alarm_row['alarm_id']] = [sub_alarm_row] - - # Forward declaration. - alarm_event_msg = {} - prev_alarm_id = None - for alarm_metric_row in alarm_metric_rows: - if prev_alarm_id != alarm_metric_row['alarm_id']: - if prev_alarm_id is not None: - sub_alarms_event_msg = ( - self._build_sub_alarm_event_msg(sub_alarm_dict, - prev_alarm_id)) - alarm_event_msg[event_type][ - u'subAlarms': sub_alarms_event_msg] - self.send_event(self.events_message_queue, - alarm_event_msg) - - alarm_metrics_event_msg = [] - alarm_event_msg = {event_type: {u'tenant_id': tenant_id, - u'alarmDefinitionId': - alarm_definition_id, - u'alarmId': alarm_metric_row[ - 'alarm_id'], - u'alarmMetrics': - alarm_metrics_event_msg}} - if extra_info: - alarm_event_msg[event_type].update(extra_info) - - prev_alarm_id = alarm_metric_row['alarm_id'] - - metric = self._build_metric(alarm_metric_row) - alarm_metrics_event_msg.append(metric) - - # Finish last alarm - sub_alarms_event_msg = self._build_sub_alarm_event_msg(sub_alarm_dict, - prev_alarm_id) - alarm_event_msg[event_type][u'subAlarms'] = sub_alarms_event_msg - - self.send_event(self.events_message_queue, - alarm_event_msg) - - def _build_sub_alarm_event_msg(self, sub_alarm_dict, alarm_id): - - sub_alarms_event_msg = {} - - if alarm_id not in sub_alarm_dict: - return sub_alarms_event_msg - - for sub_alarm in sub_alarm_dict[alarm_id]: - # There's only one expr in a sub alarm, so just take the first. - sub_expr = ( - monasca.expression_parser.alarm_expr_parser.AlarmExprParser( - sub_alarm['expression']).sub_expr_list[0]) - dimensions = {} - sub_alarms_event_msg[sub_alarm['sub_alarm_id']] = { - u'function': sub_expr.normalized_func, - u'metricDefinition': {u'name': sub_expr.metric_name, - u'dimensions': dimensions}, - u'operator': sub_expr.normalized_operator, - u'threshold': sub_expr.threshold, u'period': sub_expr.period, - u'periods': sub_expr.periods, - u'expression': sub_expr.fmtd_sub_expr_str} - - for dimension in sub_expr.dimensions_as_list: - parsed_dimension = dimension.split('=') - dimensions[parsed_dimension[0]] = parsed_dimension[1] - - return sub_alarms_event_msg - - def send_event(self, message_queue, event_msg): - try: - message_queue.send_message( - helpers.dumpit_utf8(event_msg)) - except message_queue_exceptions.MessageQueueException as ex: - LOG.exception(ex) - raise falcon.HTTPInternalServerError( - 'Message queue service unavailable'.encode('utf8'), - ex.message.encode('utf8')) diff --git a/monasca_events_api/v2/reference/alarms.py b/monasca_events_api/v2/reference/alarms.py deleted file mode 100644 index 46c9361..0000000 --- a/monasca_events_api/v2/reference/alarms.py +++ /dev/null @@ -1,328 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 re - -import falcon -from oslo.config import cfg - -from monasca.api import alarms_api_v2 -from monasca.common.repositories import exceptions -from monasca.common import resource_api -from monasca.openstack.common import log -from monasca.v2.reference.alarming import Alarming -from monasca.v2.reference import helpers -from monasca.v2.reference import resource - - -LOG = log.getLogger(__name__) - - -class Alarms(alarms_api_v2.AlarmsV2API, Alarming): - - def __init__(self, global_conf): - - try: - - super(Alarms, self).__init__(global_conf) - - self._region = cfg.CONF.region - - self._default_authorized_roles = ( - cfg.CONF.security.default_authorized_roles) - self._delegate_authorized_roles = ( - cfg.CONF.security.delegate_authorized_roles) - self._post_metrics_authorized_roles = ( - cfg.CONF.security.default_authorized_roles + - cfg.CONF.security.agent_authorized_roles) - - self._alarms_repo = resource_api.init_driver( - 'monasca.repositories', cfg.CONF.repositories.alarms_driver) - - self._metrics_repo = resource_api.init_driver( - 'monasca.repositories', cfg.CONF.repositories.metrics_driver) - - except Exception as ex: - LOG.exception(ex) - raise exceptions.RepositoryException(ex) - - @resource_api.Restify('/v2.0/alarms/{id}', method='put') - def do_put_alarms(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - - tenant_id = helpers.get_tenant_id(req) - - state = self._get_alarm_state(req) - - self._alarm_update(tenant_id, id, state) - - result = self._alarm_show(req.uri, tenant_id, id) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarms/{id}', method='patch') - def do_patch_alarms(self, req, res, id): - - # Same logic as alarm_update - return self.do_put_alarms(req, res, id) - - @resource_api.Restify('/v2.0/alarms/{id}', method='delete') - def do_delete_alarms(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - - tenant_id = helpers.get_tenant_id(req) - - self._alarm_delete(tenant_id, id) - - res.status = falcon.HTTP_204 - - @resource_api.Restify('/v2.0/alarms', method='get') - def do_get_alarms(self, req, res): - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - - query_parms = falcon.uri.parse_query_string(req.query_string) - - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - - result = self._alarm_list(req.uri, tenant_id, query_parms, offset) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarms/{id}', method='get') - def do_get_alarm_by_id(self, req, res, id): - - # Necessary because falcon interprets 'state-history' as an - # alarm id, and this url masks '/v2.0/alarms/state-history'. - if id.lower() == 'state-history': - return self.do_get_alarms_state_history(req, res) - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - - result = self._alarm_show(req.uri, tenant_id, id) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarms/state-history', method='get') - def do_get_alarms_state_history(self, req, res): - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - start_timestamp = helpers.get_query_starttime_timestamp(req, False) - end_timestamp = helpers.get_query_endtime_timestamp(req, False) - query_parms = falcon.uri.parse_query_string(req.query_string) - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - - result = self._alarm_history_list(tenant_id, start_timestamp, - end_timestamp, query_parms, - req.uri, offset) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/alarms/{id}/state-history', method='get') - def do_get_alarm_state_history(self, req, res, id): - - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - - result = self._alarm_history(tenant_id, [id], req.uri, offset) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource.resource_try_catch_block - def _alarm_update(self, tenant_id, id, new_state): - - alarm_metric_rows = self._alarms_repo.get_alarm_metrics(id) - sub_alarm_rows = self._alarms_repo.get_sub_alarms(tenant_id, id) - - old_state = self._alarms_repo.update_alarm(tenant_id, id, new_state) - - # alarm_definition_id is the same for all rows. - alarm_definition_id = sub_alarm_rows[0]['alarm_definition_id'] - - state_info = {u'alarmState': new_state, u'oldAlarmState': old_state} - - self._send_alarm_event(u'alarm-updated', tenant_id, - alarm_definition_id, alarm_metric_rows, - sub_alarm_rows, state_info) - - if old_state != new_state: - try: - alarm_definition_row = self._alarms_repo.get_alarm_definition( - tenant_id, id) - except exceptions.DoesNotExistException: - # Alarm definition does not exist. May have been deleted - # in another transaction. In that case, all associated - # alarms were also deleted, so don't send transition events. - pass - else: - self._send_alarm_transitioned_event(tenant_id, id, - alarm_definition_row, - alarm_metric_rows, - old_state, new_state) - - @resource.resource_try_catch_block - def _alarm_history_list(self, tenant_id, start_timestamp, - end_timestamp, query_parms, req_uri, offset): - - # get_alarms expects 'metric_dimensions' for dimensions key. - if 'dimensions' in query_parms: - new_query_parms = {'metric_dimensions': query_parms['dimensions']} - else: - new_query_parms = {} - - alarm_rows = self._alarms_repo.get_alarms(tenant_id, new_query_parms) - alarm_id_list = [alarm_row['alarm_id'] for alarm_row in alarm_rows] - - result = self._metrics_repo.alarm_history(tenant_id, alarm_id_list, - offset, - start_timestamp, - end_timestamp) - - return helpers.paginate(result, req_uri, offset) - - @resource.resource_try_catch_block - def _alarm_history(self, tenant_id, alarm_id, req_uri, offset): - - result = self._metrics_repo.alarm_history(tenant_id, alarm_id, offset) - - return helpers.paginate(result, req_uri, offset) - - @resource.resource_try_catch_block - def _alarm_delete(self, tenant_id, id): - - alarm_metric_rows = self._alarms_repo.get_alarm_metrics(id) - sub_alarm_rows = self._alarms_repo.get_sub_alarms(tenant_id, id) - - self._alarms_repo.delete_alarm(tenant_id, id) - - # alarm_definition_id is the same for all rows. - alarm_definition_id = sub_alarm_rows[0]['alarm_definition_id'] - - self._send_alarm_event(u'alarm-deleted', tenant_id, - alarm_definition_id, alarm_metric_rows, - sub_alarm_rows) - - @resource.resource_try_catch_block - def _alarm_show(self, req_uri, tenant_id, id): - - alarm_rows = self._alarms_repo.get_alarm(tenant_id, id) - - first_row = True - for alarm_row in alarm_rows: - if first_row: - ad = {u'id': alarm_row['alarm_definition_id'], - u'name': alarm_row['alarm_definition_name'], - u'severity': alarm_row['severity'], } - helpers.add_links_to_resource(ad, - re.sub('alarms', - 'alarm-definitions', - req_uri), - rel=None) - - metrics = [] - alarm = {u'id': alarm_row['alarm_id'], u'metrics': metrics, - u'state': alarm_row['state'], - u'alarm_definition': ad} - helpers.add_links_to_resource(alarm, req_uri) - - first_row = False - - dimensions = {} - metric = {u'name': alarm_row['metric_name'], - u'dimensions': dimensions} - - if alarm_row['metric_dimensions']: - for dimension in alarm_row['metric_dimensions'].split(','): - parsed_dimension = dimension.split('=') - dimensions[parsed_dimension[0]] = parsed_dimension[1] - - metrics.append(metric) - - return alarm - - @resource.resource_try_catch_block - def _alarm_list(self, req_uri, tenant_id, query_parms, offset): - - alarm_rows = self._alarms_repo.get_alarms(tenant_id, query_parms, - offset) - - result = [] - - if not alarm_rows: - return result - - # Forward declaration - alarm = {} - prev_alarm_id = None - for alarm_row in alarm_rows: - if prev_alarm_id != alarm_row['alarm_id']: - if prev_alarm_id is not None: - result.append(alarm) - - ad = {u'id': alarm_row['alarm_definition_id'], - u'name': alarm_row['alarm_definition_name'], - u'severity': alarm_row['severity'], } - helpers.add_links_to_resource(ad, - re.sub('alarms', - 'alarm-definitions', - req_uri), - rel=None) - - metrics = [] - alarm = {u'id': alarm_row['alarm_id'], u'metrics': metrics, - u'state': alarm_row['state'], - u'alarm_definition': ad} - helpers.add_links_to_resource(alarm, req_uri) - - prev_alarm_id = alarm_row['alarm_id'] - - dimensions = {} - metric = {u'name': alarm_row['metric_name'], - u'dimensions': dimensions} - - if alarm_row['metric_dimensions']: - for dimension in alarm_row['metric_dimensions'].split(','): - parsed_dimension = dimension.split('=') - dimensions[parsed_dimension[0]] = parsed_dimension[1] - - metrics.append(metric) - - result.append(alarm) - - return helpers.paginate(result, req_uri, offset) - - def _get_alarm_state(self, req): - - json_msg = helpers.read_http_resource(req) - if 'state' in json_msg: - state = json_msg['state'].upper() - if state not in ['OK', 'ALARM', 'UNDETERMINED']: - raise falcon.HTTPBadRequest('Bad request', 'Invalid state') - return state - else: - raise falcon.HTTPBadRequest('Bad request', 'Missing state') diff --git a/monasca_events_api/v2/reference/metrics.py b/monasca_events_api/v2/reference/metrics.py deleted file mode 100644 index 8cf5992..0000000 --- a/monasca_events_api/v2/reference/metrics.py +++ /dev/null @@ -1,230 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 json - -import falcon -from oslo.config import cfg - -from monasca.api import monasca_api_v2 -from monasca.common.messaging import exceptions as message_queue_exceptions -from monasca.common.messaging.message_formats import metrics_transform_factory -from monasca.common import resource_api -from monasca.openstack.common import log -from monasca.v2.common.schemas import (exceptions as schemas_exceptions) -from monasca.v2.common.schemas import ( - metrics_request_body_schema as schemas_metrics) -from monasca.v2.common import utils -from monasca.v2.reference import helpers - - -LOG = log.getLogger(__name__) - - -class Metrics(monasca_api_v2.V2API): - def __init__(self, global_conf): - - try: - - super(Metrics, self).__init__(global_conf) - - self._region = cfg.CONF.region - self._default_authorized_roles = ( - cfg.CONF.security.default_authorized_roles) - self._delegate_authorized_roles = ( - cfg.CONF.security.delegate_authorized_roles) - self._post_metrics_authorized_roles = ( - cfg.CONF.security.default_authorized_roles + - cfg.CONF.security.agent_authorized_roles) - self._metrics_transform = ( - metrics_transform_factory.create_metrics_transform()) - self._message_queue = ( - resource_api.init_driver('monasca.messaging', - cfg.CONF.messaging.driver, - ['metrics'])) - self._metrics_repo = resource_api.init_driver( - 'monasca.repositories', cfg.CONF.repositories.metrics_driver) - - except Exception as ex: - LOG.exception(ex) - raise falcon.HTTPInternalServerError('Service unavailable', - ex.message) - - def _validate_metrics(self, metrics): - """Validates the metrics - - :param metrics: A metric object or array of metrics objects. - :raises falcon.HTTPBadRequest - """ - try: - schemas_metrics.validate(metrics) - except schemas_exceptions.ValidationException as ex: - LOG.debug(ex) - raise falcon.HTTPBadRequest('Bad request', ex.message) - - def _send_metrics(self, metrics): - """Send the metrics using the message queue. - - :param metrics: A metric object or array of metrics objects. - :raises: falcon.HTTPServiceUnavailable - """ - - def _send_metric(metric): - try: - str_msg = json.dumps(metric, default=utils.date_handler) - self._message_queue.send_message(str_msg) - except message_queue_exceptions.MessageQueueException as ex: - LOG.exception(ex) - raise falcon.HTTPServiceUnavailable('Service unavailable', - ex.message, 60) - - if isinstance(metrics, list): - for metric in metrics: - _send_metric(metric) - else: - _send_metric(metrics) - - def _list_metrics(self, tenant_id, name, dimensions, req_uri, offset): - """Query the metric repo for the metrics, format them and return them. - - :param tenant_id: - :param name: - :param dimensions: - :raises falcon.HTTPServiceUnavailable - """ - - try: - result = self._metrics_repo.list_metrics(tenant_id, - self._region, - name, - dimensions, offset) - - return helpers.paginate(result, req_uri, offset) - - except Exception as ex: - LOG.exception(ex) - raise falcon.HTTPServiceUnavailable('Service unavailable', - ex.message, 60) - - def _measurement_list(self, tenant_id, name, dimensions, start_timestamp, - end_timestamp, req_uri, offset): - try: - result = self._metrics_repo.measurement_list(tenant_id, - self._region, - name, - dimensions, - start_timestamp, - end_timestamp, - offset) - - if offset is not None: - - paginated_result = [] - for measurement in result: - paginated_result.append( - helpers.paginate_measurement(measurement, - req_uri, offset)) - - result = {u'links': [{u'rel': u'self', - u'href': req_uri.decode('utf8')}], - u'elements': paginated_result} - - return result - - except Exception as ex: - LOG.exception(ex) - raise falcon.HTTPServiceUnavailable('Service unavailable', - ex.message, 60) - - def _metric_statistics(self, tenant_id, name, dimensions, start_timestamp, - end_timestamp, statistics, period): - try: - return self._metrics_repo.metrics_statistics(tenant_id, - self._region, - name, - dimensions, - start_timestamp, - end_timestamp, - statistics, period) - except Exception as ex: - LOG.exception(ex) - raise falcon.HTTPServiceUnavailable('Service unavailable', - ex.message, 60) - - @resource_api.Restify('/v2.0/metrics/', method='post') - def do_post_metrics(self, req, res): - helpers.validate_json_content_type(req) - helpers.validate_authorization(req, - self._post_metrics_authorized_roles) - metrics = helpers.read_http_resource(req) - self._validate_metrics(metrics) - tenant_id = ( - helpers.get_x_tenant_or_tenant_id(req, - self._delegate_authorized_roles)) - transformed_metrics = self._metrics_transform(metrics, tenant_id, - self._region) - self._send_metrics(transformed_metrics) - res.status = falcon.HTTP_204 - - @resource_api.Restify('/v2.0/metrics/', method='get') - def do_get_metrics(self, req, res): - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - name = helpers.get_query_name(req) - helpers.validate_query_name(name) - dimensions = helpers.get_query_dimensions(req) - helpers.validate_query_dimensions(dimensions) - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - result = self._list_metrics(tenant_id, name, dimensions, - req.uri, offset) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/metrics/measurements', method='get') - def do_get_measurements(self, req, res): - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - name = helpers.get_query_name(req) - helpers.validate_query_name(name) - dimensions = helpers.get_query_dimensions(req) - helpers.validate_query_dimensions(dimensions) - start_timestamp = helpers.get_query_starttime_timestamp(req) - end_timestamp = helpers.get_query_endtime_timestamp(req, False) - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - result = self._measurement_list(tenant_id, name, dimensions, - start_timestamp, end_timestamp, - req.uri, offset) - - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/metrics/statistics', method='get') - def do_get_statistics(self, req, res): - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - name = helpers.get_query_name(req) - helpers.validate_query_name(name) - dimensions = helpers.get_query_dimensions(req) - helpers.validate_query_dimensions(dimensions) - start_timestamp = helpers.get_query_starttime_timestamp(req) - end_timestamp = helpers.get_query_endtime_timestamp(req, False) - statistics = helpers.get_query_statistics(req) - period = helpers.get_query_period(req) - result = self._metric_statistics(tenant_id, name, dimensions, - start_timestamp, end_timestamp, - statistics, period) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 diff --git a/monasca_events_api/v2/reference/notifications.py b/monasca_events_api/v2/reference/notifications.py deleted file mode 100644 index 12ed5e9..0000000 --- a/monasca_events_api/v2/reference/notifications.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2014 Hewlett-Packard -# -# 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 falcon -from oslo.config import cfg - -from monasca.api import monasca_notifications_api_v2 -from monasca.common import resource_api -from monasca.openstack.common import log -from monasca.v2.common.schemas import (exceptions as schemas_exceptions) -from monasca.v2.common.schemas import ( - notifications_request_body_schema as schemas_notifications) -from monasca.v2.reference import helpers -from monasca.v2.reference import resource - - -LOG = log.getLogger(__name__) - - -class Notifications(monasca_notifications_api_v2.NotificationsV2API): - - def __init__(self, global_conf): - - super(Notifications, self).__init__(global_conf) - - self._region = cfg.CONF.region - self._default_authorized_roles = ( - cfg.CONF.security.default_authorized_roles) - self._notifications_repo = resource_api.init_driver( - 'monasca.repositories', cfg.CONF.repositories.notifications_driver) - - def _validate_notification(self, notification): - """Validates the notification - - :param notification: An event object. - :raises falcon.HTTPBadRequest - """ - try: - schemas_notifications.validate(notification) - except schemas_exceptions.ValidationException as ex: - LOG.debug(ex) - raise falcon.HTTPBadRequest('Bad request', ex.message) - - @resource.resource_try_catch_block - def _create_notification(self, tenant_id, notification, uri): - - name = notification['name'].decode('utf8') - notification_type = notification['type'].upper().decode('utf8') - address = notification['address'].decode('utf8') - notification_id = self._notifications_repo.create_notification( - tenant_id, - name, - notification_type, - address) - - return self._create_notification_response(notification_id, - name, - notification_type, - address, - uri) - - @resource.resource_try_catch_block - def _update_notification(self, id, tenant_id, notification, uri): - - name = notification['name'].decode('utf8') - notification_type = notification['type'].upper().decode('utf8') - address = notification['address'].decode('utf8') - self._notifications_repo.update_notification(id, tenant_id, name, - notification_type, - address) - - return self._create_notification_response(id, - name, - notification_type, - address, - uri) - - def _create_notification_response(self, id, name, type, - address, uri): - - response = { - 'id': id, - 'name': name, - 'type': type, - 'address': address - } - - return helpers.add_links_to_resource(response, uri) - - @resource.resource_try_catch_block - def _list_notifications(self, tenant_id, uri, offset): - - rows = self._notifications_repo.list_notifications(tenant_id, offset) - - result = [self._build_notification_result(row, - uri) for row in rows] - - return helpers.paginate(result, uri, offset) - - @resource.resource_try_catch_block - def _list_notification(self, tenant_id, notification_id, uri): - - row = self._notifications_repo.list_notification( - tenant_id, - notification_id) - - return self._build_notification_result(row, uri) - - def _build_notification_result(self, notification_row, uri): - - result = { - u'id': notification_row['id'], - u'name': notification_row['name'], - u'type': notification_row['type'], - u'address': notification_row['address'] - } - - helpers.add_links_to_resource(result, uri) - - return result - - @resource.resource_try_catch_block - def _delete_notification(self, tenant_id, notification_id): - - self._notifications_repo.delete_notification(tenant_id, - notification_id) - - @resource_api.Restify('/v2.0/notification-methods', method='post') - def do_post_notification_methods(self, req, res): - helpers.validate_json_content_type(req) - helpers.validate_authorization(req, self._default_authorized_roles) - notification = helpers.read_http_resource(req) - self._validate_notification(notification) - tenant_id = helpers.get_tenant_id(req) - result = self._create_notification(tenant_id, notification, req.uri) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_201 - - @resource_api.Restify('/v2.0/notification-methods', method='get') - def do_get_notification_methods(self, req, res): - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - offset = helpers.normalize_offset(helpers.get_query_param(req, - 'offset')) - result = self._list_notifications(tenant_id, req.uri, offset) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/notification-methods/{id}', method='delete') - def do_delete_notification_methods(self, req, res, id): - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - self._delete_notification(tenant_id, id) - res.status = falcon.HTTP_204 - - @resource_api.Restify('/v2.0/notification-methods/{id}', method='get') - def do_get_notification_method(self, req, res, id): - helpers.validate_authorization(req, self._default_authorized_roles) - tenant_id = helpers.get_tenant_id(req) - result = self._list_notification(tenant_id, id, req.uri) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200 - - @resource_api.Restify('/v2.0/notification-methods/{id}', method='put') - def do_put_notification_methods(self, req, res, id): - helpers.validate_json_content_type(req) - helpers.validate_authorization(req, self._default_authorized_roles) - notification = helpers.read_http_resource(req) - self._validate_notification(notification) - tenant_id = helpers.get_tenant_id(req) - result = self._update_notification(id, tenant_id, notification, - req.uri) - res.body = helpers.dumpit_utf8(result) - res.status = falcon.HTTP_200