From 73781a832586cbbfeda15f698648b73ca5106f4e Mon Sep 17 00:00:00 2001 From: Boris Pavlovic Date: Mon, 21 Apr 2014 04:47:59 +0400 Subject: [PATCH] Improve User context *) Default value for concurrency should be at least 30. *) Change templates for names of users and context *) Store tenant_id in user (it's very usefull in many cases): role context: https://review.openstack.org/#/c/87984/4/rally/benchmark/context/role.py quotas benchmarks: https://review.openstack.org/#/c/87283/7/rally/benchmark/scenarios/quotas/quotas.py (where we should setup quotas for passed user) Change-Id: I00a97cb6ba20f6ee1636e56dc9ad35216ed30144 --- etc/rally/rally.conf.sample | 2 +- rally/benchmark/context/users.py | 25 ++++++------ tests/benchmark/context/test_users.py | 57 ++++++++++++++++++++++++--- tests/fakes.py | 17 ++++---- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/etc/rally/rally.conf.sample b/etc/rally/rally.conf.sample index 823599d247..81480af0ef 100644 --- a/etc/rally/rally.conf.sample +++ b/etc/rally/rally.conf.sample @@ -404,6 +404,6 @@ # How many concurrent threads use for serving users context # (integer value) -#concurrent=1 +#concurrent=30 diff --git a/rally/benchmark/context/users.py b/rally/benchmark/context/users.py index cece89d018..65f5185e14 100644 --- a/rally/benchmark/context/users.py +++ b/rally/benchmark/context/users.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import uuid - from oslo.config import cfg from rally.benchmark.context import base from rally.benchmark import utils @@ -29,10 +27,10 @@ from rally import utils as rutils LOG = logging.getLogger(__name__) context_opts = [ - cfg.IntOpt('concurrent', - default=1, - help='How many concurrent threads use for' - ' serving users context'), + cfg.IntOpt("concurrent", + default=30, + help="How many concurrent threads use for serving users " + "context") ] CONF = cfg.CONF @@ -67,8 +65,8 @@ class UserGenerator(base.Context): }, "additionalProperties": False } - PATTERN_TENANT = "temp_%(run_id)s_tenant_%(iter)i" - PATTERN_USER = "%(tenant_id)s_user_%(uid)d" + PATTERN_TENANT = "ctx_rally_%(task_id)s_tenant_%(iter)i" + PATTERN_USER = "ctx_rally_%(tenant_id)s_user_%(uid)d" def __init__(self, context): super(UserGenerator, self).__init__(context) @@ -94,12 +92,12 @@ class UserGenerator(base.Context): :returns: tuple (dict tenant, list users) """ - admin_endpoint, users_num, run_id, i = args + admin_endpoint, users_num, task_id, i = args users = [] client = osclients.Clients(admin_endpoint).keystone() tenant = client.tenants.create( - cls.PATTERN_TENANT % {"run_id": run_id, "iter": i}) + cls.PATTERN_TENANT % {"task_id": task_id, "iter": i}) LOG.debug("Creating %d users for tenant %s" % (users_num, tenant.id)) @@ -112,7 +110,9 @@ class UserGenerator(base.Context): "password", tenant.name, consts.EndpointPermission.USER, client.region_name) - users.append({"id": user.id, "endpoint": user_endpoint}) + users.append({"id": user.id, + "endpoint": user_endpoint, + "tenant_id": tenant.id}) return ({"id": tenant.id, "name": tenant.name}, users) @@ -155,9 +155,8 @@ class UserGenerator(base.Context): """Create tenants and users, using pool of threads.""" users_num = self.config["users_per_tenant"] - run_id = str(uuid.uuid4()) - args = [(self.endpoint, users_num, run_id, i) + args = [(self.endpoint, users_num, self.task["uuid"], i) for i in range(self.config["tenants"])] LOG.debug("Creating %d users using %s threads" % ( diff --git a/tests/benchmark/context/test_users.py b/tests/benchmark/context/test_users.py index af2e48ca83..a43ae0792e 100644 --- a/tests/benchmark/context/test_users.py +++ b/tests/benchmark/context/test_users.py @@ -89,19 +89,17 @@ class UserGeneratorTestCase(test.TestCase): fc = fakes.FakeClients() mock_osclients.Clients.return_value = fc - with users.UserGenerator(self.context) as generator: - - # Setup (must be called obviously) + with users.UserGenerator(self.context) as ctx: self.assertEqual(len(fc.keystone().users.list()), 0) self.assertEqual(len(fc.keystone().tenants.list()), 0) - generator.setup() + ctx.setup() - self.assertEqual(len(generator.context["users"]), + self.assertEqual(len(ctx.context["users"]), self.users_num) self.assertEqual(len(fc.keystone().users.list()), self.users_num) - self.assertEqual(len(generator.context["tenants"]), + self.assertEqual(len(ctx.context["tenants"]), self.tenants_num) self.assertEqual(len(fc.keystone().tenants.list()), self.tenants_num) @@ -109,3 +107,50 @@ class UserGeneratorTestCase(test.TestCase): # Cleanup (called by content manager) self.assertEqual(len(fc.keystone().users.list()), 0) self.assertEqual(len(fc.keystone().tenants.list()), 0) + + @mock.patch("rally.benchmark.context.users.osclients") + def test_users_and_tenants_in_context(self, mock_osclients): + fc = fakes.FakeClients() + mock_osclients.Clients.return_value = fc + + task = {"uuid": "abcdef"} + + config = { + "config": { + "users": { + "tenants": 2, + "users_per_tenant": 2, + "concurrent": 1 + } + }, + "admin": {"endpoint": mock.MagicMock()}, + "task": task + } + + with users.UserGenerator(config) as ctx: + ctx.setup() + + tenants = [] + for i, t in enumerate(fc.keystone().tenants.list()): + pattern = users.UserGenerator.PATTERN_TENANT + tenants.append({ + "id": t.id, + "name": pattern % {"task_id": task["uuid"], "iter": i} + }) + + self.assertEqual(ctx.context["tenants"], tenants) + + for user in ctx.context["users"]: + self.assertEqual(set(["id", "endpoint", "tenant_id"]), + set(user.keys())) + + tenants_ids = [] + for t in tenants: + tenants_ids.extend([t["id"], t["id"]]) + + users_ids = [user.id for user in fc.keystone().users.list()] + + for (user, tenant_id, user_id) in zip(ctx.context["users"], + tenants_ids, users_ids): + self.assertEqual(user["id"], user_id) + self.assertEqual(user["tenant_id"], tenant_id) diff --git a/tests/fakes.py b/tests/fakes.py index b6dcf2acbb..5e0213ff58 100644 --- a/tests/fakes.py +++ b/tests/fakes.py @@ -90,7 +90,10 @@ class FakeFloatingIP(FakeResource): class FakeTenant(FakeResource): - pass + + def __init__(self, manager, name): + super(FakeTenant, self).__init__(manager) + self.name = name class FakeUser(FakeResource): @@ -166,6 +169,7 @@ class FakeManager(object): def __init__(self): super(FakeManager, self).__init__() self.cache = {} + self.resources_order = [] def get(self, resource_uuid): return self.cache.get(resource_uuid, None) @@ -174,17 +178,16 @@ class FakeManager(object): cached = self.get(resource_uuid) if cached is not None: cached.status = "DELETED" - del self.cache[cached.uuid] + del self.cache[resource_uuid] + self.resources_order.remove(resource_uuid) def _cache(self, resource): + self.resources_order.append(resource.uuid) self.cache[resource.uuid] = resource return resource def list(self, **kwargs): - resources = [] - for uuid in self.cache.keys(): - resources.append(self.cache[uuid]) - return resources + return [self.cache[key] for key in self.resources_order] def find(self, **kwargs): for resource in self.cache.values(): @@ -271,7 +274,7 @@ class FakeFloatingIPsManager(FakeManager): class FakeTenantsManager(FakeManager): def create(self, name): - return self._cache(FakeTenant(self)) + return self._cache(FakeTenant(self, name)) class FakeNetworkManager(FakeManager):