diff --git a/monasca_api/common/messaging/message_formats/metrics.py b/monasca_api/common/messaging/message_formats/metrics.py index 9b9f4d341..a718fb674 100644 --- a/monasca_api/common/messaging/message_formats/metrics.py +++ b/monasca_api/common/messaging/message_formats/metrics.py @@ -12,10 +12,10 @@ # License for the specific language governing permissions and limitations # under the License. -import json - from oslo_utils import timeutils +from monasca_common.rest import utils as rest_utils + def transform(metrics, tenant_id, region): transformed_metric = {'metric': {}, @@ -26,8 +26,8 @@ def transform(metrics, tenant_id, region): transformed_metrics = [] for metric in metrics: transformed_metric['metric'] = metric - transformed_metrics.append(json.dumps(transformed_metric)) + transformed_metrics.append(rest_utils.as_json(transformed_metric)) return transformed_metrics else: transformed_metric['metric'] = metrics - return [json.dumps(transformed_metric)] + return [rest_utils.as_json(transformed_metric)] diff --git a/monasca_api/common/repositories/cassandra/metrics_repository.py b/monasca_api/common/repositories/cassandra/metrics_repository.py index b4d228ecc..0aee9a428 100644 --- a/monasca_api/common/repositories/cassandra/metrics_repository.py +++ b/monasca_api/common/repositories/cassandra/metrics_repository.py @@ -16,7 +16,6 @@ import binascii from datetime import datetime from datetime import timedelta import itertools -import json import urllib from cassandra.cluster import Cluster @@ -25,6 +24,8 @@ from oslo_config import cfg from oslo_log import log from oslo_utils import timeutils +from monasca_common.rest import utils as rest_utils + from monasca_api.common.repositories import exceptions from monasca_api.common.repositories import metrics_repository @@ -233,7 +234,7 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository): measurements_list = ( [[self._isotime_msec(time_stamp), value, - json.loads(value_meta) if value_meta else {}] + rest_utils.from_json(value_meta) if value_meta else {}] for (time_stamp, value, value_meta) in rows]) measurement = {u'name': name, @@ -621,12 +622,12 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository): alarm = {u'timestamp': self._isotime_msec(time_stamp), u'alarm_id': alarm_id, - u'metrics': json.loads(metrics), + u'metrics': rest_utils.from_json(metrics), u'new_state': new_state, u'old_state': old_state, u'reason': reason, u'reason_data': reason_data, - u'sub_alarms': json.loads(sub_alarms), + u'sub_alarms': rest_utils.from_json(sub_alarms), u'id': str(self._get_millis_from_timestamp(time_stamp) ).decode('utf8')} diff --git a/monasca_api/common/repositories/influxdb/metrics_repository.py b/monasca_api/common/repositories/influxdb/metrics_repository.py index d55d875c9..3d4b26e5a 100644 --- a/monasca_api/common/repositories/influxdb/metrics_repository.py +++ b/monasca_api/common/repositories/influxdb/metrics_repository.py @@ -15,7 +15,6 @@ from datetime import datetime from datetime import timedelta from distutils import version -import json from influxdb import client from influxdb.exceptions import InfluxDBClientError @@ -23,6 +22,8 @@ from oslo_config import cfg from oslo_log import log from oslo_utils import timeutils +from monasca_common.rest import utils as rest_utils + from monasca_api.common.repositories import exceptions from monasca_api.common.repositories import metrics_repository @@ -556,7 +557,7 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository): measurements_list = [] for point in serie['values']: - value_meta = json.loads(point[2]) if point[2] else {} + value_meta = rest_utils.from_json(point[2]) if point[2] else {} timestamp = point[0][:19] + '.' + point[0][20:-1].ljust(3, '0') + 'Z' measurements_list.append([timestamp, @@ -840,12 +841,12 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository): for point in result.raw['series'][0]['values']: alarm_point = {u'timestamp': point[0], u'alarm_id': point[1], - u'metrics': json.loads(point[2]), + u'metrics': rest_utils.from_json(point[2]), u'new_state': point[3], u'old_state': point[4], u'reason': point[5], u'reason_data': point[6], - u'sub_alarms': json.loads(point[7]), + u'sub_alarms': rest_utils.from_json(point[7]), u'id': str(self._get_millis_from_timestamp( timeutils.parse_isotime(point[0])))} diff --git a/monasca_api/v2/reference/alarm_definitions.py b/monasca_api/v2/reference/alarm_definitions.py index f2db05e35..d9707736b 100644 --- a/monasca_api/v2/reference/alarm_definitions.py +++ b/monasca_api/v2/reference/alarm_definitions.py @@ -58,7 +58,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, def on_post(self, req, res): helpers.validate_authorization(req, self._default_authorized_roles) - alarm_definition = helpers.read_json_msg_body(req) + alarm_definition = helpers.from_json(req) self._validate_alarm_definition(alarm_definition) @@ -80,7 +80,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, ok_actions) helpers.add_links_to_resource(result, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_201 @resource.resource_try_catch_block @@ -115,7 +115,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, req.uri, sort_by, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 else: @@ -127,7 +127,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, helpers.add_links_to_resource(result, re.sub('/' + alarm_definition_id, '', req.uri)) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block @@ -135,7 +135,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, helpers.validate_authorization(req, self._default_authorized_roles) - alarm_definition = helpers.read_json_msg_body(req) + alarm_definition = helpers.from_json(req) self._validate_alarm_definition(alarm_definition, require_all=True) @@ -165,7 +165,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, patch=False) helpers.add_links_to_resource(result, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block @@ -173,7 +173,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, helpers.validate_authorization(req, self._default_authorized_roles) - alarm_definition = helpers.read_json_msg_body(req) + alarm_definition = helpers.from_json(req) # Optional args name = get_query_alarm_definition_name(alarm_definition, @@ -210,7 +210,7 @@ class AlarmDefinitions(alarm_definitions_api_v2.AlarmDefinitionsV2API, patch=True) helpers.add_links_to_resource(result, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block diff --git a/monasca_api/v2/reference/alarming.py b/monasca_api/v2/reference/alarming.py index b3c4c1342..0ea08a2a9 100644 --- a/monasca_api/v2/reference/alarming.py +++ b/monasca_api/v2/reference/alarming.py @@ -174,8 +174,7 @@ class Alarming(object): def send_event(self, message_queue, event_msg): try: - message_queue.send_message( - helpers.dumpit_utf8(event_msg)) + message_queue.send_message(helpers.to_json(event_msg)) except message_queue_exceptions.MessageQueueException as ex: LOG.exception(ex) raise falcon.HTTPInternalServerError( diff --git a/monasca_api/v2/reference/alarms.py b/monasca_api/v2/reference/alarms.py index b9d7874a6..a040da956 100644 --- a/monasca_api/v2/reference/alarms.py +++ b/monasca_api/v2/reference/alarms.py @@ -54,7 +54,7 @@ class Alarms(alarms_api_v2.AlarmsV2API, helpers.validate_authorization(req, self._default_authorized_roles) - alarm = helpers.read_http_resource(req) + alarm = helpers.from_json(req) schema_alarm.validate(alarm) # Validator makes state optional, so check it here @@ -73,7 +73,7 @@ class Alarms(alarms_api_v2.AlarmsV2API, result = self._alarm_show(req.uri, req.project_id, alarm_id) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block @@ -81,7 +81,7 @@ class Alarms(alarms_api_v2.AlarmsV2API, helpers.validate_authorization(req, self._default_authorized_roles) - alarm = helpers.read_http_resource(req) + alarm = helpers.from_json(req) schema_alarm.validate(alarm) old_alarm = self._alarms_repo.get_alarm(req.project_id, alarm_id)[0] @@ -99,7 +99,7 @@ class Alarms(alarms_api_v2.AlarmsV2API, result = self._alarm_show(req.uri, req.project_id, alarm_id) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block @@ -150,13 +150,13 @@ class Alarms(alarms_api_v2.AlarmsV2API, query_parms, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 else: result = self._alarm_show(req.uri, req.project_id, alarm_id) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _alarm_update(self, tenant_id, alarm_id, new_state, lifecycle_state, @@ -397,7 +397,7 @@ class AlarmsCount(alarms_api_v2.AlarmsCountV2API, alarming.Alarming): result = self._alarms_count(req.uri, req.project_id, query_parms, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _alarms_count(self, req_uri, tenant_id, query_parms, offset, limit): @@ -484,7 +484,7 @@ class AlarmsStateHistory(alarms_api_v2.AlarmsStateHistoryV2API, end_timestamp, dimensions, req.uri, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 else: @@ -495,7 +495,7 @@ class AlarmsStateHistory(alarms_api_v2.AlarmsStateHistoryV2API, req.uri, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _alarm_history_list(self, tenant_id, start_timestamp, diff --git a/monasca_api/v2/reference/helpers.py b/monasca_api/v2/reference/helpers.py index d5309fa71..bbb535a2d 100644 --- a/monasca_api/v2/reference/helpers.py +++ b/monasca_api/v2/reference/helpers.py @@ -14,22 +14,22 @@ # under the License. import datetime -import json import falcon -from monasca_common.validation import metrics as metric_validation from oslo_log import log from oslo_utils import timeutils -import simplejson import six import six.moves.urllib.parse as urlparse +from monasca_common.rest import utils as rest_utils +from monasca_common.validation import metrics as metric_validation + from monasca_api.v2.common.exceptions import HTTPUnprocessableEntityError LOG = log.getLogger(__name__) -def read_json_msg_body(req): +def from_json(req): """Read the json_msg from the http request body and return them as JSON. :param req: HTTP request object. @@ -38,14 +38,29 @@ def read_json_msg_body(req): """ try: msg = req.stream.read() - json_msg = json.loads(msg) - return json_msg - except ValueError as ex: - LOG.debug(ex) + return rest_utils.from_json(msg) + except Exception as ex: + LOG.exception(ex) raise falcon.HTTPBadRequest('Bad request', 'Request body is not valid JSON') +def to_json(data): + """Converts data to JSON string. + + :param dict data: data to be transformed to JSON + :return: JSON string + :rtype: str + :raises: Exception + """ + try: + # NOTE(trebskit) ensure_ascii => UTF-8 + return rest_utils.as_json(data, ensure_ascii=False) + except Exception as ex: + LOG.exception(ex) + raise + + def validate_json_content_type(req): if req.content_type not in ['application/json']: raise falcon.HTTPBadRequest('Bad request', 'Bad content type. Must be ' @@ -718,20 +733,6 @@ def add_links_to_resource_list(resourcelist, uri): return resourcelist -def read_http_resource(req): - """Read from http request and return json. - - :param req: the http request. - """ - try: - msg = req.stream.read() - json_msg = simplejson.loads(msg) - return json_msg - except ValueError as ex: - LOG.debug(ex) - raise HTTPUnprocessableEntityError('Unprocessable Entity', 'Request body is not valid JSON') - - def raise_not_found_exception(resource_name, resource_id, tenant_id): """Provides exception for not found requests (update, delete, list). @@ -748,9 +749,5 @@ def raise_not_found_exception(resource_name, resource_id, tenant_id): code=404) -def dumpit_utf8(thingy): - return json.dumps(thingy, ensure_ascii=False).encode('utf8') - - def str_2_bool(s): return s.lower() in ("true") diff --git a/monasca_api/v2/reference/metrics.py b/monasca_api/v2/reference/metrics.py index 44ae82559..ec3ec6e08 100644 --- a/monasca_api/v2/reference/metrics.py +++ b/monasca_api/v2/reference/metrics.py @@ -96,7 +96,7 @@ class Metrics(metrics_api_v2.MetricsV2API): helpers.validate_json_content_type(req) helpers.validate_authorization(req, self._post_metrics_authorized_roles) - metrics = helpers.read_http_resource(req) + metrics = helpers.from_json(req) try: metric_validation.validate(metrics) except Exception as ex: @@ -129,7 +129,7 @@ class Metrics(metrics_api_v2.MetricsV2API): dimensions, req.uri, offset, req.limit, start_timestamp, end_timestamp) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @@ -177,7 +177,7 @@ class MetricsMeasurements(metrics_api_v2.MetricsMeasurementsV2API): req.limit, merge_metrics_flag, group_by) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _measurement_list(self, tenant_id, name, dimensions, start_timestamp, @@ -241,7 +241,7 @@ class MetricsStatistics(metrics_api_v2.MetricsStatisticsV2API): offset, req.limit, merge_metrics_flag, group_by) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _metric_statistics(self, tenant_id, name, dimensions, start_timestamp, @@ -292,7 +292,7 @@ class MetricsNames(metrics_api_v2.MetricsNamesV2API): offset = helpers.get_query_param(req, 'offset') result = self._list_metric_names(tenant_id, dimensions, req.uri, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _list_metric_names(self, tenant_id, dimensions, req_uri, offset, @@ -335,7 +335,7 @@ class DimensionValues(metrics_api_v2.DimensionValuesV2API): offset = helpers.get_query_param(req, 'offset') result = self._dimension_values(tenant_id, req.uri, metric_name, dimension_name, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _dimension_values(self, tenant_id, req_uri, metric_name, @@ -377,7 +377,7 @@ class DimensionNames(metrics_api_v2.DimensionNamesV2API): offset = helpers.get_query_param(req, 'offset') result = self._dimension_names(tenant_id, req.uri, metric_name, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 def _dimension_names(self, tenant_id, req_uri, metric_name, offset, limit): diff --git a/monasca_api/v2/reference/notifications.py b/monasca_api/v2/reference/notifications.py index 52a49b2aa..e3f057bfb 100644 --- a/monasca_api/v2/reference/notifications.py +++ b/monasca_api/v2/reference/notifications.py @@ -196,10 +196,10 @@ class Notifications(notifications_api_v2.NotificationsV2API): def on_post(self, req, res): helpers.validate_json_content_type(req) helpers.validate_authorization(req, self._default_authorized_roles) - notification = helpers.read_http_resource(req) + notification = helpers.from_json(req) self._parse_and_validate_notification(notification) result = self._create_notification(req.project_id, notification, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_201 @resource.resource_try_catch_block @@ -228,7 +228,7 @@ class Notifications(notifications_api_v2.NotificationsV2API): result = self._list_notifications(req.project_id, req.uri, sort_by, offset, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 else: helpers.validate_authorization(req, @@ -236,7 +236,7 @@ class Notifications(notifications_api_v2.NotificationsV2API): result = self._list_notification(req.project_id, notification_method_id, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block @@ -249,21 +249,21 @@ class Notifications(notifications_api_v2.NotificationsV2API): def on_put(self, req, res, notification_method_id): helpers.validate_json_content_type(req) helpers.validate_authorization(req, self._default_authorized_roles) - notification = helpers.read_http_resource(req) + notification = helpers.from_json(req) self._parse_and_validate_notification(notification, require_all=True) result = self._update_notification(notification_method_id, req.project_id, notification, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 @resource.resource_try_catch_block def on_patch(self, req, res, notification_method_id): helpers.validate_json_content_type(req) helpers.validate_authorization(req, self._default_authorized_roles) - notification = helpers.read_http_resource(req) + notification = helpers.from_json(req) self._patch_get_notification(req.project_id, notification_method_id, notification) self._parse_and_validate_notification(notification, require_all=True) result = self._update_notification(notification_method_id, req.project_id, notification, req.uri) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 diff --git a/monasca_api/v2/reference/notificationstype.py b/monasca_api/v2/reference/notificationstype.py index f16611a44..55bf7d278 100644 --- a/monasca_api/v2/reference/notificationstype.py +++ b/monasca_api/v2/reference/notificationstype.py @@ -39,5 +39,5 @@ class NotificationsType(notificationstype_api_v2.NotificationsTypeV2API): # are not that many rows result = self._list_notifications(req.uri, req.limit) - res.body = helpers.dumpit_utf8(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 diff --git a/monasca_api/v2/reference/version_2_0.py b/monasca_api/v2/reference/version_2_0.py index f6f96ab1d..e4473caec 100644 --- a/monasca_api/v2/reference/version_2_0.py +++ b/monasca_api/v2/reference/version_2_0.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -import json +from monasca_api.v2.reference import helpers class Version2(object): @@ -29,4 +29,4 @@ class Version2(object): 'status': 'CURRENT', 'updated': "2013-03-06T00:00:00.000Z" } - res.body = json.dumps(result) + res.body = helpers.to_json(result) diff --git a/monasca_api/v2/reference/versions.py b/monasca_api/v2/reference/versions.py index c4d40fe28..85961da57 100644 --- a/monasca_api/v2/reference/versions.py +++ b/monasca_api/v2/reference/versions.py @@ -12,12 +12,11 @@ # License for the specific language governing permissions and limitations # under the License. -import json - import falcon from monasca_api.api import versions_api from monasca_api.v2.common.exceptions import HTTPUnprocessableEntityError +from monasca_api.v2.reference import helpers VERSIONS = { 'v2.0': { @@ -49,13 +48,13 @@ class Versions(versions_api.VersionsAPI): VERSIONS[version]['links'][0]['href'] = ( req.uri.decode('utf8') + version) result['elements'].append(VERSIONS[version]) - res.body = json.dumps(result) + res.body = helpers.to_json(result) res.status = falcon.HTTP_200 else: if version_id in VERSIONS: VERSIONS[version_id]['links'][0]['href'] = ( req.uri.decode('utf8')) - res.body = json.dumps(VERSIONS[version_id]) + res.body = helpers.to_json(VERSIONS[version_id]) res.status = falcon.HTTP_200 else: raise HTTPUnprocessableEntityError('Invalid version', diff --git a/requirements.txt b/requirements.txt index 4db01092b..577e67dc8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,6 +19,5 @@ six>=1.9.0 # MIT pyparsing>=2.1.0 # MIT voluptuous>=0.8.9 # BSD License eventlet!=0.18.3,>=0.18.2 # MIT -simplejson>=2.2.0 # MIT monasca-common>=1.4.0 # Apache-2.0 SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.0.10 # MIT