diff --git a/rally-jobs/rally.yaml b/rally-jobs/rally.yaml index a4b66cb592..199fdf5773 100755 --- a/rally-jobs/rally.yaml +++ b/rally-jobs/rally.yaml @@ -86,6 +86,18 @@ failure_rate: max: 0 + KeystoneBasic.create_update_and_delete_tenant: + - + args: + name_length: 10 + runner: + type: "constant" + times: 10 + concurrency: 5 + sla: + failure_rate: + max: 0 + KeystoneBasic.create_delete_user: - args: diff --git a/rally/benchmark/scenarios/keystone/basic.py b/rally/benchmark/scenarios/keystone/basic.py index b5a57b3a5d..fee5e946d6 100644 --- a/rally/benchmark/scenarios/keystone/basic.py +++ b/rally/benchmark/scenarios/keystone/basic.py @@ -125,6 +125,19 @@ class KeystoneBasic(kutils.KeystoneScenario): service = self._service_create(name, service_type, description) self._delete_service(service.id) + @validation.number("name_length", minval=10) + @validation.required_openstack(admin=True) + @base.scenario(context={"admin_cleanup": ["keystone"]}) + def create_update_and_delete_tenant(self, name_length=10, **kwargs): + """Create, update and delete tenant. + + :param name_length: length of the random part of tenant name + :param kwargs: Other optional parameters for tenant creation + """ + tenant = self._tenant_create(name_length=name_length, **kwargs) + self._update_tenant(tenant) + self._resource_delete(tenant) + @validation.required_openstack(admin=True) @base.scenario(context={"admin_cleanup": ["keystone"]}) def create_and_list_services(self, name=None, service_type=None, diff --git a/rally/benchmark/scenarios/keystone/utils.py b/rally/benchmark/scenarios/keystone/utils.py index 0f7f9e0f1a..0311b896c3 100644 --- a/rally/benchmark/scenarios/keystone/utils.py +++ b/rally/benchmark/scenarios/keystone/utils.py @@ -164,3 +164,16 @@ class KeystoneScenario(base.Scenario): :param service_id: service to be deleted """ self.admin_clients("keystone").services.delete(service_id) + + @base.atomic_action_timer("keystone.update_tenant") + def _update_tenant(self, tenant, name=None, description=None): + """Update tenant name and description. + + :param tenant: tenant to be updated + :param name: tenant name to be set + :param description: tenant description to be set + """ + name = name or (tenant.name + "_updated") + description = description or (tenant.name + "_description_updated") + self.admin_clients("keystone").tenants.update(tenant.id, + name, description) diff --git a/samples/tasks/scenarios/keystone/create-update-and-delete-tenant.json b/samples/tasks/scenarios/keystone/create-update-and-delete-tenant.json new file mode 100644 index 0000000000..a2b36f28cc --- /dev/null +++ b/samples/tasks/scenarios/keystone/create-update-and-delete-tenant.json @@ -0,0 +1,14 @@ +{ + "KeystoneBasic.create_update_and_delete_tenant": [ + { + "args": { + "name_length": 10 + }, + "runner": { + "type": "constant", + "times": 100, + "concurrency": 10 + } + } + ] +} diff --git a/samples/tasks/scenarios/keystone/create-update-and-delete-tenant.yaml b/samples/tasks/scenarios/keystone/create-update-and-delete-tenant.yaml new file mode 100644 index 0000000000..2cb33c83b1 --- /dev/null +++ b/samples/tasks/scenarios/keystone/create-update-and-delete-tenant.yaml @@ -0,0 +1,9 @@ +--- + KeystoneBasic.create_update_and_delete_tenant: + - + args: + name_length: 10 + runner: + type: "constant" + times: 100 + concurrency: 10 diff --git a/tests/unit/benchmark/scenarios/keystone/test_basic.py b/tests/unit/benchmark/scenarios/keystone/test_basic.py index 8c3a3c1a6c..3e5899d64b 100644 --- a/tests/unit/benchmark/scenarios/keystone/test_basic.py +++ b/tests/unit/benchmark/scenarios/keystone/test_basic.py @@ -141,6 +141,16 @@ class KeystoneBasicTestCase(test.TestCase): description) scenario._delete_service.assert_called_once_with(fake_service.id) + def test_create_update_and_delete_tenant(self): + scenario = basic.KeystoneBasic() + fake_tenant = mock.MagicMock() + scenario._tenant_create = mock.MagicMock(return_value=fake_tenant) + scenario._update_tenant = mock.MagicMock() + scenario._resource_delete = mock.MagicMock() + scenario.create_update_and_delete_tenant() + scenario._update_tenant.assert_called_once_with(fake_tenant) + scenario._resource_delete.assert_called_once_with(fake_tenant) + def test_create_and_list_services(self): scenario = basic.KeystoneBasic() name = "Rally_test_service" diff --git a/tests/unit/benchmark/scenarios/keystone/test_utils.py b/tests/unit/benchmark/scenarios/keystone/test_utils.py index 14afd01a53..8c97190814 100644 --- a/tests/unit/benchmark/scenarios/keystone/test_utils.py +++ b/tests/unit/benchmark/scenarios/keystone/test_utils.py @@ -271,9 +271,27 @@ class KeystoneScenarioTestCase(test.TestCase): self._test_atomic_action_timer(scenario.atomic_actions(), "keystone.get_service") + def test_update_tenant(self): + tenant = mock.MagicMock() + description = tenant.name + "_description_updated_test" + name = tenant.name + "test_updated_test" + fake_keystone = fakes.FakeKeystoneClient() + fake_keystone.tenants.update = mock.MagicMock() + fake_clients = fakes.FakeClients() + fake_clients._keystone = fake_keystone + scenario = utils.KeystoneScenario(admin_clients=fake_clients) + + scenario._update_tenant(tenant=tenant, name=name, + description=description) + + fake_keystone.tenants.update.assert_called_once_with(tenant.id, name, + description) + self._test_atomic_action_timer(scenario.atomic_actions(), + "keystone.update_tenant") + def test_get_service_by_name(self): scenario = utils.KeystoneScenario() svc_foo, svc_bar = mock.Mock(), mock.Mock() scenario._list_services = mock.Mock(return_value=[svc_foo, svc_bar]) self.assertEqual(scenario._get_service_by_name(svc_bar.name), svc_bar) - self.assertIsNone(scenario._get_service_by_name("spam")) \ No newline at end of file + self.assertIsNone(scenario._get_service_by_name("spam")) diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index b708a8b0a8..0782fe690c 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -449,6 +449,14 @@ class FakeTenantsManager(FakeManager): def create(self, name): return self._cache(FakeTenant(self, name)) + def update(self, tenant_id, name=None, description=None): + tenant = self.get(tenant_id) + name = name or (tenant.name + "_updated") + desc = description or (tenant.name + "_description_updated") + tenant.name = name + tenant.description = desc + return self._cache(tenant) + class FakeNetworkManager(FakeManager):