Add base utils for keystone benchmarks

This patch introduce keystone benchmarks with keystone base utils
+ add 2 keystone benchmark scenarios:
1) create_user - just create user one by one
2) create_delete_user - create & delete user

Add tests for utils and benchmarks

Samples included

blueprint keystone-benchmark

Change-Id: I9362135877bb1bc904fc8ed93c74eba89686e78a
This commit is contained in:
Boris Pavlovic 2013-12-28 15:07:37 +04:00
parent 2436e86d48
commit 6d7432eeeb
8 changed files with 209 additions and 2 deletions

View File

@ -0,0 +1,7 @@
{
"KeystoneBasic.create_delete_user": [
{"args": {"name_length": 10},
"execution": "continuous",
"config": {"times": 100, "active_users": 10}}
]
}

View File

@ -0,0 +1,7 @@
{
"KeystoneBasic.create_user": [
{"args": {"name_length": 10},
"execution": "continuous",
"config": {"times": 100, "active_users": 10}}
]
}

View File

@ -0,0 +1,28 @@
# Copyright 2013: Mirantis Inc.
# 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.scenarios.keystone import utils as kutils
class KeystoneBasic(kutils.KeystoneScenario):
@classmethod
def create_user(cls, name_length=10, **kwargs):
cls._user_create(name_length=name_length, **kwargs)
@classmethod
def create_delete_user(cls, name_length=10, **kwargs):
user = cls._user_create(name_length=name_length, **kwargs)
cls._resource_delete(user)

View File

@ -13,9 +13,49 @@
# License for the specific language governing permissions and limitations
# under the License.
import random
import string
from rally.benchmark import base
# TODO(boris-42): Bind name to the uuid of benchmark.
TEMP_TEMPLATE = "rally_k_"
def is_temporary(resource):
return resource.name.startswith(TEMP_TEMPLATE)
def generate_keystone_name(length=10):
"""Generate random name for keystone resources."""
rand_part = ''.join(random.choice(string.lowercase) for i in range(length))
return TEMP_TEMPLATE + rand_part
class KeystoneScenario(base.Scenario):
"""This class should contain base operations for benchmarking keystone,
most of them are creating/deleting resources.
"""
@classmethod
def _user_create(cls, name_length=10, password=None, email=None, **kwargs):
"""Creates keystone user with random name.
:param name_length: length of generated (ranodm) part of name
:param **kwargs: Other optional parameters to create users like
"tenant_id", "enabled".
:return: keystone user instance
"""
name = generate_keystone_name(length=name_length)
# NOTE(boris-42): password and email parameters are required by
# keystone client v2.0. This should be cleanuped
# when we switch to v3.
password = password or name
email = email or (name + "@rally.me")
return cls.admin_clients("keystone").users.create(name, password,
email, **kwargs)
@classmethod
def _resource_delete(cls, resource):
""""Delete keystone resource."""
resource.delete()

View File

@ -0,0 +1,52 @@
# Copyright 2013: Mirantis Inc.
# 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.scenarios.keystone import basic
from rally import test
KEYSTONE_BASE = "rally.benchmark.scenarios.keystone."
KEYSTONE_BASIC = KEYSTONE_BASE + "basic.KeystoneBasic."
KEYSTONE_UTILS = KEYSTONE_BASE + "utils."
class KeystoneBasicTestCase(test.TestCase):
@mock.patch(KEYSTONE_UTILS + "generate_keystone_name")
@mock.patch(KEYSTONE_BASIC + "_user_create")
def test_create_user(self, mock_create, mock_gen_name):
mock_gen_name.return_value = "teeeest"
basic.KeystoneBasic.create_user(name_length=20, password="tttt",
**{"tenant_id": "id"})
mock_create.assert_called_once_with(name_length=20, password="tttt",
**{"tenant_id": "id"})
@mock.patch(KEYSTONE_UTILS + "generate_keystone_name")
@mock.patch(KEYSTONE_BASIC + "_resource_delete")
@mock.patch(KEYSTONE_BASIC + "_user_create")
def test_create_delete_user(self, mock_create, mock_delete, mock_gen_name):
create_result = {}
mock_create.return_value = create_result
mock_gen_name.return_value = "teeeest"
basic.KeystoneBasic.create_delete_user(name_length=30, email="abcd",
**{"enabled": True})
mock_create.assert_called_once_with(name_length=30, email="abcd",
**{"enabled": True})
mock_delete.assert_called_once_with(create_result)

View File

@ -0,0 +1,73 @@
# Copyright 2013: Mirantis Inc.
# 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.scenarios.keystone import utils
from rally import test
from tests import fakes
UTILS = "rally.benchmark.scenarios.keystone.utils."
class KeystoneUtilsTestCase(test.TestCase):
@mock.patch(UTILS + "random.choice")
def test_generate_keystone_name(self, mock_random_choice):
mock_random_choice.return_value = "a"
for length in [10, 20]:
result = utils.generate_keystone_name(length)
self.assertEqual(result, utils.TEMP_TEMPLATE + "a" * length)
def test_is_temporary(self):
tests = [
(fakes.FakeResource(name=utils.TEMP_TEMPLATE + "abc"), True),
(fakes.FakeResource(name="fdaffdafa"), False),
(fakes.FakeResource(name=utils.TEMP_TEMPLATE[:-3] + "agag"), False)
]
for resource, is_valid in tests:
self.assertEqual(utils.is_temporary(resource), is_valid)
class KeystoneScenarioTestCase(test.TestCase):
@mock.patch(UTILS + "KeystoneScenario.admin_clients")
@mock.patch(UTILS + "generate_keystone_name")
def test_user_create(self, mock_gen_name, mock_admin_clients):
name = "abc"
mock_gen_name.return_value = name
user = {}
fake_keystone = fakes.FakeKeystoneClient()
fake_keystone.users.create = mock.MagicMock(return_value=user)
mock_admin_clients.return_value = fake_keystone
result = utils.KeystoneScenario._user_create()
self.assertEqual(user, result)
mock_admin_clients.assert_called_once_with("keystone")
fake_keystone.users.create.assert_called_once_with(name, name,
name + "@rally.me")
def test_user_delete(self):
resource = fakes.FakeResource()
resource.delete = mock.MagicMock()
utils.KeystoneScenario._resource_delete(resource)
resource.delete.assert_called_once_with()

View File

@ -22,8 +22,8 @@ from rally import utils as rally_utils
class FakeResource(object):
def __init__(self, manager=None):
self.name = uuid.uuid4()
def __init__(self, manager=None, name=None):
self.name = name or uuid.uuid4()
self.status = "ACTIVE"
self.manager = manager
self.uuid = uuid.uuid4()