def on_put(self, req, res, alarm_id): helpers.validate_authorization(req, self._default_authorized_roles) tenant_id = helpers.get_tenant_id(req) alarm = helpers.read_http_resource(req) schema_alarm.validate(alarm) # Validator makes state optional, so check it here if 'state' not in alarm or not alarm['state']: raise HTTPUnprocessableEntityError('Unprocessable Entity', "Field 'state' is required") if 'lifecycle_state' not in alarm or not alarm['lifecycle_state']: raise HTTPUnprocessableEntityError( 'Unprocessable Entity', "Field 'lifecycle_state' is required") if 'link' not in alarm or not alarm['link']: raise HTTPUnprocessableEntityError('Unprocessable Entity', "Field 'link' is required") self._alarm_update(tenant_id, alarm_id, alarm['state'], alarm['lifecycle_state'], alarm['link']) result = self._alarm_show(req.uri, tenant_id, alarm_id) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200
def on_put(self, req, res, alarm_id): helpers.validate_authorization(req, ['api:alarms:put']) alarm = helpers.from_json(req) schema_alarm.validate(alarm) # Validator makes state optional, so check it here if 'state' not in alarm or not alarm['state']: raise HTTPUnprocessableEntityError('Unprocessable Entity', "Field 'state' is required") if 'lifecycle_state' not in alarm or not alarm['lifecycle_state']: raise HTTPUnprocessableEntityError( 'Unprocessable Entity', "Field 'lifecycle_state' is required") if 'link' not in alarm or not alarm['link']: raise HTTPUnprocessableEntityError('Unprocessable Entity', "Field 'link' is required") self._alarm_update(req.project_id, alarm_id, alarm['state'], alarm['lifecycle_state'], alarm['link']) result = self._alarm_show(req.uri, req.project_id, alarm_id) res.body = helpers.to_json(result) res.status = falcon.HTTP_200
def on_get(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) if 'state' in query_parms: validation.validate_alarm_state(query_parms['state']) if 'severity' in query_parms: validation.validate_alarm_definition_severity(query_parms['severity']) if 'group_by' in query_parms: if not isinstance(query_parms['group_by'], list): query_parms['group_by'] = [query_parms['group_by']] self._validate_group_by(query_parms['group_by']) # ensure metric_dimensions is a list if 'metric_dimensions' in query_parms and isinstance(query_parms['metric_dimensions'], str): query_parms['metric_dimensions'] = query_parms['metric_dimensions'].split(',') offset = helpers.get_query_param(req, 'offset') if offset is not None: try: offset = int(offset) except Exception: raise HTTPUnprocessableEntityError("Unprocessable Entity", "Offset must be a valid integer, was {}".format(offset)) limit = helpers.get_limit(req) result = self._alarms_count(req.uri, tenant_id, query_parms, offset, limit) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200
def on_get(self, req, res): helpers.validate_authorization(req, self._get_alarms_authorized_roles) query_parms = falcon.uri.parse_query_string(req.query_string) if 'state' in query_parms: validation.validate_alarm_state(query_parms['state']) query_parms['state'] = query_parms['state'].upper() if 'severity' in query_parms: validation.validate_severity_query(query_parms['severity']) query_parms['severity'] = query_parms['severity'].upper() if 'group_by' in query_parms: if not isinstance(query_parms['group_by'], list): query_parms['group_by'] = query_parms['group_by'].split(',') self._validate_group_by(query_parms['group_by']) query_parms['metric_dimensions'] = helpers.get_query_dimensions(req, 'metric_dimensions') helpers.validate_query_dimensions(query_parms['metric_dimensions']) offset = helpers.get_query_param(req, 'offset') if offset is not None: try: offset = int(offset) except Exception: raise HTTPUnprocessableEntityError("Unprocessable Entity", "Offset must be a valid integer, was {}".format(offset)) result = self._alarms_count(req.uri, req.project_id, query_parms, offset, req.limit) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200
def get_query_dimensions(req): """Gets and parses the query param dimensions. :param req: HTTP request object. :return: Returns the dimensions as a JSON object :raises falcon.HTTPBadRequest: If dimensions are malformed. """ try: params = falcon.uri.parse_query_string(req.query_string) dimensions = {} if 'dimensions' in params: dimensions_param = params['dimensions'] if isinstance(dimensions_param, basestring): dimensions_str_array = dimensions_param.split(',') elif isinstance(dimensions_param, list): dimensions_str_array = [] for sublist in dimensions_param: dimensions_str_array.extend(sublist.split(",")) else: raise Exception("Error parsing dimensions, unknown format") for dimension in dimensions_str_array: dimension_name_value = dimension.split(':') if len(dimension_name_value) == 2: dimensions[ dimension_name_value[0]] = dimension_name_value[1] elif len(dimension_name_value) == 1: dimensions[dimension_name_value[0]] = "" else: raise Exception('Dimensions are malformed') return dimensions except Exception as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
def try_it(*args, **kwargs): try: return fun(*args, **kwargs) except falcon.HTTPError: raise except exceptions.DoesNotExistException: raise falcon.HTTPNotFound except exceptions.MultipleMetricsException as ex: raise falcon.HTTPConflict("MultipleMetrics", ex.message) except exceptions.AlreadyExistsException as ex: raise falcon.HTTPConflict(ex.__class__.__name__, ex.message) except exceptions.InvalidUpdateException as ex: raise HTTPUnprocessableEntityError(ex.__class__.__name__, ex.message) except exceptions.RepositoryException as ex: LOG.exception(ex) msg = " ".join(map(str, ex.message.args)) raise falcon.HTTPInternalServerError('The repository was unable ' 'to process your request', msg) except Exception as ex: LOG.exception(ex) raise falcon.HTTPInternalServerError('Service unavailable', ex.message)
def on_get(self, req, res, notification_method_id=None): if notification_method_id is None: helpers.validate_authorization( req, self._get_notifications_authorized_roles) sort_by = helpers.get_query_param(req, 'sort_by', default_val=None) if sort_by is not None: if isinstance(sort_by, basestring): sort_by = sort_by.split(',') allowed_sort_by = { 'id', 'name', 'type', 'address', 'updated_at', 'created_at' } validation.validate_sort_by(sort_by, allowed_sort_by) offset = helpers.get_query_param(req, 'offset') if offset is not None and not isinstance(offset, int): try: offset = int(offset) except Exception: raise HTTPUnprocessableEntityError( 'Unprocessable Entity', 'Offset value {} must be an integer'.format(offset)) result = self._list_notifications(req.project_id, req.uri, sort_by, offset, req.limit) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200 else: helpers.validate_authorization( req, self._get_notifications_authorized_roles) result = self._list_notification(req.project_id, notification_method_id, req.uri) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200
def on_get(self, req, res, version_id=None): result = { 'links': [{ 'rel': 'self', 'href': req.uri.decode('utf8') }], 'elements': [] } if version_id is None: for version in VERSIONS: VERSIONS[version]['links'][0]['href'] = ( req.uri.decode('utf8') + version) result['elements'].append(VERSIONS[version]) 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 = helpers.to_json(VERSIONS[version_id]) res.status = falcon.HTTP_200 else: raise HTTPUnprocessableEntityError( 'Invalid version', 'No versions found matching ' + version_id)
def _validate_group_by(self, group_by): allowed_values = {'alarm_definition_id', 'name', 'state', 'severity', 'link', 'lifecycle_state', 'metric_name', 'dimension_name', 'dimension_value'} if not set(group_by).issubset(allowed_values): raise HTTPUnprocessableEntityError( "Unprocessable Entity", "One or more group-by values from {} are not in {}".format(group_by, allowed_values))
def on_get(self, req, res, alarm_id=None): helpers.validate_authorization(req, self._default_authorized_roles) tenant_id = helpers.get_tenant_id(req) if alarm_id is None: query_parms = falcon.uri.parse_query_string(req.query_string) if 'state' in query_parms: validation.validate_alarm_state(query_parms['state']) if 'severity' in query_parms: validation.validate_alarm_definition_severity( query_parms['severity']) if 'sort_by' in query_parms: if isinstance(query_parms['sort_by'], basestring): query_parms['sort_by'] = [query_parms['sort_by']] allowed_sort_by = { 'alarm_id', 'alarm_definition_id', 'alarm_definition_name', 'state', 'severity', 'lifecycle_state', 'link', 'state_updated_timestamp', 'updated_timestamp', 'created_timestamp' } validation.validate_sort_by(query_parms['sort_by'], allowed_sort_by) # ensure metric_dimensions is a list if 'metric_dimensions' in query_parms and isinstance( query_parms['metric_dimensions'], str): query_parms['metric_dimensions'] = query_parms[ 'metric_dimensions'].split(',') self._validate_dimensions(query_parms['metric_dimensions']) offset = helpers.get_query_param(req, 'offset') if offset is not None and not isinstance(offset, int): try: offset = int(offset) except Exception as ex: LOG.exception(ex) raise HTTPUnprocessableEntityError( "Unprocessable Entity", "Offset value {} must be an integer".format(offset)) limit = helpers.get_limit(req) result = self._alarm_list(req.uri, tenant_id, query_parms, offset, limit) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200 else: result = self._alarm_show(req.uri, tenant_id, alarm_id) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200
def validate_sort_by(sort_by_list, allowed_sort_by): for sort_by_field in sort_by_list: sort_by_values = sort_by_field.split() if len(sort_by_values) > 2: raise HTTPUnprocessableEntityError( "Unprocessable Entity", "Invalid sort_by {}".format(sort_by_field)) if sort_by_values[0] not in allowed_sort_by: raise HTTPUnprocessableEntityError( "Unprocessable Entity", "sort_by field {} must be one of [{}]".format( sort_by_values[0], ','.join(list(allowed_sort_by)))) if len(sort_by_values) > 1 and sort_by_values[1] not in [ 'asc', 'desc' ]: raise HTTPUnprocessableEntityError( "Unprocessable Entity", "sort_by value {} must be 'asc' or 'desc'".format( sort_by_values[1]))
def validate_query_dimensions(dimensions): """Validates the query param dimensions. :param dimensions: Query param dimensions. :raises falcon.HTTPBadRequest: If dimensions are not valid. """ try: dimensions_schema.validate(dimensions) except schemas_exceptions.ValidationException as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
def get_query_alarm_definition_severity(alarm_definition, return_none=False): if 'severity' in alarm_definition: severity = encodeutils.safe_decode(alarm_definition['severity'], 'utf-8').upper() if severity not in ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']: raise HTTPUnprocessableEntityError('Unprocessable Entity', 'Invalid severity') return severity else: if return_none: return None else: return 'LOW'
def _validate_alarm_definition(self, alarm_definition, require_all=False): try: schema_alarms.validate(alarm_definition, require_all=require_all) if 'match_by' in alarm_definition: for name in alarm_definition['match_by']: metric_validation.validate_dimension_key(name) except Exception as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', str(ex))
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_query_name(name): """Validates the query param name. :param name: Query param name. :raises falcon.HTTPBadRequest: If name is not valid. """ try: metric_name_schema.validate(name) except schemas_exceptions.ValidationException as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
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 on_get(self, req, res, alarm_definition_id=None): if alarm_definition_id is None: helpers.validate_authorization( req, self._get_alarmdefs_authorized_roles) tenant_id = helpers.get_tenant_id(req) name = helpers.get_query_name(req) dimensions = helpers.get_query_dimensions(req) severity = helpers.get_query_param(req, "severity", default_val=None) if severity is not None: validation.validate_severity_query(severity) sort_by = helpers.get_query_param(req, 'sort_by', default_val=None) if sort_by is not None: if isinstance(sort_by, basestring): sort_by = sort_by.split(',') allowed_sort_by = { 'id', 'name', 'severity', 'updated_at', 'created_at' } validation.validate_sort_by(sort_by, allowed_sort_by) offset = helpers.get_query_param(req, 'offset') if offset is not None and not isinstance(offset, int): try: offset = int(offset) except Exception: raise HTTPUnprocessableEntityError( 'Unprocessable Entity', 'Offset value {} must be an integer'.format(offset)) limit = helpers.get_limit(req) result = self._alarm_definition_list(tenant_id, name, dimensions, severity, req.uri, sort_by, offset, limit) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200 else: helpers.validate_authorization( req, self._get_alarmdefs_authorized_roles) tenant_id = helpers.get_tenant_id(req) result = self._alarm_definition_show(tenant_id, alarm_definition_id) helpers.add_links_to_resource( result, re.sub('/' + alarm_definition_id, '', req.uri)) res.body = helpers.dumpit_utf8(result) res.status = falcon.HTTP_200
def validate_query_name(name): """Validates the query param name. :param name: Query param name. :raises falcon.HTTPBadRequest: If name is not valid. """ if not name: return try: metric_validation.validate_name(name) except Exception as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', str(ex))
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 HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
def get_query_group_by(req): try: params = falcon.uri.parse_query_string(req.query_string) if 'group_by' in params: group_by = params['group_by'] if not isinstance(group_by, list): group_by = [group_by] return group_by else: return None except Exception as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
def get_query_endtime_timestamp(req, required=True): try: params = falcon.uri.parse_query_string(req.query_string) if 'end_time' in params: return _convert_time_string(params['end_time']) else: if required: raise Exception("Missing end time") else: return None except Exception as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', 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 HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
def on_get(self, req, res, alarm_id=None): helpers.validate_authorization(req, ['api:alarms:get']) if alarm_id is None: query_parms = falcon.uri.parse_query_string(req.query_string) if 'state' in query_parms: validation.validate_alarm_state(query_parms['state']) query_parms['state'] = query_parms['state'].upper() if 'severity' in query_parms: validation.validate_severity_query(query_parms['severity']) query_parms['severity'] = query_parms['severity'].upper() if 'sort_by' in query_parms: if isinstance(query_parms['sort_by'], six.string_types): query_parms['sort_by'] = query_parms['sort_by'].split(',') allowed_sort_by = { 'alarm_id', 'alarm_definition_id', 'alarm_definition_name', 'state', 'severity', 'lifecycle_state', 'link', 'state_updated_timestamp', 'updated_timestamp', 'created_timestamp' } validation.validate_sort_by(query_parms['sort_by'], allowed_sort_by) query_parms['metric_dimensions'] = helpers.get_query_dimensions( req, 'metric_dimensions') helpers.validate_query_dimensions(query_parms['metric_dimensions']) offset = helpers.get_query_param(req, 'offset') if offset is not None and not isinstance(offset, int): try: offset = int(offset) except Exception as ex: LOG.exception(ex) raise HTTPUnprocessableEntityError( "Unprocessable Entity", "Offset value {} must be an integer".format(offset)) result = self._alarm_list(req.uri, req.project_id, query_parms, offset, req.limit) 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.to_json(result) res.status = falcon.HTTP_200
def _alarm_definition_create(self, tenant_id, name, expression, description, severity, match_by, alarm_actions, undetermined_actions, ok_actions): try: sub_expr_list = ( monasca_api.expression_parser.alarm_expr_parser. AlarmExprParser(expression).sub_expr_list) except (pyparsing.ParseException, pyparsing.ParseFatalException) as ex: LOG.exception(ex) title = u"Invalid alarm expression" msg = u"parser failed on expression '{}' at column {}: {}".format( encodeutils.safe_decode(expression, 'utf-8'), encodeutils.safe_decode(str(ex.column), 'utf-8'), encodeutils.safe_decode(ex.msg, 'utf-8')) raise HTTPUnprocessableEntityError(title, msg) self._validate_name_not_conflicting(tenant_id, name) 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': True, u'undetermined_actions': undetermined_actions, u'expression': expression, u'id': alarm_definition_id, u'deterministic': is_definition_deterministic(expression), u'name': name}) return result
def _validate_dimensions(dimensions): try: assert isinstance(dimensions, list) for dimension in dimensions: name_value = dimension.split(':') validation.dimension_key(name_value[0]) if len(name_value) > 1: if '|' in name_value[1]: values = name_value[1].split('|') for value in values: validation.dimension_value(value) else: validation.dimension_value(name_value[1]) except Exception as e: raise HTTPUnprocessableEntityError("Unprocessable Entity", e.message)
def on_post(self, req, res): helpers.validate_json_content_type(req) helpers.validate_authorization(req, ['api:metrics:post']) metrics = helpers.from_json(req) try: metric_validation.validate(metrics) except Exception as ex: LOG.exception(ex) raise HTTPUnprocessableEntityError("Unprocessable Entity", str(ex)) tenant_id = helpers.get_x_tenant_or_tenant_id(req, ['api:delegate']) transformed_metrics = metrics_message.transform( metrics, tenant_id, self._region) self._send_metrics(transformed_metrics) res.status = falcon.HTTP_204
def get_limit(req): limit = get_query_param(req, 'limit') if limit: if limit.isdigit(): limit = int(limit) if limit > constants.PAGE_LIMIT: return constants.PAGE_LIMIT else: return limit else: raise HTTPUnprocessableEntityError( "Invalid limit", "Limit parameter must " "be a positive integer") else: return constants.PAGE_LIMIT
def get_query_period(req): try: params = falcon.uri.parse_query_string(req.query_string) if 'period' in params: period = params['period'] try: period = int(period) except Exception: raise Exception("Period must be a valid integer") if period < 0: raise Exception("Period must be a positive integer") return str(period) else: return None except Exception as ex: LOG.debug(ex) raise HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)
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 HTTPUnprocessableEntityError('Unprocessable Entity', ex.message)