From 9c1338dd9d12e985507b654e74043450fab8995c Mon Sep 17 00:00:00 2001 From: Nikita Konovalov Date: Tue, 22 Jul 2014 18:10:21 +0400 Subject: [PATCH] Added Sahara Image context This context will be responsable for uploading and tagging an image for Sahara clusters' benchmarks. Change-Id: I9b89805e35f48212ac49ec94aa02ffc14d3ab535 --- rally/benchmark/context/sahara_image.py | 106 +++++++++++++++++++ tests/benchmark/context/test_sahara_image.py | 102 ++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 rally/benchmark/context/sahara_image.py create mode 100644 tests/benchmark/context/test_sahara_image.py diff --git a/rally/benchmark/context/sahara_image.py b/rally/benchmark/context/sahara_image.py new file mode 100644 index 0000000000..9ad9948d63 --- /dev/null +++ b/rally/benchmark/context/sahara_image.py @@ -0,0 +1,106 @@ +# All Rights Reserved. +# +# 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.benchmark.context import base +from rally.benchmark.context.cleanup import utils as cleanup_utils +from rally.benchmark.scenarios import base as scenarios_base +from rally.benchmark.scenarios.glance import utils as glance_utils +from rally import exceptions +from rally.openstack.common import log as logging +from rally import osclients +from rally import utils as rutils + + +LOG = logging.getLogger(__name__) + + +class SaharaImage(base.Context): + """Context class for adding and tagging Sahara images.""" + + __ctx_name__ = "sahara_image" + __ctx_order__ = 412 + __ctx_hidden__ = False + + CONFIG_SCHEMA = { + "type": "object", + "$schema": rutils.JSON_SCHEMA, + "properties": { + "image_url": { + "type": "string", + }, + "username": { + "type": "string" + }, + "plugin_name": { + "type": "string", + }, + "hadoop_version": { + "type": "string", + }, + }, + "additionalProperties": False, + "required": ["image_url", "username", "plugin_name", "hadoop_version"] + } + + def __init__(self, context): + super(SaharaImage, self).__init__(context) + self.context["sahara_images"] = {} + + @rutils.log_task_wrapper(LOG.info, _("Enter context: `Sahara Image`")) + def setup(self): + image_url = self.config["image_url"] + plugin_name = self.config["plugin_name"] + hadoop_version = self.config["hadoop_version"] + user_name = self.config["username"] + + for user in self.context.get("users", []): + tenant_id = user["tenant_id"] + if tenant_id not in self.context["sahara_images"]: + + clients = osclients.Clients(user["endpoint"]) + glance_util_class = glance_utils.GlanceScenario( + clients=clients) + + image_name = scenarios_base.Scenario._generate_random_name( + prefix="sahara_image_", length=15) + image = glance_util_class._create_image(image_name, + "bare", + image_url, + "qcow2") + + clients.sahara().images.update_image(image_id=image.id, + user_name=user_name, + desc="") + + clients.sahara().images.update_tags(image_id=image.id, + new_tags=[plugin_name, + hadoop_version]) + + self.context["sahara_images"][tenant_id] = image.id + + @rutils.log_task_wrapper(LOG.info, _("Exit context: `Sahara Image`")) + def cleanup(self): + clean_tenants = set([]) + for user in self.context.get("users", []): + tenant_id = user["tenant_id"] + if tenant_id not in clean_tenants: + clean_tenants.add(tenant_id) + + try: + glance = osclients.Clients(user["endpoint"]).glance() + cleanup_utils.delete_glance_resources(glance, + user["tenant_id"]) + except Exception as e: + LOG.error(e) + raise exceptions.ImageCleanUpException() diff --git a/tests/benchmark/context/test_sahara_image.py b/tests/benchmark/context/test_sahara_image.py new file mode 100644 index 0000000000..d0410c46fd --- /dev/null +++ b/tests/benchmark/context/test_sahara_image.py @@ -0,0 +1,102 @@ +# All Rights Reserved. +# +# 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.benchmark.context import sahara_image +from rally import exceptions +from tests import test + +CTX = "rally.benchmark.context" +SCN = "rally.benchmark.scenarios" + + +class SaharaImageTestCase(test.TestCase): + + def setUp(self): + super(SaharaImageTestCase, self).setUp() + self.tenants_num = 2 + self.users_per_tenant = 2 + self.users = self.tenants_num * self.users_per_tenant + self.task = mock.MagicMock() + + self.user_key = [{'id': i, 'tenant_id': j, 'endpoint': 'endpoint'} + for j in range(self.tenants_num) + for i in range(self.users_per_tenant)] + + @property + def context_without_images_key(self): + return { + "config": { + "users": { + "tenants": self.tenants_num, + "users_per_tenant": self.users_per_tenant, + }, + "sahara_image": { + "image_url": "http://somewhere", + "plugin_name": "test_plugin", + "hadoop_version": "test_version", + "username": "test_user" + } + }, + "admin": {"endpoint": mock.MagicMock()}, + "task": mock.MagicMock(), + "users": self.user_key, + } + + @mock.patch("%s.base.Scenario._generate_random_name" % SCN, + return_value="sahara_image_42") + @mock.patch("%s.glance.utils.GlanceScenario._create_image" % SCN, + return_value=mock.MagicMock(id=42)) + @mock.patch("%s.sahara_image.osclients" % CTX) + @mock.patch("%s.cleanup.utils.delete_glance_resources" % CTX) + def test_setup_and_cleanup(self, mock_image_remover, mock_osclients, + mock_image_generator, mock_uuid): + + ctx = self.context_without_images_key + sahara_ctx = sahara_image.SaharaImage(ctx) + + glance_calls = [] + + for i in range(self.tenants_num): + glance_calls.append(mock.call("sahara_image_42", + "bare", + "http://somewhere", + "qcow2")) + + sahara_update_image_calls = [] + sahara_update_tags_calls = [] + + for i in range(self.tenants_num): + sahara_update_image_calls.append(mock.call(image_id=42, + user_name="test_user", + desc="")) + sahara_update_tags_calls.append(mock.call( + image_id=42, + new_tags=["test_plugin", "test_version"])) + + sahara_ctx.setup() + mock_image_generator.assert_has_calls(glance_calls) + mock_osclients.Clients( + mock.MagicMock()).sahara().images.update_image.assert_has_calls( + sahara_update_image_calls) + mock_osclients.Clients( + mock.MagicMock()).sahara().images.update_tags.assert_has_calls( + sahara_update_tags_calls) + + sahara_ctx.cleanup() + self.assertEqual(self.tenants_num, len(mock_image_remover.mock_calls)) + + mock_image_remover.side_effect = Exception('failed_deletion') + self.assertRaises(exceptions.ImageCleanUpException, sahara_ctx.cleanup)