diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 32a259d4..e3c1d6dc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,7 @@ Added * [scenario plugin] GnocchiMetric.list_metric * [scenario plugin] GnocchiMetric.create_metric * [scenario plugin] GnocchiMetric.create_delete_metric +* [scenario plugin] GnocchiResource.create_resource Fixed ~~~~~ diff --git a/rally-jobs/telemetry.yaml b/rally-jobs/telemetry.yaml index 9e1c6d43..d538a87f 100644 --- a/rally-jobs/telemetry.yaml +++ b/rally-jobs/telemetry.yaml @@ -204,3 +204,17 @@ sla: failure_rate: max: 0 + + GnocchiResource.create_resource: + - + 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 15fc18c2..68d5da48 100644 --- a/rally_openstack/cleanup/resources.py +++ b/rally_openstack/cleanup/resources.py @@ -899,6 +899,36 @@ class GnocchiMetric(GnocchiMixin): return result +@base.resource("gnocchi", "resource", order=next(_gnocchi_order), + tenant_resource=True) +class GnocchiResource(GnocchiMixin): + def id(self): + return self.raw_resource["id"] + + def name(self): + return self.raw_resource["original_resource_id"] + + def is_deleted(self): + from gnocchiclient import exceptions as gnocchi_exc + try: + self._manager().get(self.raw_resource["type"], self.id()) + except gnocchi_exc.NotFound: + return True + return False + + def list(self): + result = [] + marker = None + while True: + resources = self._manager().list(marker=marker) + if not resources: + break + result.extend(resources) + marker = resources[-1]["id"] + + return result + + # WATCHER _watcher_order = get_order(1500) diff --git a/rally_openstack/scenarios/gnocchi/resource.py b/rally_openstack/scenarios/gnocchi/resource.py new file mode 100644 index 00000000..6db4c903 --- /dev/null +++ b/rally_openstack/scenarios/gnocchi/resource.py @@ -0,0 +1,36 @@ +# 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 resource.""" + + +@validation.add("required_services", services=[consts.Service.GNOCCHI]) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"cleanup@openstack": ["gnocchi.resource"]}, + name="GnocchiResource.create_resource") +class CreateResource(gnocchiutils.GnocchiBase): + + def run(self, resource_type="generic"): + """Create resource. + + :param resource_type: Type of the resource + """ + name = self.generate_random_name() + self.gnocchi.create_resource(name, resource_type=resource_type) diff --git a/rally_openstack/services/gnocchi/metric.py b/rally_openstack/services/gnocchi/metric.py index 5d788de0..66c76b08 100644 --- a/rally_openstack/services/gnocchi/metric.py +++ b/rally_openstack/services/gnocchi/metric.py @@ -150,12 +150,13 @@ class GnocchiService(service.Service): return metrics @atomic.action_timer("gnocchi.create_resource") - def create_resource(self, resource_type="generic"): + def create_resource(self, name, resource_type="generic"): """Create a resource. + :param name: Name of the resource :param resource_type: Type of the resource """ - resource = {"id": self.generate_random_name()} + resource = {"id": name} return self._clients.gnocchi().resource.create( resource_type, resource) diff --git a/samples/tasks/scenarios/gnocchi/create-resource.json b/samples/tasks/scenarios/gnocchi/create-resource.json new file mode 100644 index 00000000..f3b0be56 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/create-resource.json @@ -0,0 +1,22 @@ +{ + "GnocchiResource.create_resource": [ + { + "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-resource.yaml b/samples/tasks/scenarios/gnocchi/create-resource.yaml new file mode 100644 index 00000000..c3f9d875 --- /dev/null +++ b/samples/tasks/scenarios/gnocchi/create-resource.yaml @@ -0,0 +1,14 @@ +--- + GnocchiResource.create_resource: + - + 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 ae575689..ca97b57c 100755 --- a/tests/ci/osresources.py +++ b/tests/ci/osresources.py @@ -315,7 +315,15 @@ class Gnocchi(ResourceManager): REQUIRED_SERVICE = consts.Service.GNOCCHI def list_resources(self): - return self.client.resource.list() + result = [] + marker = None + while True: + resources = self.client.resource.list(marker=marker) + if not resources: + break + result.extend(resources) + marker = resources[-1]["id"] + return result def list_archive_policy_rules(self): return self.client.archive_policy_rule.list() diff --git a/tests/unit/cleanup/test_resources.py b/tests/unit/cleanup/test_resources.py index 3d3b0d02..0d10b5c8 100644 --- a/tests/unit/cleanup/test_resources.py +++ b/tests/unit/cleanup/test_resources.py @@ -1144,3 +1144,29 @@ class GnocchiMetricTestCase(test.TestCase): [mock.call(marker=None), mock.call(marker=metrics[1]["id"]), mock.call(marker=metrics[3]["id"])], gnocchi._manager.return_value.list.call_args_list) + + +class GnocchiResourceTestCase(test.TestCase): + + def get_gnocchi(self): + gnocchi = resources.GnocchiResource() + 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() + res = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock(), + mock.MagicMock()] + gnocchi._manager.return_value.list.side_effect = ( + res[:2], res[2:4], []) + self.assertEqual(res, gnocchi.list()) + self.assertEqual( + [mock.call(marker=None), mock.call(marker=res[1]["id"]), + mock.call(marker=res[3]["id"])], + gnocchi._manager.return_value.list.call_args_list) diff --git a/tests/unit/scenarios/gnocchi/test_resource.py b/tests/unit/scenarios/gnocchi/test_resource.py new file mode 100644 index 00000000..e817cc8b --- /dev/null +++ b/tests/unit/scenarios/gnocchi/test_resource.py @@ -0,0 +1,51 @@ +# 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 resource +from tests.unit import test + + +class GnocchiResourceTestCase(test.ScenarioTestCase): + + def get_test_context(self): + context = super(GnocchiResourceTestCase, 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(GnocchiResourceTestCase, self).setUp() + patch = mock.patch( + "rally_openstack.services.gnocchi.metric.GnocchiService") + self.addCleanup(patch.stop) + self.mock_metric = patch.start() + + def test_create_resource(self): + resource_service = self.mock_metric.return_value + scenario = resource.CreateResource(self.context) + scenario.generate_random_name = mock.MagicMock(return_value="name") + scenario.run(resource_type="foo") + resource_service.create_resource.assert_called_once_with( + "name", resource_type="foo")