Merge "OSprofiler support"

This commit is contained in:
Jenkins 2017-05-30 12:48:37 +00:00 committed by Gerrit Code Review
commit 6dae6cbe1d
19 changed files with 195 additions and 42 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -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

View File

@ -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]

View File

@ -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)

View File

@ -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")
]}

View File

@ -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})

View File

@ -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):

View File

@ -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]})

View File

@ -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

View File

@ -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"
}
}
}

View File

@ -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):

View File

@ -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")

View File

@ -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": {

View File

@ -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": {

View File

@ -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}
]

View File

@ -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"]}
]

View File

@ -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)

View File

@ -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",

View File

@ -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)]