392 lines
17 KiB
Python
392 lines
17 KiB
Python
# (C) Copyright 2014, 2016 Hewlett Packard Enterprise Development LP
|
|
#
|
|
# 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 monasca_common.simport import simport
|
|
from oslo_config import cfg
|
|
from oslo_log import log
|
|
|
|
from monasca_api.api import metrics_api_v2
|
|
from monasca_api.common.messaging import (
|
|
exceptions as message_queue_exceptions)
|
|
from monasca_api.common.messaging.message_formats import (
|
|
metrics as metrics_message)
|
|
from monasca_api.v2.common.exceptions import HTTPUnprocessableEntityError
|
|
from monasca_api.v2.common import validation
|
|
from monasca_api.v2.reference import helpers
|
|
from monasca_api.v2.reference import resource
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
def get_merge_metrics_flag(req):
|
|
'''Return the value of the optional metrics_flag
|
|
|
|
Returns False if merge_metrics parameter is not supplied or is not a
|
|
string that evaluates to True, otherwise True
|
|
'''
|
|
|
|
merge_metrics_flag = helpers.get_query_param(req,
|
|
'merge_metrics',
|
|
False,
|
|
False)
|
|
if merge_metrics_flag is not False:
|
|
return helpers.str_2_bool(merge_metrics_flag)
|
|
else:
|
|
return False
|
|
|
|
|
|
class Metrics(metrics_api_v2.MetricsV2API):
|
|
def __init__(self):
|
|
try:
|
|
super(Metrics, self).__init__()
|
|
self._region = cfg.CONF.region
|
|
self._delegate_authorized_roles = (
|
|
cfg.CONF.security.delegate_authorized_roles)
|
|
self._get_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.read_only_authorized_roles)
|
|
self._post_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.agent_authorized_roles)
|
|
self._message_queue = simport.load(cfg.CONF.messaging.driver)(
|
|
'metrics')
|
|
self._metrics_repo = simport.load(
|
|
cfg.CONF.repositories.metrics_driver)()
|
|
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
|
ex.message)
|
|
|
|
def _validate_metrics(self, metrics):
|
|
|
|
try:
|
|
if isinstance(metrics, list):
|
|
for metric in metrics:
|
|
self._validate_single_metric(metric)
|
|
else:
|
|
self._validate_single_metric(metrics)
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
|
|
|
|
def _validate_single_metric(self, metric):
|
|
validation.metric_name(metric['name'])
|
|
assert isinstance(metric['timestamp'], (int, float)), "Timestamp must be a number"
|
|
assert isinstance(metric['value'], (int, long, float)), "Value must be a number"
|
|
if "dimensions" in metric:
|
|
for dimension_key in metric['dimensions']:
|
|
validation.dimension_key(dimension_key)
|
|
validation.dimension_value(metric['dimensions'][dimension_key])
|
|
if "value_meta" in metric:
|
|
validation.validate_value_meta(metric['value_meta'])
|
|
|
|
def _send_metrics(self, metrics):
|
|
try:
|
|
self._message_queue.send_message_batch(metrics)
|
|
except message_queue_exceptions.MessageQueueException as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPServiceUnavailable('Service unavailable',
|
|
ex.message, 60)
|
|
|
|
@resource.resource_try_catch_block
|
|
def _list_metrics(self, tenant_id, name, dimensions, req_uri, offset,
|
|
limit, start_timestamp, end_timestamp):
|
|
|
|
result = self._metrics_repo.list_metrics(tenant_id,
|
|
self._region,
|
|
name,
|
|
dimensions,
|
|
offset, limit,
|
|
start_timestamp,
|
|
end_timestamp)
|
|
|
|
return helpers.paginate(result, req_uri, limit)
|
|
|
|
def on_post(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 = metrics_message.transform(
|
|
metrics, tenant_id, self._region)
|
|
self._send_metrics(transformed_metrics)
|
|
res.status = falcon.HTTP_204
|
|
|
|
def on_get(self, req, res):
|
|
helpers.validate_authorization(req, self._get_metrics_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.get_query_param(req, 'offset')
|
|
limit = helpers.get_limit(req)
|
|
start_timestamp = helpers.get_query_starttime_timestamp(req, False)
|
|
end_timestamp = helpers.get_query_endtime_timestamp(req, False)
|
|
helpers.validate_start_end_timestamps(start_timestamp, end_timestamp)
|
|
result = self._list_metrics(tenant_id, name, dimensions,
|
|
req.uri, offset, limit,
|
|
start_timestamp, end_timestamp)
|
|
res.body = helpers.dumpit_utf8(result)
|
|
res.status = falcon.HTTP_200
|
|
|
|
|
|
class MetricsMeasurements(metrics_api_v2.MetricsMeasurementsV2API):
|
|
def __init__(self):
|
|
try:
|
|
super(MetricsMeasurements, self).__init__()
|
|
self._region = cfg.CONF.region
|
|
self._delegate_authorized_roles = (
|
|
cfg.CONF.security.delegate_authorized_roles)
|
|
self._get_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.read_only_authorized_roles)
|
|
self._post_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.agent_authorized_roles)
|
|
self._metrics_repo = simport.load(
|
|
cfg.CONF.repositories.metrics_driver)()
|
|
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
|
ex.message)
|
|
|
|
def on_get(self, req, res):
|
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
|
tenant_id = helpers.get_tenant_id(req)
|
|
name = helpers.get_query_name(req, True)
|
|
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)
|
|
helpers.validate_start_end_timestamps(start_timestamp, end_timestamp)
|
|
offset = helpers.get_query_param(req, 'offset')
|
|
limit = helpers.get_limit(req)
|
|
merge_metrics_flag = get_merge_metrics_flag(req)
|
|
group_by = helpers.get_query_group_by(req)
|
|
|
|
result = self._measurement_list(tenant_id, name, dimensions,
|
|
start_timestamp, end_timestamp,
|
|
req.uri, offset,
|
|
limit, merge_metrics_flag,
|
|
group_by)
|
|
|
|
res.body = helpers.dumpit_utf8(result)
|
|
res.status = falcon.HTTP_200
|
|
|
|
@resource.resource_try_catch_block
|
|
def _measurement_list(self, tenant_id, name, dimensions, start_timestamp,
|
|
end_timestamp, req_uri, offset,
|
|
limit, merge_metrics_flag, group_by):
|
|
|
|
result = self._metrics_repo.measurement_list(tenant_id,
|
|
self._region,
|
|
name,
|
|
dimensions,
|
|
start_timestamp,
|
|
end_timestamp,
|
|
offset,
|
|
limit,
|
|
merge_metrics_flag,
|
|
group_by)
|
|
|
|
return helpers.paginate_measurements(result, req_uri, limit)
|
|
|
|
|
|
class MetricsStatistics(metrics_api_v2.MetricsStatisticsV2API):
|
|
def __init__(self):
|
|
try:
|
|
super(MetricsStatistics, self).__init__()
|
|
self._region = cfg.CONF.region
|
|
self._get_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.read_only_authorized_roles)
|
|
self._metrics_repo = simport.load(
|
|
cfg.CONF.repositories.metrics_driver)()
|
|
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
|
ex.message)
|
|
|
|
def on_get(self, req, res):
|
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
|
tenant_id = helpers.get_tenant_id(req)
|
|
name = helpers.get_query_name(req, True)
|
|
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)
|
|
helpers.validate_start_end_timestamps(start_timestamp, end_timestamp)
|
|
statistics = helpers.get_query_statistics(req)
|
|
period = helpers.get_query_period(req)
|
|
offset = helpers.get_query_param(req, 'offset')
|
|
limit = helpers.get_limit(req)
|
|
merge_metrics_flag = get_merge_metrics_flag(req)
|
|
group_by = helpers.get_query_group_by(req)
|
|
|
|
result = self._metric_statistics(tenant_id, name, dimensions,
|
|
start_timestamp, end_timestamp,
|
|
statistics, period, req.uri,
|
|
offset, limit, merge_metrics_flag,
|
|
group_by)
|
|
|
|
res.body = helpers.dumpit_utf8(result)
|
|
res.status = falcon.HTTP_200
|
|
|
|
@resource.resource_try_catch_block
|
|
def _metric_statistics(self, tenant_id, name, dimensions, start_timestamp,
|
|
end_timestamp, statistics, period, req_uri,
|
|
offset, limit, merge_metrics_flag, group_by):
|
|
|
|
result = self._metrics_repo.metrics_statistics(tenant_id,
|
|
self._region,
|
|
name,
|
|
dimensions,
|
|
start_timestamp,
|
|
end_timestamp,
|
|
statistics, period,
|
|
offset,
|
|
limit,
|
|
merge_metrics_flag,
|
|
group_by)
|
|
|
|
return helpers.paginate_statistics(result, req_uri, limit)
|
|
|
|
|
|
class MetricsNames(metrics_api_v2.MetricsNamesV2API):
|
|
def __init__(self):
|
|
try:
|
|
super(MetricsNames, self).__init__()
|
|
self._region = cfg.CONF.region
|
|
self._get_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.read_only_authorized_roles)
|
|
self._metrics_repo = simport.load(
|
|
cfg.CONF.repositories.metrics_driver)()
|
|
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
|
ex.message)
|
|
|
|
def on_get(self, req, res):
|
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
|
tenant_id = helpers.get_tenant_id(req)
|
|
dimensions = helpers.get_query_dimensions(req)
|
|
helpers.validate_query_dimensions(dimensions)
|
|
offset = helpers.get_query_param(req, 'offset')
|
|
limit = helpers.get_limit(req)
|
|
result = self._list_metric_names(tenant_id, dimensions,
|
|
req.uri, offset, limit)
|
|
res.body = helpers.dumpit_utf8(result)
|
|
res.status = falcon.HTTP_200
|
|
|
|
@resource.resource_try_catch_block
|
|
def _list_metric_names(self, tenant_id, dimensions, req_uri, offset,
|
|
limit):
|
|
|
|
result = self._metrics_repo.list_metric_names(tenant_id,
|
|
self._region,
|
|
dimensions)
|
|
|
|
return helpers.paginate_with_no_id(result, req_uri, offset, limit)
|
|
|
|
|
|
class DimensionValues(metrics_api_v2.DimensionValuesV2API):
|
|
def __init__(self):
|
|
try:
|
|
super(DimensionValues, self).__init__()
|
|
self._region = cfg.CONF.region
|
|
self._get_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.read_only_authorized_roles)
|
|
self._metrics_repo = simport.load(
|
|
cfg.CONF.repositories.metrics_driver)()
|
|
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
|
ex.message)
|
|
|
|
def on_get(self, req, res):
|
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
|
tenant_id = helpers.get_tenant_id(req)
|
|
metric_name = helpers.get_query_param(req, 'metric_name')
|
|
dimension_name = helpers.get_query_param(req, 'dimension_name',
|
|
required=True)
|
|
offset = helpers.get_query_param(req, 'offset')
|
|
limit = helpers.get_limit(req)
|
|
result = self._dimension_values(tenant_id, req.uri, metric_name,
|
|
dimension_name, offset, limit)
|
|
res.body = helpers.dumpit_utf8(result)
|
|
res.status = falcon.HTTP_200
|
|
|
|
@resource.resource_try_catch_block
|
|
def _dimension_values(self, tenant_id, req_uri, metric_name,
|
|
dimension_name, offset, limit):
|
|
|
|
result = self._metrics_repo.list_dimension_values(tenant_id,
|
|
self._region,
|
|
metric_name,
|
|
dimension_name)
|
|
|
|
return helpers.paginate_with_no_id(result, req_uri, offset, limit)
|
|
|
|
|
|
class DimensionNames(metrics_api_v2.DimensionNamesV2API):
|
|
def __init__(self):
|
|
try:
|
|
super(DimensionNames, self).__init__()
|
|
self._region = cfg.CONF.region
|
|
self._get_metrics_authorized_roles = (
|
|
cfg.CONF.security.default_authorized_roles +
|
|
cfg.CONF.security.read_only_authorized_roles)
|
|
self._metrics_repo = simport.load(
|
|
cfg.CONF.repositories.metrics_driver)()
|
|
|
|
except Exception as ex:
|
|
LOG.exception(ex)
|
|
raise falcon.HTTPInternalServerError('Service unavailable',
|
|
ex.message)
|
|
|
|
def on_get(self, req, res):
|
|
helpers.validate_authorization(req, self._get_metrics_authorized_roles)
|
|
tenant_id = helpers.get_tenant_id(req)
|
|
metric_name = helpers.get_query_param(req, 'metric_name')
|
|
offset = helpers.get_query_param(req, 'offset')
|
|
limit = helpers.get_limit(req)
|
|
result = self._dimension_names(tenant_id, req.uri, metric_name,
|
|
offset, limit)
|
|
res.body = helpers.dumpit_utf8(result)
|
|
res.status = falcon.HTTP_200
|
|
|
|
@resource.resource_try_catch_block
|
|
def _dimension_names(self, tenant_id, req_uri, metric_name, offset, limit):
|
|
|
|
result = self._metrics_repo.list_dimension_names(tenant_id,
|
|
self._region,
|
|
metric_name)
|
|
|
|
return helpers.paginate_with_no_id(result, req_uri, offset, limit)
|