rest: allow to create missing metrics when sending measures in batch
Change-Id: If1f684ad368d4fb797267bbc4c099938f2722dfe
This commit is contained in:
parent
b1fe83142c
commit
f9b19ad8d0
|
@ -121,6 +121,11 @@ Or using named metrics of resources:
|
|||
|
||||
{{ scenarios['post-measures-batch-named']['doc'] }}
|
||||
|
||||
If some named metrics specified in the batch request do not exist, Gnocchi can
|
||||
try to create them as long as an archive policy rule matches:
|
||||
|
||||
{{ scenarios['post-measures-batch-named-create']['doc'] }}
|
||||
|
||||
|
||||
Archive Policy
|
||||
==============
|
||||
|
|
|
@ -550,6 +550,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
- name: post-measures-batch-named-create
|
||||
request: |
|
||||
POST /v1/batch/resources/metrics/measures?create_metrics=true HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"{{ scenarios['create-resource-with-new-metrics']['response'].json['id'] }}": {
|
||||
"disk.io.test": [
|
||||
{ "timestamp": "2014-10-06T14:34:12", "value": 71 },
|
||||
{ "timestamp": "2014-10-06T14:34:20", "value": 81 }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
- name: delete-resource-generic
|
||||
request: DELETE /v1/resource/generic/{{ scenarios['create-resource-generic']['response'].json['id'] }} HTTP/1.1
|
||||
|
||||
|
|
|
@ -653,6 +653,8 @@ class SQLAlchemyIndexer(indexer.IndexerDriver):
|
|||
if (e.constraint ==
|
||||
'fk_metric_ap_name_ap_name'):
|
||||
raise indexer.NoSuchArchivePolicy(archive_policy_name)
|
||||
if e.constraint == 'fk_metric_resource_id_resource_id':
|
||||
raise indexer.NoSuchResource(resource_id)
|
||||
raise
|
||||
return m
|
||||
|
||||
|
|
|
@ -51,8 +51,9 @@ def abort(status_code, detail='', headers=None, comment=None, **kw):
|
|||
"""Like pecan.abort, but make sure detail is a string."""
|
||||
if status_code == 404 and not detail:
|
||||
raise RuntimeError("http code 404 must have 'detail' set")
|
||||
return pecan.abort(status_code, six.text_type(detail),
|
||||
headers, comment, **kw)
|
||||
if isinstance(detail, Exception):
|
||||
detail = six.text_type(detail)
|
||||
return pecan.abort(status_code, detail, headers, comment, **kw)
|
||||
|
||||
|
||||
def get_user_and_project():
|
||||
|
@ -1394,8 +1395,8 @@ class ResourcesMetricsMeasuresBatchController(rest.RestController):
|
|||
{utils.ResourceUUID: {six.text_type: MeasuresListSchema}}
|
||||
)
|
||||
|
||||
@pecan.expose()
|
||||
def post(self):
|
||||
@pecan.expose('json')
|
||||
def post(self, create_metrics=False):
|
||||
body = deserialize_and_validate(self.MeasuresBatchSchema)
|
||||
|
||||
known_metrics = []
|
||||
|
@ -1405,8 +1406,35 @@ class ResourcesMetricsMeasuresBatchController(rest.RestController):
|
|||
metrics = pecan.request.indexer.list_metrics(
|
||||
names=names, resource_id=resource_id)
|
||||
|
||||
if len(names) != len(metrics):
|
||||
known_names = [m.name for m in metrics]
|
||||
known_names = [m.name for m in metrics]
|
||||
if strutils.bool_from_string(create_metrics):
|
||||
user_id, project_id = get_user_and_project()
|
||||
unknown_resources = set()
|
||||
for name in names:
|
||||
if name not in known_names:
|
||||
metric = MetricsController.MetricSchema({
|
||||
"name": name
|
||||
})
|
||||
try:
|
||||
pecan.request.indexer.create_metric(
|
||||
uuid.uuid4(),
|
||||
user_id, project_id,
|
||||
resource_id=resource_id,
|
||||
name=metric.get('name'),
|
||||
unit=metric.get('unit'),
|
||||
archive_policy_name=metric[
|
||||
'archive_policy_name'])
|
||||
except indexer.NoSuchResource as e:
|
||||
unknown_resources.add(resource_id)
|
||||
except indexer.IndexerException as e:
|
||||
# This catch NoSuchArchivePolicy, which is unlikely
|
||||
# be still possible
|
||||
abort(400, e)
|
||||
if unknown_resources:
|
||||
abort(400, {"cause": "Unknown resources",
|
||||
"detail": unknown_resources})
|
||||
|
||||
elif len(names) != len(metrics):
|
||||
unknown_metrics.extend(
|
||||
["%s/%s" % (six.text_type(resource_id), m)
|
||||
for m in names if m not in known_names])
|
||||
|
|
|
@ -160,3 +160,48 @@ tests:
|
|||
- timestamp: "2015-03-06T14:34:12"
|
||||
value: 12
|
||||
status: 202
|
||||
|
||||
- name: create archive policy rule for auto
|
||||
POST: /v1/archive_policy_rule
|
||||
request_headers:
|
||||
content-type: application/json
|
||||
x-roles: admin
|
||||
data:
|
||||
name: rule_auto
|
||||
metric_pattern: "auto.*"
|
||||
archive_policy_name: simple
|
||||
status: 201
|
||||
|
||||
- name: push measurements to unknown named metrics and create it
|
||||
POST: /v1/batch/resources/metrics/measures?create_metrics=true
|
||||
request_headers:
|
||||
content-type: application/json
|
||||
data:
|
||||
46c9418d-d63b-4cdd-be89-8f57ffc5952e:
|
||||
auto.test:
|
||||
- timestamp: "2015-03-06T14:33:57"
|
||||
value: 43.1
|
||||
- timestamp: "2015-03-06T14:34:12"
|
||||
value: 12
|
||||
status: 202
|
||||
|
||||
- name: get created metric to check creation
|
||||
GET: /v1/resource/generic/46c9418d-d63b-4cdd-be89-8f57ffc5952e/metric/auto.test
|
||||
|
||||
- name: push measurements to unknown named metrics and resource with create_metrics
|
||||
POST: /v1/batch/resources/metrics/measures?create_metrics=true
|
||||
request_headers:
|
||||
content-type: application/json
|
||||
accept: application/json
|
||||
data:
|
||||
aaaaaaaa-d63b-4cdd-be89-111111111111:
|
||||
auto.test:
|
||||
- timestamp: "2015-03-06T14:33:57"
|
||||
value: 43.1
|
||||
- timestamp: "2015-03-06T14:34:12"
|
||||
value: 12
|
||||
status: 400
|
||||
response_json_paths:
|
||||
$.description.cause: "Unknown resources"
|
||||
$.description.detail:
|
||||
- "aaaaaaaa-d63b-4cdd-be89-111111111111"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
features:
|
||||
- "When sending measures in batch for resources, it is now possible to pass
|
||||
`create_metric=true` to the query parameters so missing metrics are created.
|
||||
This only works if an archive policy rule matching those named metrics matches."
|
Loading…
Reference in New Issue