From 367b14102ffc18600d745eeeaad1e23500a71afd Mon Sep 17 00:00:00 2001 From: Juha Kosonen Date: Thu, 22 Mar 2018 18:02:53 +0200 Subject: [PATCH] Add Gnocchi metric scenarios This patch is based on [1] and adds following scenarios: GnocchiMetric.list_metric GnocchiMetric.create_metric GnocchiMetric.create_delete_metric [1] https://review.openstack.org/#/c/453861/ Change-Id: Ia391b89fb7c57dbf30d4ed1756ddca184b1e592f Signed-off-by: Juha Kosonen --- CHANGELOG.rst | 10 +++ rally-jobs/telemetry.yaml | 48 ++++++++++++ rally_openstack/cleanup/resources.py | 23 ++++++ rally_openstack/scenarios/gnocchi/metric.py | 73 +++++++++++++++++++ rally_openstack/services/gnocchi/metric.py | 21 +++++- .../gnocchi/create-delete-metric.json | 25 +++++++ .../gnocchi/create-delete-metric.yaml | 16 ++++ .../scenarios/gnocchi/create-metric.json | 25 +++++++ .../scenarios/gnocchi/create-metric.yaml | 16 ++++ .../tasks/scenarios/gnocchi/list-metric.json | 25 +++++++ .../tasks/scenarios/gnocchi/list-metric.yaml | 16 ++++ tests/ci/osresources.py | 15 +++- tests/unit/cleanup/test_resources.py | 26 +++++++ tests/unit/scenarios/gnocchi/test_metric.py | 66 +++++++++++++++++ tests/unit/services/gnocchi/test_metric.py | 15 ++-- 15 files changed, 408 insertions(+), 12 deletions(-) create mode 100644 rally_openstack/scenarios/gnocchi/metric.py create mode 100644 samples/tasks/scenarios/gnocchi/create-delete-metric.json create mode 100644 samples/tasks/scenarios/gnocchi/create-delete-metric.yaml create mode 100644 samples/tasks/scenarios/gnocchi/create-metric.json create mode 100644 samples/tasks/scenarios/gnocchi/create-metric.yaml create mode 100644 samples/tasks/scenarios/gnocchi/list-metric.json create mode 100644 samples/tasks/scenarios/gnocchi/list-metric.yaml create mode 100644 tests/unit/scenarios/gnocchi/test_metric.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d40bae75..b954cf9e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,16 @@ Changelog .. Release notes for existing releases are MUTABLE! If there is something that was missed or can be improved, feel free to change it! +[Unreleased] +------------ + +Added +~~~~~ + +* [scenario plugin] GnocchiMetric.list_metric +* [scenario plugin] GnocchiMetric.create_metric +* [scenario plugin] GnocchiMetric.create_delete_metric + [1.0.0] - 2018-03-28 -------------------- Start a fork of `rally/plugins/openstack module of original OpenStack Rally diff --git a/rally-jobs/telemetry.yaml b/rally-jobs/telemetry.yaml index bdccaab1..9e1c6d43 100644 --- a/rally-jobs/telemetry.yaml +++ b/rally-jobs/telemetry.yaml @@ -156,3 +156,51 @@ sla: failure_rate: max: 0 + + GnocchiMetric.list_metric: + - + args: + limit: 10000 + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 3 + sla: + failure_rate: + max: 0 + + GnocchiMetric.create_metric: + - + args: + archive_policy_name: "low" + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 3 + sla: + failure_rate: + max: 0 + + GnocchiMetric.create_delete_metric: + - + args: + archive_policy_name: "low" + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 3 + sla: + failure_rate: + max: 0 diff --git a/rally_openstack/cleanup/resources.py b/rally_openstack/cleanup/resources.py index d5f89aa2..15fc18c2 100644 --- a/rally_openstack/cleanup/resources.py +++ b/rally_openstack/cleanup/resources.py @@ -876,6 +876,29 @@ class GnocchiResourceType(GnocchiMixin): pass +@base.resource("gnocchi", "metric", order=next(_gnocchi_order), + tenant_resource=True) +class GnocchiMetric(GnocchiMixin): + + def id(self): + return self.raw_resource["id"] + + def list(self): + result = [] + marker = None + while True: + metrics = self._manager().list(marker=marker) + if not metrics: + break + result.extend(metrics) + marker = metrics[-1]["id"] + if self.tenant_uuid: + result = [r for r in result + if r["creator"].partition(":")[2] == self.tenant_uuid] + + return result + + # WATCHER _watcher_order = get_order(1500) diff --git a/rally_openstack/scenarios/gnocchi/metric.py b/rally_openstack/scenarios/gnocchi/metric.py new file mode 100644 index 00000000..ef9ad371 --- /dev/null +++ b/rally_openstack/scenarios/gnocchi/metric.py @@ -0,0 +1,73 @@ +# Copyright 2017 Red Hat, Inc. +# +# 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. + +from rally import consts +from rally.task import validation + +from rally_openstack import scenario +from rally_openstack.scenarios.gnocchi import utils as gnocchiutils + +"""Scenarios for Gnocchi metric.""" + + +@validation.add("required_services", services=[consts.Service.GNOCCHI]) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(name="GnocchiMetric.list_metric") +class ListMetric(gnocchiutils.GnocchiBase): + + def run(self, limit=None): + """List metrics. + + :param limit: Maximum number of metrics to list + """ + self.gnocchi.list_metric(limit=limit) + + +@validation.add("required_services", services=[consts.Service.GNOCCHI]) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"cleanup@openstack": ["gnocchi.metric"]}, + name="GnocchiMetric.create_metric") +class CreateMetric(gnocchiutils.GnocchiBase): + + def run(self, archive_policy_name="low", resource_id=None, unit=None): + """Create metric. + + :param archive_policy_name: Archive policy name + :param resource_id: The resource ID to attach the metric to + :param unit: The unit of the metric + """ + name = self.generate_random_name() + self.gnocchi.create_metric(name, + archive_policy_name=archive_policy_name, + resource_id=resource_id, unit=unit) + + +@validation.add("required_services", services=[consts.Service.GNOCCHI]) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"cleanup@openstack": ["gnocchi.metric"]}, + name="GnocchiMetric.create_delete_metric") +class CreateDeleteMetric(gnocchiutils.GnocchiBase): + + def run(self, archive_policy_name="low", resource_id=None, unit=None): + """Create metric and then delete it. + + :param archive_policy_name: Archive policy name + :param resource_id: The resource ID to attach the metric to + :param unit: The unit of the metric + """ + name = self.generate_random_name() + metric = self.gnocchi.create_metric( + name, archive_policy_name=archive_policy_name, + resource_id=resource_id, unit=unit) + self.gnocchi.delete_metric(metric["id"]) diff --git a/rally_openstack/services/gnocchi/metric.py b/rally_openstack/services/gnocchi/metric.py index 6eace64f..5d788de0 100644 --- a/rally_openstack/services/gnocchi/metric.py +++ b/rally_openstack/services/gnocchi/metric.py @@ -128,9 +128,26 @@ class GnocchiService(service.Service): return self._clients.gnocchi().metric.delete(metric_id) @atomic.action_timer("gnocchi.list_metric") - def list_metric(self): + def list_metric(self, limit=None): """List metrics.""" - return self._clients.gnocchi().metric.list() + metrics = [] + marker = None + limit_val = limit + while True: + page = self._clients.gnocchi().metric.list(limit=limit_val, + marker=marker) + if not page: + break + metrics.extend(page) + marker = page[-1]["id"] + if limit_val is not None: + cnt = len(metrics) + if cnt < limit: + limit_val = limit - cnt + else: + break + + return metrics @atomic.action_timer("gnocchi.create_resource") def create_resource(self, resource_type="generic"): diff --git a/samples/tasks/scenarios/gnocchi/create-delete-metric.json b/samples/tasks/scenarios/gnocchi/create-delete-metric.json new file mode 100644 index 00000000..ed1b8bd2 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/create-delete-metric.json @@ -0,0 +1,25 @@ +{ + "GnocchiMetric.create_delete_metric": [ + { + "args": { + "archive_policy_name": "low" + }, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 3 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/gnocchi/create-delete-metric.yaml b/samples/tasks/scenarios/gnocchi/create-delete-metric.yaml new file mode 100644 index 00000000..e429fb10 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/create-delete-metric.yaml @@ -0,0 +1,16 @@ +--- + GnocchiMetric.create_delete_metric: + - + args: + archive_policy_name: "low" + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 3 + sla: + failure_rate: + max: 0 diff --git a/samples/tasks/scenarios/gnocchi/create-metric.json b/samples/tasks/scenarios/gnocchi/create-metric.json new file mode 100644 index 00000000..ce240ad5 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/create-metric.json @@ -0,0 +1,25 @@ +{ + "GnocchiMetric.create_metric": [ + { + "args": { + "archive_policy_name": "low" + }, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 3 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/gnocchi/create-metric.yaml b/samples/tasks/scenarios/gnocchi/create-metric.yaml new file mode 100644 index 00000000..509c1027 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/create-metric.yaml @@ -0,0 +1,16 @@ +--- + GnocchiMetric.create_metric: + - + args: + archive_policy_name: "low" + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 3 + sla: + failure_rate: + max: 0 diff --git a/samples/tasks/scenarios/gnocchi/list-metric.json b/samples/tasks/scenarios/gnocchi/list-metric.json new file mode 100644 index 00000000..c4b075c5 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/list-metric.json @@ -0,0 +1,25 @@ +{ + "GnocchiMetric.list_metric": [ + { + "args": { + "limit": 10000 + }, + "runner": { + "type": "constant", + "times": 10, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 3 + } + }, + "sla": { + "failure_rate": { + "max": 0 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/gnocchi/list-metric.yaml b/samples/tasks/scenarios/gnocchi/list-metric.yaml new file mode 100644 index 00000000..d3ab0f07 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/list-metric.yaml @@ -0,0 +1,16 @@ +--- + GnocchiMetric.list_metric: + - + args: + limit: 10000 + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 3 + sla: + failure_rate: + max: 0 diff --git a/tests/ci/osresources.py b/tests/ci/osresources.py index 0584b3c1..ae575689 100755 --- a/tests/ci/osresources.py +++ b/tests/ci/osresources.py @@ -320,12 +320,23 @@ class Gnocchi(ResourceManager): def list_archive_policy_rules(self): return self.client.archive_policy_rule.list() - def list_archive_policy(self): + def list_archive_policys(self): return self.client.archive_policy.list() - def list_resource_type(self): + def list_resource_types(self): return self.client.resource_type.list() + def list_metrics(self): + result = [] + marker = None + while True: + metrics = self.client.metric.list(marker=marker) + if not metrics: + break + result.extend(metrics) + marker = metrics[-1]["id"] + return result + class Ironic(ResourceManager): diff --git a/tests/unit/cleanup/test_resources.py b/tests/unit/cleanup/test_resources.py index 477d5435..3d3b0d02 100644 --- a/tests/unit/cleanup/test_resources.py +++ b/tests/unit/cleanup/test_resources.py @@ -1118,3 +1118,29 @@ class GnocchiMixinTestCase(test.TestCase): gnocchi = self.get_gnocchi() gnocchi.raw_resource = {"name": "test_name"} self.assertEqual("test_name", gnocchi.name()) + + +class GnocchiMetricTestCase(test.TestCase): + + def get_gnocchi(self): + gnocchi = resources.GnocchiMetric() + gnocchi._service = "gnocchi" + return gnocchi + + def test_id(self): + gnocchi = self.get_gnocchi() + gnocchi.raw_resource = {"id": "test_id"} + self.assertEqual("test_id", gnocchi.id()) + + def test_list(self): + gnocchi = self.get_gnocchi() + gnocchi._manager = mock.MagicMock() + metrics = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock(), + mock.MagicMock()] + gnocchi._manager.return_value.list.side_effect = ( + metrics[:2], metrics[2:4], []) + self.assertEqual(metrics, gnocchi.list()) + self.assertEqual( + [mock.call(marker=None), mock.call(marker=metrics[1]["id"]), + mock.call(marker=metrics[3]["id"])], + gnocchi._manager.return_value.list.call_args_list) diff --git a/tests/unit/scenarios/gnocchi/test_metric.py b/tests/unit/scenarios/gnocchi/test_metric.py new file mode 100644 index 00000000..c69c7aec --- /dev/null +++ b/tests/unit/scenarios/gnocchi/test_metric.py @@ -0,0 +1,66 @@ +# Copyright 2017 Red Hat, Inc. +# +# 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 mock + +from rally_openstack.scenarios.gnocchi import metric +from tests.unit import test + + +class GnocchiMetricTestCase(test.ScenarioTestCase): + + def get_test_context(self): + context = super(GnocchiMetricTestCase, self).get_test_context() + context.update({ + "admin": { + "user_id": "fake", + "credential": mock.MagicMock() + }, + "user": { + "user_id": "fake", + "credential": mock.MagicMock() + }, + "tenant": {"id": "fake"} + }) + return context + + def setUp(self): + super(GnocchiMetricTestCase, self).setUp() + patch = mock.patch( + "rally_openstack.services.gnocchi.metric.GnocchiService") + self.addCleanup(patch.stop) + self.mock_metric = patch.start() + + def test_list_metric(self): + metric_service = self.mock_metric.return_value + scenario = metric.ListMetric(self.context) + scenario.run(limit=42) + metric_service.list_metric.assert_called_once_with(limit=42) + + def test_create_metric(self): + metric_service = self.mock_metric.return_value + scenario = metric.CreateMetric(self.context) + scenario.generate_random_name = mock.MagicMock(return_value="name") + scenario.run(archive_policy_name="foo", resource_id="123", unit="u") + metric_service.create_metric.assert_called_once_with( + "name", archive_policy_name="foo", resource_id="123", unit="u") + + def test_create_delete_metric(self): + metric_service = self.mock_metric.return_value + scenario = metric.CreateDeleteMetric(self.context) + scenario.generate_random_name = mock.MagicMock(return_value="name") + scenario.run(archive_policy_name="bar", resource_id="123", unit="v") + metric_service.create_metric.assert_called_once_with( + "name", archive_policy_name="bar", resource_id="123", unit="v") + self.assertEqual(1, metric_service.delete_metric.call_count) diff --git a/tests/unit/services/gnocchi/test_metric.py b/tests/unit/services/gnocchi/test_metric.py index 16794c1e..0ca70ef3 100644 --- a/tests/unit/services/gnocchi/test_metric.py +++ b/tests/unit/services/gnocchi/test_metric.py @@ -129,17 +129,17 @@ class GnocchiServiceTestCase(test.TestCase): "gnocchi.get_measures") def test__create_metric(self): - metric = {"name": "fake_name"} - metric["archive_policy_name"] = "fake_archive_policy" - metric["unit"] = "fake_unit" - metric["resource_id"] = "fake_resource_id" + param = {"name": "fake_name"} + param["archive_policy_name"] = "fake_archive_policy" + param["unit"] = "fake_unit" + param["resource_id"] = "fake_resource_id" self.assertEqual( self.service.create_metric( name="fake_name", archive_policy_name="fake_archive_policy", unit="fake_unit", resource_id="fake_resource_id"), - self.service._clients.gnocchi().metric.create(metric) + self.service._clients.gnocchi().metric.create(param) ) self._test_atomic_action_timer(self.atomic_actions(), "gnocchi.create_metric") @@ -152,10 +152,9 @@ class GnocchiServiceTestCase(test.TestCase): "gnocchi.delete_metric") def test__list_metric(self): + self.service.list_metric(limit=0) self.assertEqual( - self.service.list_metric(), - self.service._clients.gnocchi().metric.list.return_value - ) + 1, self.service._clients.gnocchi().metric.list.call_count) self._test_atomic_action_timer(self.atomic_actions(), "gnocchi.list_metric")