diff --git a/doc/source/images/Report-Task-Scenario-Data-Per-iteration-profiler.png b/doc/source/images/Report-Task-Scenario-Data-Per-iteration-profiler.png new file mode 100644 index 00000000..4254834b Binary files /dev/null and b/doc/source/images/Report-Task-Scenario-Data-Per-iteration-profiler.png differ diff --git a/doc/source/quick_start/tutorial.rst b/doc/source/quick_start/tutorial.rst index 43037101..f4151225 100644 --- a/doc/source/quick_start/tutorial.rst +++ b/doc/source/quick_start/tutorial.rst @@ -38,3 +38,4 @@ more complicated cases. tutorial/step_8_discovering_more_plugins tutorial/step_9_deploying_openstack tutorial/step_10_verifying_cloud_via_tempest_verifier + tutorial/step_11_profiling_openstack_internals diff --git a/etc/rally/rally.conf.sample b/etc/rally/rally.conf.sample index 66a7526c..332d823f 100644 --- a/etc/rally/rally.conf.sample +++ b/etc/rally/rally.conf.sample @@ -580,6 +580,8 @@ # Neutron create loadbalancer poll interval (floating point value) #neutron_create_loadbalancer_poll_interval = 2.0 +# Enable or disable osprofiler to trace the scenarios +#enable_profiler = True [cleanup] diff --git a/rally/plugins/openstack/cfg/opts.py b/rally/plugins/openstack/cfg/opts.py index 416cccee..939051b8 100644 --- a/rally/plugins/openstack/cfg/opts.py +++ b/rally/plugins/openstack/cfg/opts.py @@ -25,6 +25,7 @@ from rally.plugins.openstack.cfg import monasca from rally.plugins.openstack.cfg import murano from rally.plugins.openstack.cfg import neutron from rally.plugins.openstack.cfg import nova +from rally.plugins.openstack.cfg import profiler from rally.plugins.openstack.cfg import sahara from rally.plugins.openstack.cfg import senlin from rally.plugins.openstack.cfg import vm @@ -43,9 +44,10 @@ def list_opts(): opts = {} for l_opts in (cinder.OPTS, ec2.OPTS, heat.OPTS, ironic.OPTS, magnum.OPTS, manila.OPTS, mistral.OPTS, monasca.OPTS, murano.OPTS, - nova.OPTS, sahara.OPTS, vm.OPTS, glance.OPTS, watcher.OPTS, - tempest.OPTS, keystone_roles.OPTS, keystone_users.OPTS, - cleanup.OPTS, senlin.OPTS, neutron.OPTS): + nova.OPTS, profiler.OPTS, sahara.OPTS, vm.OPTS, glance.OPTS, + watcher.OPTS, tempest.OPTS, keystone_roles.OPTS, + keystone_users.OPTS, cleanup.OPTS, senlin.OPTS, + neutron.OPTS): for category, opt in l_opts.items(): opts.setdefault(category, []) opts[category].extend(opt) diff --git a/rally/plugins/openstack/cfg/profiler.py b/rally/plugins/openstack/cfg/profiler.py new file mode 100644 index 00000000..e0c290c4 --- /dev/null +++ b/rally/plugins/openstack/cfg/profiler.py @@ -0,0 +1,21 @@ +# Copyright 2017: Inria. +# 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 oslo_config import cfg + +OPTS = {"benchmark": [ + cfg.BoolOpt("enable_profiler", default=True, + help="Enable or disable osprofiler to trace the scenarios") +]} diff --git a/rally/plugins/openstack/context/keystone/users.py b/rally/plugins/openstack/context/keystone/users.py index 1e0e37cc..415595ea 100644 --- a/rally/plugins/openstack/context/keystone/users.py +++ b/rally/plugins/openstack/context/keystone/users.py @@ -196,7 +196,8 @@ class UserGenerator(context.Context): endpoint_type=self.credential.endpoint_type, https_insecure=self.credential.https_insecure, https_cacert=self.credential.https_cacert, - region_name=self.credential.region_name) + region_name=self.credential.region_name, + profiler_hmac_key=self.credential.profiler_hmac_key) users.append({"id": user.id, "credential": user_credential, "tenant_id": tenant_id}) diff --git a/rally/plugins/openstack/credential.py b/rally/plugins/openstack/credential.py index 85c6055c..56b7b09d 100644 --- a/rally/plugins/openstack/credential.py +++ b/rally/plugins/openstack/credential.py @@ -32,7 +32,8 @@ class OpenStackCredential(credential.Credential): region_name=None, endpoint_type=None, domain_name=None, endpoint=None, user_domain_name=None, project_domain_name=None, - https_insecure=False, https_cacert=None): + https_insecure=False, https_cacert=None, + profiler_hmac_key=None): self.auth_url = auth_url self.username = username self.password = password @@ -46,6 +47,7 @@ class OpenStackCredential(credential.Credential): self.endpoint = endpoint self.https_insecure = https_insecure self.https_cacert = https_cacert + self.profiler_hmac_key = profiler_hmac_key self._clients_cache = {} @@ -76,7 +78,8 @@ class OpenStackCredential(credential.Credential): "https_cacert": self.https_cacert, "user_domain_name": self.user_domain_name, "project_domain_name": self.project_domain_name, - "permission": self.permission} + "permission": self.permission, + "profiler_hmac_key": self.profiler_hmac_key} def verify_connection(self): from keystoneclient import exceptions as keystone_exceptions @@ -152,6 +155,7 @@ class OpenStackCredentialBuilder(credential.CredentialBuilder): None]}, "https_insecure": {"type": "boolean"}, "https_cacert": {"type": "string"}, + "profiler_hmac_key": {"type": ["string", "null"]} }, "required": ["auth_url", "admin"], "additionalProperties": False @@ -171,7 +175,8 @@ class OpenStackCredentialBuilder(credential.CredentialBuilder): user_domain_name=user.get("user_domain_name", None), project_domain_name=user.get("project_domain_name", None), https_insecure=common.get("https_insecure", False), - https_cacert=common.get("https_cacert")) + https_cacert=common.get("https_cacert"), + profiler_hmac_key=common.get("profiler_hmac_key")) return cred.to_dict() def build_credentials(self): diff --git a/rally/plugins/openstack/scenario.py b/rally/plugins/openstack/scenario.py index 0688a270..0b6dba44 100644 --- a/rally/plugins/openstack/scenario.py +++ b/rally/plugins/openstack/scenario.py @@ -16,11 +16,15 @@ import functools import random +from oslo_config import cfg +from osprofiler import profiler from rally import osclients from rally.task import scenario configure = functools.partial(scenario.configure, namespace="openstack") +CONF = cfg.CONF + class OpenStackScenario(scenario.Scenario): """Base class for all OpenStack scenarios.""" @@ -54,6 +58,8 @@ class OpenStackScenario(scenario.Scenario): if clients: self._clients = clients + self._init_profiler(context) + def _choose_user(self, context): """Choose one user from users context @@ -104,3 +110,27 @@ class OpenStackScenario(scenario.Scenario): client = getattr(self._admin_clients, client_type) return client(version) if version is not None else client() + + def _init_profiler(self, context): + """Inits the profiler.""" + if not CONF.benchmark.enable_profiler: + return + if context is not None: + cred = None + profiler_hmac_key = None + if "admin" in context: + cred = context["admin"]["credential"] + if cred.profiler_hmac_key is not None: + profiler_hmac_key = cred.profiler_hmac_key + if "user" in context: + cred = context["user"]["credential"] + if cred.profiler_hmac_key is not None: + profiler_hmac_key = cred.profiler_hmac_key + if profiler_hmac_key is None: + return + profiler.init(profiler_hmac_key) + trace_id = profiler.get().get_base_id() + self.add_output(complete={ + "title": "OSProfiler Trace-ID", + "chart_plugin": "TextArea", + "data": [trace_id]}) diff --git a/requirements.txt b/requirements.txt index 1f984d37..a3f949da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,6 +30,7 @@ boto>=2.32.1,<=2.46.1 # MIT gnocchiclient>=2.7.0,<=3.1.1 # Apache Software License keystoneauth1==2.20.0 # Apache Software License os-faults>=0.1.5,<=0.1.12 # Apache Software License +osprofiler>=1.4.0 # Apache License, Version 2.0 python-ceilometerclient>=2.5.0,<=2.8.1 # Apache Software License python-cinderclient==2.0.1 # Apache Software License python-designateclient>=1.5.0,<=2.6.0 # Apache License, Version 2.0 diff --git a/samples/deployments/existing-keystone-v3-osprofiler.json b/samples/deployments/existing-keystone-v3-osprofiler.json new file mode 100644 index 00000000..89f96412 --- /dev/null +++ b/samples/deployments/existing-keystone-v3-osprofiler.json @@ -0,0 +1,20 @@ +{ + "type": "ExistingCloud", + "creds": { + "openstack": { + "auth_url": "http://example.net:5000/v3/", + "region_name": "RegionOne", + "endpoint_type": "public", + "admin": { + "username": "admin", + "password": "myadminpass", + "user_domain_name": "admin", + "project_name": "admin", + "project_domain_name": "admin" + }, + "https_insecure": false, + "https_cacert": "", + "profiler_hmac_key": "SECRET_KEY" + } + } +} diff --git a/tests/unit/plugins/openstack/context/ec2/test_servers.py b/tests/unit/plugins/openstack/context/ec2/test_servers.py index 5f20c6ee..0ed471df 100644 --- a/tests/unit/plugins/openstack/context/ec2/test_servers.py +++ b/tests/unit/plugins/openstack/context/ec2/test_servers.py @@ -37,7 +37,7 @@ class EC2ServerGeneratorTestCase(test.TestCase): for tenant_id in tenants.keys(): for i in range(users_per_tenant): users.append({"id": i, "tenant_id": tenant_id, - "credential": "credential"}) + "credential": mock.MagicMock()}) return tenants, users def _get_context(self, users, tenants): diff --git a/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py b/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py index 2bdd3939..12296f5f 100644 --- a/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py +++ b/tests/unit/plugins/openstack/context/manila/test_manila_share_networks.py @@ -27,6 +27,8 @@ from tests.unit import test MANILA_UTILS_PATH = ("rally.plugins.openstack.scenarios.manila.utils." "ManilaScenario.") +MOCK_USER_CREDENTIAL = mock.MagicMock() + class Fake(object): def __init__(self, **kwargs): @@ -71,8 +73,9 @@ class ShareNetworksTestCase(test.TestCase): users = [] for t_id in tenants.keys(): for i in range(self.USERS_PER_TENANT): - users.append( - {"id": i, "tenant_id": t_id, "credential": "fake"}) + users.append({ + "id": i, "tenant_id": t_id, + "credential": MOCK_USER_CREDENTIAL}) context = { "config": { "users": { @@ -123,8 +126,8 @@ class ShareNetworksTestCase(test.TestCase): "tenant_2_id": {"id": "tenant_2_id", "name": "tenant_2_name"}, }, "users": [ - {"tenant_id": "tenant_1_id", "credential": {"c1": "foo"}}, - {"tenant_id": "tenant_2_id", "credential": {"c2": "bar"}}, + {"tenant_id": "tenant_1_id", "credential": mock.MagicMock()}, + {"tenant_id": "tenant_2_id", "credential": mock.MagicMock()}, ], } self.existing_sns = [ @@ -288,8 +291,8 @@ class ShareNetworksTestCase(test.TestCase): ] mock_manila_scenario__create_share_network.assert_has_calls( expected_calls * (self.TENANTS_AMOUNT * networks_per_tenant)) - mock_clients.assert_has_calls([ - mock.call("fake", {}) for i in range(self.TENANTS_AMOUNT)]) + mock_clients.assert_has_calls([mock.call(MOCK_USER_CREDENTIAL, {}) + for i in range(self.TENANTS_AMOUNT)]) @ddt.data(True, False) @mock.patch("rally.osclients.Clients") @@ -326,8 +329,8 @@ class ShareNetworksTestCase(test.TestCase): expected_calls = [mock.call(**sn_args), mock.call().to_dict()] mock_manila_scenario__create_share_network.assert_has_calls( expected_calls * (self.TENANTS_AMOUNT * networks_per_tenant)) - mock_clients.assert_has_calls([ - mock.call("fake", {}) for i in range(self.TENANTS_AMOUNT)]) + mock_clients.assert_has_calls([mock.call(MOCK_USER_CREDENTIAL, {}) + for i in range(self.TENANTS_AMOUNT)]) @mock.patch("rally.osclients.Clients") @mock.patch(MANILA_UTILS_PATH + "_create_share_network") @@ -351,8 +354,8 @@ class ShareNetworksTestCase(test.TestCase): expected_calls = [mock.call(), mock.call().to_dict()] mock_manila_scenario__create_share_network.assert_has_calls( expected_calls * self.TENANTS_AMOUNT) - mock_clients.assert_has_calls([ - mock.call("fake", {}) for i in range(self.TENANTS_AMOUNT)]) + mock_clients.assert_has_calls([mock.call(MOCK_USER_CREDENTIAL, {}) + for i in range(self.TENANTS_AMOUNT)]) @mock.patch("rally.osclients.Clients") @mock.patch(MANILA_UTILS_PATH + "_delete_share_network") diff --git a/tests/unit/plugins/openstack/context/manila/test_manila_shares.py b/tests/unit/plugins/openstack/context/manila/test_manila_shares.py index 6f023533..24afa2f2 100644 --- a/tests/unit/plugins/openstack/context/manila/test_manila_shares.py +++ b/tests/unit/plugins/openstack/context/manila/test_manila_shares.py @@ -56,8 +56,9 @@ class SharesTestCase(test.TestCase): users = [] for t_id in sorted(list(tenants.keys())): for i in range(self.USERS_PER_TENANT): - users.append( - {"id": i, "tenant_id": t_id, "credential": "fake"}) + users.append({ + "id": i, "tenant_id": t_id, + "credential": mock.MagicMock()}) context = { "config": { "users": { diff --git a/tests/unit/plugins/openstack/context/murano/test_murano_environments.py b/tests/unit/plugins/openstack/context/murano/test_murano_environments.py index 69fe47fb..4ea04bee 100644 --- a/tests/unit/plugins/openstack/context/murano/test_murano_environments.py +++ b/tests/unit/plugins/openstack/context/murano/test_murano_environments.py @@ -50,12 +50,12 @@ class MuranoEnvironmentGeneratorTestCase(test.TestCase): { "id": "user_0", "tenant_id": "tenant_0", - "credential": "credential" + "credential": mock.MagicMock() }, { "id": "user_1", "tenant_id": "tenant_1", - "credential": "credential" + "credential": mock.MagicMock() } ], "tenants": { diff --git a/tests/unit/plugins/openstack/context/swift/test_objects.py b/tests/unit/plugins/openstack/context/swift/test_objects.py index 9c8d554d..394a82d3 100644 --- a/tests/unit/plugins/openstack/context/swift/test_objects.py +++ b/tests/unit/plugins/openstack/context/swift/test_objects.py @@ -41,8 +41,16 @@ class SwiftObjectGeneratorTestCase(test.TestCase): "t2": {"name": "t2_name"} }, "users": [ - {"id": "u1", "tenant_id": "t1", "credential": "c1"}, - {"id": "u2", "tenant_id": "t2", "credential": "c2"} + { + "id": "u1", + "tenant_id": "t1", + "credential": mock.MagicMock() + }, + { + "id": "u2", + "tenant_id": "t2", + "credential": mock.MagicMock() + } ] }) @@ -122,8 +130,16 @@ class SwiftObjectGeneratorTestCase(test.TestCase): "t2": {"name": "t2_name"} }, "users": [ - {"id": "u1", "tenant_id": "t1", "credential": "c1"}, - {"id": "u2", "tenant_id": "t2", "credential": "c2"} + { + "id": "u1", + "tenant_id": "t1", + "credential": mock.MagicMock() + }, + { + "id": "u2", + "tenant_id": "t2", + "credential": mock.MagicMock() + } ] }) mock_swift = mock_clients.return_value.swift.return_value @@ -143,8 +159,16 @@ class SwiftObjectGeneratorTestCase(test.TestCase): "t2": {"name": "t2_name"} }, "users": [ - {"id": "u1", "tenant_id": "t1", "credential": "c1"}, - {"id": "u2", "tenant_id": "t2", "credential": "c2"} + { + "id": "u1", + "tenant_id": "t1", + "credential": mock.MagicMock() + }, + { + "id": "u2", + "tenant_id": "t2", + "credential": mock.MagicMock() + } ] }) mock_swift = mock_clients.return_value.swift.return_value @@ -163,7 +187,7 @@ class SwiftObjectGeneratorTestCase(test.TestCase): "name": "t1_name", "containers": [ {"user": {"id": "u1", "tenant_id": "t1", - "credential": "c1"}, + "credential": mock.MagicMock()}, "container": "coooon", "objects": []}] * 3 } @@ -184,7 +208,7 @@ class SwiftObjectGeneratorTestCase(test.TestCase): "name": "t1_name", "containers": [ {"user": {"id": "u1", "tenant_id": "t1", - "credential": "c1"}, + "credential": mock.MagicMock()}, "container": "c1", "objects": ["oooo"] * 3} ] diff --git a/tests/unit/plugins/openstack/context/swift/test_utils.py b/tests/unit/plugins/openstack/context/swift/test_utils.py index ec1761cd..2a80a5df 100644 --- a/tests/unit/plugins/openstack/context/swift/test_utils.py +++ b/tests/unit/plugins/openstack/context/swift/test_utils.py @@ -26,14 +26,15 @@ class SwiftObjectMixinTestCase(test.TestCase): tenants = 2 containers_per_tenant = 2 context = test.get_test_context() + c = [mock.MagicMock(), mock.MagicMock()] context.update({ "tenants": { "1001": {"name": "t1_name"}, "1002": {"name": "t2_name"} }, "users": [ - {"id": "u1", "tenant_id": "1001", "credential": "c1"}, - {"id": "u2", "tenant_id": "1002", "credential": "c2"} + {"id": "u1", "tenant_id": "1001", "credential": c[0]}, + {"id": "u2", "tenant_id": "1002", "credential": c[1]} ] }) @@ -51,7 +52,7 @@ class SwiftObjectMixinTestCase(test.TestCase): self.assertEqual(containers_per_tenant, len(containers)) for container in containers: self.assertEqual("u%d" % index, container["user"]["id"]) - self.assertEqual("c%d" % index, + self.assertEqual(c[index - 1], container["user"]["credential"]) self.assertEqual(0, len(container["objects"])) @@ -68,7 +69,7 @@ class SwiftObjectMixinTestCase(test.TestCase): "containers": [ {"user": { "id": "u1", "tenant_id": "1001", - "credential": "c0"}, + "credential": mock.MagicMock()}, "container": "c1", "objects": []} ] @@ -78,7 +79,7 @@ class SwiftObjectMixinTestCase(test.TestCase): "containers": [ {"user": { "id": "u2", "tenant_id": "1002", - "credential": "c2"}, + "credential": mock.MagicMock()}, "container": "c2", "objects": []} ] @@ -114,7 +115,7 @@ class SwiftObjectMixinTestCase(test.TestCase): "containers": [ {"user": { "id": "u1", "tenant_id": "1001", - "credential": "c1"}, + "credential": mock.MagicMock()}, "container": "c1", "objects": []} ] @@ -124,7 +125,7 @@ class SwiftObjectMixinTestCase(test.TestCase): "containers": [ {"user": { "id": "u2", "tenant_id": "1002", - "credential": "c2"}, + "credential": mock.MagicMock()}, "container": "c2", "objects": []} ] @@ -154,7 +155,7 @@ class SwiftObjectMixinTestCase(test.TestCase): "containers": [ {"user": { "id": "u1", "tenant_id": "1001", - "credential": "c1"}, + "credential": mock.MagicMock()}, "container": "c1", "objects": ["o1", "o2", "o3"]} ] @@ -164,7 +165,7 @@ class SwiftObjectMixinTestCase(test.TestCase): "containers": [ {"user": { "id": "u2", "tenant_id": "1002", - "credential": "c2"}, + "credential": mock.MagicMock()}, "container": "c2", "objects": ["o4", "o5", "o6"]} ] diff --git a/tests/unit/plugins/openstack/scenarios/vm/test_vmtasks.py b/tests/unit/plugins/openstack/scenarios/vm/test_vmtasks.py index 3a5405ac..61b25406 100644 --- a/tests/unit/plugins/openstack/scenarios/vm/test_vmtasks.py +++ b/tests/unit/plugins/openstack/scenarios/vm/test_vmtasks.py @@ -262,7 +262,7 @@ class VMTasksTestCase(test.ScenarioTestCase): mock_heat.main.Stack.return_value = fake_stack context = { "user": {"keypair": {"name": "name", "private": "pk"}, - "credential": "ok"}, + "credential": mock.MagicMock()}, "tenant": {"networks": [{"router_id": "1"}]} } scenario = vmtasks.RuncommandHeat(context) diff --git a/tests/unit/plugins/openstack/test_credential.py b/tests/unit/plugins/openstack/test_credential.py index bd58e4fe..5ec2e24f 100644 --- a/tests/unit/plugins/openstack/test_credential.py +++ b/tests/unit/plugins/openstack/test_credential.py @@ -44,7 +44,9 @@ class OpenStackCredentialTestCase(test.TestCase): "https_insecure": False, "https_cacert": None, "project_domain_name": None, - "user_domain_name": None}, self.credential.to_dict()) + "user_domain_name": None, + "profiler_hmac_key": None}, + self.credential.to_dict()) @mock.patch("rally.osclients.Clients") def test_verify_connection_admin(self, mock_clients): @@ -127,6 +129,7 @@ class OpenStackCredentialBuilderTestCase(test.TestCase): "endpoint_type": consts.EndpointType.INTERNAL, "https_cacert": "cacert", "https_insecure": False, + "profiler_hmac_key": None, "project_domain_name": None, "region_name": "RegionOne", "tenant_name": "demo", @@ -143,6 +146,7 @@ class OpenStackCredentialBuilderTestCase(test.TestCase): "endpoint_type": consts.EndpointType.INTERNAL, "https_cacert": "cacert", "https_insecure": False, + "profiler_hmac_key": None, "project_domain_name": None, "region_name": "RegionOne", "tenant_name": "demo", diff --git a/tests/unit/plugins/openstack/test_scenario.py b/tests/unit/plugins/openstack/test_scenario.py index 68741701..38062733 100644 --- a/tests/unit/plugins/openstack/test_scenario.py +++ b/tests/unit/plugins/openstack/test_scenario.py @@ -16,11 +16,23 @@ import ddt import mock from oslotest import mockpatch - +from rally.plugins.openstack.credential import OpenStackCredential from rally.plugins.openstack import scenario as base_scenario from tests.unit import test +CREDENTIAL_WITHOUT_HMAC = OpenStackCredential( + "auth_url", + "username", + "password") + +CREDENTIAL_WITH_HMAC = OpenStackCredential( + "auth_url", + "username", + "password", + profiler_hmac_key="test_profiler_hmac_key") + + @ddt.ddt class OpenStackScenarioTestCase(test.TestCase): def setUp(self): @@ -80,6 +92,31 @@ class OpenStackScenarioTestCase(test.TestCase): self.assertEqual("foobar", scenario._clients) + @ddt.data(([], 0), + ([("admin", CREDENTIAL_WITHOUT_HMAC)], 0), + ([("user", CREDENTIAL_WITHOUT_HMAC)], 0), + ([("admin", CREDENTIAL_WITH_HMAC)], 1), + ([("user", CREDENTIAL_WITH_HMAC)], 1), + ([("admin", CREDENTIAL_WITH_HMAC), + ("user", CREDENTIAL_WITH_HMAC)], 1), + ([("admin", CREDENTIAL_WITHOUT_HMAC), + ("user", CREDENTIAL_WITH_HMAC)], 1), + ([("admin", CREDENTIAL_WITH_HMAC), + ("user", CREDENTIAL_WITHOUT_HMAC)], 1), + ([("admin", CREDENTIAL_WITHOUT_HMAC), + ("user", CREDENTIAL_WITHOUT_HMAC)], 0)) + @ddt.unpack + @mock.patch("rally.plugins.openstack.scenario.profiler.init") + def test_profiler_init(self, users_credentials, + expected_init_call_count, + mock_profiler_init): + for user, credential in users_credentials: + print(user, credential.profiler_hmac_key) + self.context.update({user: {"credential": credential}}) + base_scenario.OpenStackScenario(self.context) + self.assertEqual(expected_init_call_count, + mock_profiler_init.call_count) + def test__choose_user_random(self): users = [{"credential": mock.Mock(), "tenant_id": "foo"} for _ in range(5)]