From d74ea92ebe40e59b251b5c543cc7a2a73a8bb2ef Mon Sep 17 00:00:00 2001 From: zhangguoqing Date: Wed, 4 May 2016 12:26:20 +0000 Subject: [PATCH] add unit column for metric Change-Id: I9cdf83f1ec51670e74a11125ac9f048bf9d70d84 Closes-Bug: #1530967 --- gnocchi/indexer/__init__.py | 3 +- ...c62df18bf4ee_add_unit_column_for_metric.py | 38 +++++++++++++++++++ gnocchi/indexer/sqlalchemy.py | 5 ++- gnocchi/indexer/sqlalchemy_base.py | 3 ++ gnocchi/rest/__init__.py | 4 ++ gnocchi/tests/gabbi/gabbits/metric.yaml | 18 ++++++++- gnocchi/tests/test_indexer.py | 1 + 7 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 gnocchi/indexer/alembic/versions/c62df18bf4ee_add_unit_column_for_metric.py diff --git a/gnocchi/indexer/__init__.py b/gnocchi/indexer/__init__.py index 4ad7bf5a8..47dc11488 100644 --- a/gnocchi/indexer/__init__.py +++ b/gnocchi/indexer/__init__.py @@ -306,7 +306,8 @@ class IndexerDriver(object): @staticmethod def create_metric(id, created_by_user_id, created_by_project_id, - archive_policy_name, name=None, resource_id=None): + archive_policy_name, name=None, unit=None, + resource_id=None): raise exceptions.NotImplementedError @staticmethod diff --git a/gnocchi/indexer/alembic/versions/c62df18bf4ee_add_unit_column_for_metric.py b/gnocchi/indexer/alembic/versions/c62df18bf4ee_add_unit_column_for_metric.py new file mode 100644 index 000000000..7d4deef59 --- /dev/null +++ b/gnocchi/indexer/alembic/versions/c62df18bf4ee_add_unit_column_for_metric.py @@ -0,0 +1,38 @@ +# Copyright 2016 OpenStack Foundation +# +# 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. +# + +"""add unit column for metric + +Revision ID: c62df18bf4ee +Revises: 2e0b912062d1 +Create Date: 2016-05-04 12:31:25.350190 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'c62df18bf4ee' +down_revision = '2e0b912062d1' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column('metric', sa.Column('unit', + sa.String(length=31), + nullable=True)) diff --git a/gnocchi/indexer/sqlalchemy.py b/gnocchi/indexer/sqlalchemy.py index f1de9dac0..c7593a128 100644 --- a/gnocchi/indexer/sqlalchemy.py +++ b/gnocchi/indexer/sqlalchemy.py @@ -370,12 +370,13 @@ class SQLAlchemyIndexer(indexer.IndexerDriver): def create_metric(self, id, created_by_user_id, created_by_project_id, archive_policy_name, - name=None, resource_id=None): + name=None, unit=None, resource_id=None): m = Metric(id=id, created_by_user_id=created_by_user_id, created_by_project_id=created_by_project_id, archive_policy_name=archive_policy_name, name=name, + unit=unit, resource_id=resource_id) try: with self.facade.writer() as session: @@ -535,12 +536,14 @@ class SQLAlchemyIndexer(indexer.IndexerDriver): if update == 0: raise indexer.NoSuchMetric(value) else: + unit = value.get('unit') ap_name = value['archive_policy_name'] m = Metric(id=uuid.uuid4(), created_by_user_id=r.created_by_user_id, created_by_project_id=r.created_by_project_id, archive_policy_name=ap_name, name=name, + unit=unit, resource_id=r.id) session.add(m) try: diff --git a/gnocchi/indexer/sqlalchemy_base.py b/gnocchi/indexer/sqlalchemy_base.py index 25115ec45..5b2322bd3 100644 --- a/gnocchi/indexer/sqlalchemy_base.py +++ b/gnocchi/indexer/sqlalchemy_base.py @@ -161,6 +161,7 @@ class Metric(Base, GnocchiBase, storage.Metric): ondelete="SET NULL", name="fk_metric_resource_id_resource_id")) name = sqlalchemy.Column(sqlalchemy.String(255)) + unit = sqlalchemy.Column(sqlalchemy.String(31)) status = sqlalchemy.Column(sqlalchemy.Enum('active', 'delete', name="metric_status_enum"), nullable=False, @@ -172,6 +173,7 @@ class Metric(Base, GnocchiBase, storage.Metric): "created_by_user_id": self.created_by_user_id, "created_by_project_id": self.created_by_project_id, "name": self.name, + "unit": self.unit, } unloaded = sqlalchemy.inspect(self).unloaded if 'resource' in unloaded: @@ -195,6 +197,7 @@ class Metric(Base, GnocchiBase, storage.Metric): and self.created_by_user_id == other.created_by_user_id and self.created_by_project_id == other.created_by_project_id and self.name == other.name + and self.unit == other.unit and self.resource_id == other.resource_id) or (storage.Metric.__eq__(self, other))) diff --git a/gnocchi/rest/__init__.py b/gnocchi/rest/__init__.py index 4c140e449..70769c610 100644 --- a/gnocchi/rest/__init__.py +++ b/gnocchi/rest/__init__.py @@ -586,6 +586,8 @@ class MetricsController(rest.RestController): "project_id": six.text_type, "archive_policy_name": six.text_type, "name": six.text_type, + voluptuous.Optional("unit"): + voluptuous.All(six.text_type, voluptuous.Length(max=31)), }) # NOTE(jd) Define this method as it was a voluptuous schema – it's just a @@ -621,6 +623,7 @@ class MetricsController(rest.RestController): "project_id": definition.get('project_id'), "archive_policy_name": archive_policy_name, "name": name, + "unit": definition.get('unit'), }) return definition @@ -634,6 +637,7 @@ class MetricsController(rest.RestController): uuid.uuid4(), user, project, name=body.get('name'), + unit=body.get('unit'), archive_policy_name=body['archive_policy_name']) except indexer.NoSuchArchivePolicy as e: abort(400, e) diff --git a/gnocchi/tests/gabbi/gabbits/metric.yaml b/gnocchi/tests/gabbi/gabbits/metric.yaml index 8ee0b490c..735dd7c78 100644 --- a/gnocchi/tests/gabbi/gabbits/metric.yaml +++ b/gnocchi/tests/gabbi/gabbits/metric.yaml @@ -63,17 +63,33 @@ tests: response_strings: - "[]" - - name: create metric with name + - name: create metric with name and unit url: /v1/metric request_headers: content-type: application/json method: post data: name: "disk.io.rate" + unit: "B/s" status: 201 response_json_paths: $.archive_policy_name: cookies $.name: disk.io.rate + $.unit: B/s + + - name: create metric with name and over length unit + url: /v1/metric + request_headers: + content-type: application/json + method: post + data: + name: "disk.io.rate" + unit: "over_length_unit_over_length_unit" + status: 400 + response_strings: + # split to not match the u' in py2 + - "Invalid input: length of value must be at most 31 for dictionary value @ data[" + - "'unit']" - name: create metric with name no rule url: /v1/metric diff --git a/gnocchi/tests/test_indexer.py b/gnocchi/tests/test_indexer.py index b4e5a98ab..e081621d3 100644 --- a/gnocchi/tests/test_indexer.py +++ b/gnocchi/tests/test_indexer.py @@ -102,6 +102,7 @@ class TestIndexerDriver(tests_base.TestCase): self.assertEqual(m.created_by_user_id, user) self.assertEqual(m.created_by_project_id, project) self.assertIsNone(m.name) + self.assertIsNone(m.unit) self.assertIsNone(m.resource_id) m2 = self.index.list_metrics(id=r1) self.assertEqual([m], m2)